From f8b0042f2c7e85e634bba61840c0709098571bb0 Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Wed, 28 Aug 2019 13:18:03 -0600 Subject: [PATCH 001/718] Added CHANGELOG v9.0 --- CHANGELOG-9.0.0 | 765 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 765 insertions(+) create mode 100644 CHANGELOG-9.0.0 diff --git a/CHANGELOG-9.0.0 b/CHANGELOG-9.0.0 new file mode 100644 index 00000000000..1b0e8a2cf8d --- /dev/null +++ b/CHANGELOG-9.0.0 @@ -0,0 +1,765 @@ +Changes with Apache Traffic Server 9.0.0 + #3676 - IOBufferChain: initial version + #3693 - register stats in traffic_server if running in standalone mode + #3724 - Unify include paths for headers between core, internal plugins, and external plugins. + #3768 - Autest: Test revalidating cached objects + #3777 - Bump version on master to v9.0.0 + #3819 - Upstream max conn upgrade + #3851 - For atscppapi::AsyncTimer, pass the thread pool for execution to the constructor, … + #3900 - ts/Extendible and AcidPtr classes + #3901 - MemArena: Add make method to construct objects in the arena. + #3907 - IntrusiveDList: Refreshed for C++ eleventy, added const_iterator. + #3913 - Doc: fix build error in traffic_layout documentation. + #3921 - Bug fix in microServer's threading and reorganized some code + #3925 - Enforce sphinx>=1.7.5 when building docs + #3930 - Remove proxy.config.config_dir from records.config + #3941 - Fix RecConfigReadPluginDir and clean up RecCore + #3942 - Doc: Fix build error in Lua plugin documentation. + #3943 - Handle response parsing case where EOF happens before any data arrives. + #3945 - Doc: Tweak to fix doc issues in IntrusiveDList documentation. + #3951 - Fixed broken sphinx version check on MacOS + #3955 - IntrusiveHashMap: Refresh TSHashTable for C++ eleventy. + #3957 - Add generic "guard" class (PostScript) for exception and early function return safety. + #3958 - PROXY Protocol transformed to Forwarded HTTP header + #3963 - TextView: More unit tests about separators and tokens. + #3964 - Fixes spelling + #3965 - Testing: Convert test_History.cc to Catch + #3966 - Add BWF support for SourceLocation. + #3967 - BufferWriter: Add print overloads to FixedBufferWriter + #3968 - Test: Convert test_Regex.cc to Catch. + #3982 - Minor update on README's directory structure + #3992 - TextView: More unit tests. + #3993 - Test: Convert test_Ptr.cc to Catch. + #4003 - Fix another crash on shutdown + #4008 - Add support for 'fwd' value to X-Debug header, and move to later hook any deletion of X-Debug header from client request. + #4020 - Add logic to clean up vios on HttpSM shutdown + #4029 - Replace TSHashTable in server session management with IntrusiveHashMap + #4033 - Removes remnants of dprintf support + #4039 - Enable ECDH explicitly only if OpenSSL version is v1.0.2 or lower + #4042 - Fixed url_sig error when storing base64ed params in penultimate segment. + #4044 - Adjust tests to work with more versions of curl. + #4046 - Collapses LogAccess and LogAccessHttp into LogAccess + #4047 - Improve log entry for http connect result errors + #4049 - Removes carriage returns from MT_hashtable.h + #4050 - Optimize: make NetAccept::init_accept_loop has the logic similar to NetAccept::init_accept_per_thread + #4051 - Doc: Document TSContCall + #4063 - BWF: Add "FirstOf" for better handling of printing alternates for null strings. + #4064 - Runroot: Update test to support different layout + #4067 - Bug fix for timeout test + #4075 - General code cleanup + #4077 - Skip timeout test + #4089 - reenable timeout and change microServer timeout logic + #4095 - Optimize: Assign nh->mutex to new NetVC first and switch to new mutex within UnixNetVC::acceptEvent + #4098 - adding a Mutex to the continuation + #4100 - Doc: Update comments in InkAPI.cc in the header and for member converters. + #4107 - Fixes MacOS linker issue with release build + #4113 - Disables openclose_h2 test. + #4115 - TextView: Add overload for strcasecmp for string_view & TextView. + #4125 - ssl_session_reuse plugin + #4127 - Allows to run Spinx builds on portions of the docs + #4129 - Update IPAllow infrastructure. + #4132 - Completes documentation regarding redirects + #4133 - Disables the double test for inconsistent execution + #4140 - Meta: Add conditional compilation case meta structures. + #4145 - Adds configurable behavior on redirect to loopback + #4146 - Cleanup: remove unused and unimplemented functions from ink_string.h + #4148 - Cleanup: Remove #define INT_TO_BOOL, use local lambda instead. + #4149 - Clang-format: Redo clang-format error that slipped through. + #4163 - Doc: Remove deprecated configs from examples of traffic_ctl + #4168 - YAML: Convert ip_allow.config + #4175 - TextView: Better support for std::string assignment. + #4176 - TextView: Add support for use as "Source" in STL containers. + #4177 - IntrusiveDList: Add ptr_ref_cast to make inheritance easier + #4184 - Update to changelog generation tool to not require milestone to be closed + #4186 - clang-format: Another one that slipped through. + #4187 - Plugins: Cleanup up dependencies on core headers - sslheaders + #4190 - Plugins: Cleanup up dependencies on core headers - authproxy + #4192 - Add exit code checks in clang-format.sh + #4193 - G++ 8.1.1: Fix complaint about lack of storage definitiona for class static constant + #4194 - Remove ssl_cert_loader. Certifier is more complete version. + #4198 - Cleanup, and adds support for new luajit option + #4206 - ts_file: Simple sketch of std::filesystem for internal use. + #4220 - IntrusiveHashMap: Inserts preserve order for equal keys, as with std::multimap + #4221 - IntrusiveHashMap: Fix for find false positive in some cases. + #4226 - HttpSessionManager: Fix potential infinite loop problem. + #4234 - Corrects path to test file in docs + #4240 - Inherited Extendible + #4249 - Test: Convert test_PriorityQueue.cc to Catch + #4257 - Update base version of AuTest to 1.6.0 + #4259 - Corrects typo in argument name + #4260 - Removes logging of secrets + #4261 - Adds a few missing packages needed by autest + #4265 - CMakeLists.txt: Change to be generic and not need updates so often. + #4268 - Test: Convert test_X509HostnameValidator.cc to Catch + #4280 - Fix clang format problems + #4284 - Fixed ts_file test for out of tree builds + #4285 - Change atscppapi::TransformationPlugin to use atscppapi::Continuation instead of TSCont. + #4289 - Do not follow redirects after cache hit + #4290 - Remove unnecessary line in src/Makefile.am + #4300 - Expand the post chunked tests. + #4301 - Fix doc building warnings for recent plugin docs + #4305 - Generally random code cleanup + #4306 - Convert traffic_cache_tool to use ArgParser + #4309 - Orders k-v pairs to avoid making too many files + #4310 - Add warning of body_factory templates are not loaded due to missing dot file + #4324 - Adds Robots exclusion file + #4331 - Make build failures also mark the CA builds as failed + #4332 - Fixes build issues related to Clang Analyzer only + #4334 - Converts ink_autoconf.h to #pragma once + #4337 - Fix Segmentation fault in ShowCache::handleCacheEvent #4328 + #4341 - clang-format + #4346 - TCL: remove tcl depencency from HostLookUp and refresh for C++11 + #4349 - Prevent segment violation in TSContDestroy() when it is called during destruction of statically-allocated objects + #4350 - Fix for ASAN buffer overrun for IpMap::contains in HttpTransact::OSDNSLookup + #4351 - Add some feeble amount of encapsulation to the Thread class. + #4356 - slice plugin, intercept handler that uses cache_range_request + #4357 - TCL: Remove TCL dependency from iocore + #4360 - Fix mysql_remap plugin build with MySQL 8 + #4363 - CMake: Add lib/records, unit_tests. + #4366 - Docs: Remove the EXTERNAL_TYPES logic + #4368 - s3_auth_v4: update default region map + #4374 - TCL: remove TCL dependency from RecHttp + #4384 - Fix gzip(compress) plugin not linked correctly with zlib + #4387 - Replace the overridable lookup with an unordered_map + #4397 - Remove deprecated HTTP/2 metrics + #4398 - Removes the old expander feature of header_rewrite + #4402 - Convert traffic_cache_tool to use ts_file + #4406 - ts_file: Add 'view' method to get a view of the path. + #4411 - Split current client transactions metrics into HTTP/1.1 and HTTP/2 + #4412 - Cachekey plugin doc minor typos fixed. + #4414 - Cleaning up TLS server verify options + #4422 - TCL: Rmove TCL dependency from HostStatus + #4424 - YAML: LibSWOC IntrusiveDList update. + #4426 - YAML: Move ts_meta to external C++ library. + #4427 - Add vconn reenable event + #4430 - TCL: Rmove TCL dependency from UrlRewrite + #4431 - TCL: All ink_hash_table in proxy converted to use STL + #4433 - YAML: LibSWOC upgrade for TextView. + #4434 - YAML: move MemSpan to external C++ library. + #4437 - Adds the log tag cqint for internal requests + #4448 - YAML: TextView upgrade revisited. + #4449 - YAML: Inline BufferWriter formatting functions. + #4450 - Improve BufferWriter logic in HttpTransactHeaders.cc + #4453 - TCL: Code relocation in HttpCompact and HttpBodyFactory for TCL removal + #4454 - CacheTool: Cleanup TS_INLINE. + #4457 - Clean up client certificate specification and add tests + #4459 - Move the test-only plugins test_hooks and test_cppapi to tests/tools/plugins. + #4473 - Cleanup: Replace DynArray with STL vector + #4474 - clang-format + #4478 - Do not attempt clang-analyzer builds on 7.1.x branch + #4486 - Reload records client certs + #4487 - Cleanup: replace multiple HashMap with STL unordered_map + #4496 - Log deletion rewrite + #4497 - Fix chained server cert verify + #4500 - Augment cryptic diag message when log line fails to print + #4501 - Refresh mgmt signal logic to remove possible memory issues. + #4502 - Fix for #4413 - avoid ASAN crash on use after free for file name. + #4512 - Use references for indexes of range-based for loops when this avoids expensive copies. + #4513 - Adding cdnicrit claim support for uri signing service + #4522 - Rewrite TunnelHashMap in modern standard + #4524 - Convert ctx_store in SSLCertLookUp to use STL vector + #4526 - Atomic: Convert ProxyConfig to use std::atomic. + #4527 - Remove FAQ entry claiming that Traffic Server does not support expect-100 + #4531 - Rewrite url after running all remap plugins + #4532 - Remove explicit free of ref-counted object. + #4536 - Minor C++ cleanup for background_fetch + #4540 - URI signing support for JWS to be passed as path parameter + #4542 - TCL: Replace RawHashTable with STL and refactor HttpBodyFactory + #4544 - Updated Dockerfile with some additional dependencies + #4545 - Fix tunnel_route action in ssl_server_name and various test fixes for Fedora 28 and 29 + #4546 - Test: fix failed clang link for test_proxy_http. + #4551 - Fix TLS hooks diagram and other docs cleanup + #4553 - hostdb: Replace the last TSHashTable with IntrusiveHashMap. + #4555 - Test: fix test_Ptr.cc to deal with clang not liking "p1 = p1". + #4564 - Fix duplicate keys in python dict + #4566 - Include additional names of events for debug output. + #4567 - Cleanup: Update Version support to be actual C++ code. + #4570 - MIME: Add string_view based overload for value_get. + #4573 - access_control: reduced some log errs to debug + #4576 - Add Session and SSL hooks to test_hooks Au test. + #4579 - traffic_ctl: Refactor and convert traffic_ctl to use ArgParser + #4580 - Make double_h2 reliably wait for stats to be ready + #4585 - Runroot: make runroot_handler support both ink_args and ArgParser + #4591 - An example of our preferred indentation style + #4596 - Add TS_EVENT_AIO_DONE, remove TS_AIO_EVENT_DONE + #4602 - New ScheduleOn APIs + #4603 - Add cdniip and cdnistd claims to uri signing + #4604 - Repurpose sub claim and add cdniuc support for URI signing + #4606 - TLS Bridge: Fix remap for UA connection, tweak docs for remap support. + #4609 - BWF: Change timestamp global name to be consistent with logging timestamps + #4613 - Runroot: Update verify command and refactor + #4616 - [WEBP] Transform images when a client accepts image/webp. + #4618 - Add case were origin returns 404 to x_remap gold test. + #4627 - Add test and fix regression with disable_h2 option + #4629 - Use LoopTailHandler in UDPNetHandler to support signalActivity + #4630 - Generalize the wild-card fqdn's for user_agent attributes in ssl_server_name + #4641 - Issue #4637: Clean up / unify hex conversions. + #4642 - Issue #4637 - Clean up / unify hex conversions + #4643 - Docs: Fix proxy.config.net.connections_throttle text. + #4645 - Cleanup: Remove Map.h including HashMap, Vec and TSHashTable + #4646 - TCL: Remove TCL from our code base + #4657 - TLS Bridge: Fix error where connect failure lead to a silent timeout. + #4660 - Runroot: Add a new doc on runroot for programs + #4662 - Adds a reasonable rip-grep config file + #4663 - Add back in the option to conf_remap the verify_server settings. + #4666 - Allow empty fqdn in ssl_server_name for unset SNI case. + #4667 - Add forward_route in ssl_server_name + #4668 - Compare servers script for comparing responses from new and old versions of ATS + #4669 - Cleanup: This is just a stylistic cleanup of PR 4531. + #4673 - Avoid the auto-reschedule with dispatchEvent + #4674 - Cleanup: change RemapPlugins::run_single_remap to return bool. + #4675 - TLS Bridge: Add "--file" option to configuration. + #4677 - Remove the ssl wire trace feature. + #4680 - Change serverName member back to const char * to avoid crash. + #4690 - Remove unnecessary TSHandleMLocRelease + #4692 - BWF: Clean up diags log entry header construction. + #4696 - Updates the CI build scripts, adds a new build for HTTP cache-tests + #4698 - Fixes some cache-tests, and make check shouldn't run on build fail + #4703 - Correct the statements within ink_assert and ink_release_assert + #4704 - task threads ready lifecycle hook + #4705 - Eliminate remaining hack around copy CTORs + #4706 - Correction to documentation for TSHttpHookAdd(). + #4707 - Remove the APIHooks::invoke() function. + #4712 - Make client cert overridable + #4715 - Optimize: Avoid meaningless lock operations + #4718 - BWF: Fix handling of null char * - avoid string_view constructor. + #4719 - Add config reload to tls_tunnel test. + #4720 - Fix disable freelist options + #4721 - Optimize: Do not signal EThreads which are not blocked on cond_timedwait + #4722 - Add control for how outbound SNI is selected. + #4723 - Fix documentation on client certificates in ssl_server_name + #4724 - Add shutdown lifecycle hook + #4727 - Remove unused Http2Stream destructor + #4730 - Moved AtomicBit into its own file. + #4734 - Event num ordering + #4738 - Fix typo in HdrHeap + #4746 - Optimize: tighten the logic of the PluginVC::process_read/write_side() + #4747 - Slight clarification to documentation of TLS User Agent Hooks. + #4748 - Tries to enforce .git installation of pre-commit + #4749 - Add more information about event data to 'hook add' API function documentation. + #4750 - Fix spelling errors reported by lintian + #4760 - Updated STATUS with all known releases + #4764 - Adds logging around various config file loads + #4765 - Cleanup: Make _next_round_robin uint64_t + #4767 - Fixes the hook install conditional, Makefile.am is finicky... + #4777 - Add unit tests for the URI signing plugin + #4779 - TLS Bridge: Fix regex compile issue with loading configurations from file. + #4782 - TLS Bridge: Cleanup, fix TSError for more consistency. + #4784 - Remove TSHttpTxnRedirectRequest appears experimental and unused. + #4785 - Bug in traffic_ctl, formatting output for config changes + #4791 - Adds some missing packages to the Dockerfile + #4796 - Autest test extension modification using opensourced testing tools + #4798 - Regex: Clean up constructors. + #4802 - JWT validation uses a token-stripped URI + #4803 - i4637: A tiny bit of cleanup. + #4804 - Regex: update to use string_view. + #4805 - JA3 fingerprint and documentation + #4806 - Add Log fields that dump all MIME headers in a message. + #4809 - Set "Language" of po files under doc/locale/ja/ + #4814 - Add normalization the URI before cdniuc validation in URI Signing + #4815 - Add valid_tls_protocols_in to allow for per-domain protocols. + #4816 - Fix potential unterminated string in logging in state machine. + #4817 - Fix a content issue and a couple format issues. + #4818 - Add log method overload for string_view to LogObject + #4819 - Add clang-format build target to CMake editor file. + #4827 - MIME: Update MIMEField::name_get and MIMEField::value_get to return string_view + #4828 - Removes proxy.config.http.parse.allow_non_http + #4829 - Improves on the ripgrep .rc file + #4831 - Create an autest for the regex_revalidate plugin + #4832 - TextView: add overflow checking to svto_radix. + #4833 - Add test cases to exercise the verify.server* defaults. + #4834 - Change src/tscpp/api/TransformationPlugin.cc to avoid error for -Werror=subobject-linkage . + #4835 - TLS Bridge: Fix possible race condition. + #4836 - Correctly deal with the ssl.client.sni_policy if not set via conf_remap + #4837 - Fix potential instability in cacheIMSRange + #4840 - resolve stack-use-after-scope in YamlLogConfig.cc + #4841 - Do not call dns_result repeatedly for a valid dns result. + #4844 - doc for option -F + #4846 - Fix initialization style. + #4847 - Increase the per test case timeout from 5 to 10 seconds + #4849 - Allow client_cert and client_key to be specified by relative path + #4850 - Cleans up memcached_remap plugin README and code + #4851 - Add IOBufferReader::block_read_view method. + #4855 - Turns off HostDB disk sync by default + #4856 - Changes the return codes to be RecErrT + #4858 - Removes the echo from installing pre-commit + #4862 - Updates uri_signing docs to reflect new RFC changes + #4866 - Remove start_HttpProxyServerBackDoor. + #4869 - Cleanup: remove lib/cppapi from clang-format, it's been moved. + #4870 - Cleanup: Remove "hooks_on" and associated machinery. + #4874 - Avoid ats_malloc in unmarshal + #4878 - Fix a segfault on mac, because of new ScheduleOn APIs + #4879 - Clean up StrHeapDesc constructor. + #4880 - Remove class StrTest, which is not used. + #4886 - Avoid reschedule HostDBContinuation::iterateEvent if there are no more buckets + #4888 - Adjust tests to make them more resilient for different curl versions. + #4889 - Add tsapi Au test. Initially just testing TSHttpTxnEffectiveUrlStringGet() function. + #4895 - URI Signing Strips token from upstream if configured and string buffers are dynamically allocated + #4897 - Uri signing regex as POSIX ERE + #4901 - Update overridable config conversion logic. + #4903 - Adjust connection timeout for TLS + #4909 - Update plugin API type conversions to support enums automatically. + #4910 - Doc: Update HdrHeap documentation for serialization, string inheritance. + #4914 - DFA: Update DFA to use string_view. + #4916 - Optimize: Keep cont->mutex locked, during probe the bucket by hash object within HostDBProcessor::getby + #4917 - Update HdrUtils to be C++17. + #4919 - Shutdown hook should grab the lock if there is one + #4923 - Makes the master triggers works with the 9.x Jenkins Tab name + #4924 - lua plugin: add support for relative path scripts; moves inline script to switch + #4926 - Make mutex lock routines deal with null mutex and general clean up. + #4927 - Cleanup: Convert HTTPHdr::length_get to real method. + #4928 - Pull Age out of the gold test + #4931 - For tls tests look at logs until config has been reloaded + #4933 - Plugin Traffic Dump: new feature for setting limit on disk usage. + #4935 - Use the appropriate length field for uintmax_t + #4938 - Fix client_hello_cb to correctly check for sufficient server_name data + #4940 - ats_scoped_str: c++17 cleanup. + #4941 - Add a case to the tls_client_cert2 to exercise one file with cert and key + #4942 - Load client key event if only the certificate file is specified. + #4948 - MIMEScanner: Make MIMEScanner a class, not a POD with free functions. + #4952 - Cleanup: Tweak for loops to be more consistently C++17 in style. + #4953 - Scalar: add generic rounding. + #4954 - Hdrheap more modernization + #4955 - Marks the YAML exceptions, which gives line number / pos info + #4956 - Fix a ssl handshake crash during shutdown + #4957 - Remove error-prone mirror enum in code handling TS API SSL hooks. + #4960 - Add doc for using relative path to configuration directory for lua sc… + #4961 - Optimize: rewrite getbyname_imm and getSRVbyname_imm as wrappers for getby + #4962 - Remove unnecessary storing of redirect_url in redirect_info + #4964 - Rewrite URL before all remap plugins run + #4965 - HdrHeap: Remove pointless code and misleading comment. + #4966 - Some tidying up of the global namespace. + #4972 - Fix tls_client_verify curl command missing certificate + #4973 - Adjust tls_client_versions to be more resilient for different curl versions + #4974 - Fix tls_check_cert_selection test + #4975 - URL: remove undefined function declaration. + #4976 - Fix tls_forward_nonhttp test requirement + #4979 - Ignore config.cache file + #4982 - Documentation fix to lua plugin + #4986 - Added TS_SSL_CLIENT_HELLO_HOOK and docs + #4988 - Implement nbf claim in Uri Signing Plugin + #5000 - Add Perltidy configuration and build target + #5007 - Build fix: Fix build issue for -O3 on CI. + #5008 - Build: Fix array bounds error under -O3. + #5014 - ink_inet: Fix family string printing, add IpAddr::isAnyAddr. + #5015 - RecHttp.cc unit tests. + #5018 - RecHttp: Convert protocol session pool to use views and MemArena. + #5021 - Frees up disk_vols when volume creation failed + #5029 - Removing Lazy Buf Alloc from H1 Server session + #5030 - IpMap: Add move constructor. + #5032 - Cleanup loading certs from ssl_multicert.config + #5033 - Cleanup: use string_view for ssl_multicert.config field tags + #5034 - Implement aud claim in Uri Signing Plugin + #5035 - Overload ProcessManager::signalManager for string_view + #5038 - Cleanup: remove duplicated SSL_CTX_set_tlsext_status_cb calls for OCSP Stapling + #5039 - Add BufferWriter formatting support to IpMap + #5041 - Cleanup: Set SSL_OP_NO_TICKET in SSLInitServerContext() + #5044 - Fixed memory leaking introduced by 4873 + #5046 - Cleanup: Separate SSLStats and SSLDiags from SSLUtils + #5050 - Set thread affinity using type info + #5051 - Restructured SSL client context mapping to 2-level + #5053 - Fixed compiler error with std::string_view + #5054 - Cleanup: Separate TLS SessionTicket from SSLUtils + #5058 - Fixed use after free when running regression under ASAN + #5059 - Add Assertion when fragment_size is large than MAX_FRAG_SIZE + #5060 - IP support: Make IpAddr constexpr constructible, define min/max addresses in IpMap + #5065 - RemapPluginInfo Refresh. + #5068 - HdrHeap default size unit test fix. + #5069 - url_sig: fixed unit-test for remapped url. + #5070 - Ignore test_librecords + #5074 - Move minimum OpenSSL version to 1.0.2 + #5075 - Fixed the compatibility with previous cache verison + #5077 - Unify plugins hook dispatch + #5078 - Fix directives for checking TS_USE_TLS_OCSP + #5079 - Fix directives for checking TS_HAS_TESTS + #5082 - Add support for the lua and numeric log roll values + #5086 - Remove extra args to bwprint in SSLConfigParams::getCTX() + #5088 - MIME: Fix line_is_real false positive. + #5089 - Slight adjust to the thread affinity logic + #5091 - Override delete in Extendible + #5112 - uri_signing build helpers + #5113 - Fix #5094: Fix use after free in test_IntrusiveHashMap.cc + #5114 - Fix #5093: new/delete mismatch in test_IntrusivePtr.cc + #5115 - Remove OS dependency in test_BufferWriterFormat.cc + #5120 - Ensure queued HostDB requests get rescheduled back to the original thread + #5122 - fix crash in CacheVC::openReadFromWriter + #5123 - Fix SessionProtocolNameRegistry lookup + #5126 - -H "xdebug: probe" injects trace of headers into response body + #5128 - Change url_mapping::toUrl to url_mapping::toURL + #5129 - Fixed memory leaks in test_IntrusiveHashMap + #5131 - Do not run clang-format for @default_stack_size@ + #5132 - Fix for() loop, correctly calculate the value of seg_in_use within Vol::dir_check() + #5136 - Fixes some places where refactoring was not complete + #5138 - Run clang-format against the same files on both make clang-foramt and git pre-hook + #5139 - Add virtual destructor to SSLMultiCertConfigLoader. + #5140 - cdniuc is not a manditory claim + #5141 - Need to pop messages from queue + #5142 - UrlRewrite: separate constructor and configuration loading for testability + #5144 - Fix AcidPtr test + #5150 - Augment wildcard_match to allow underscore in domain name + #5151 - Updates to the STATUS file + #5152 - Test acid ptr persistence + #5153 - Separate P_SSLUtil and P_SSLClientUtils includes + #5157 - Set the block's m_water_level in Arena:free even if the block is not the last block + #5167 - Fix Makefile.am to run clang-tidy + #5172 - Run clang-tidy one by one + #5174 - Adds Cache test suits + #5176 - Adds a new log tag for the MPTCP state of a connection + #5180 - Regex name checks on ssl_server_name should be anchored. + #5181 - Ignore check programs + #5182 - Ran clang-tidy + #5183 - Do not run clang-tidy on lib/yamlcpp/ + #5184 - traffic_via.pl: Fixed bugs, added tests, and make the output match more like traffic_via + #5185 - The response header of CONNECT should not have content-length or chun… + #5186 - Ran clang-tidy with modernize-use-default-member-init + #5187 - Use pthread_cancel to terminate plugin threads + #5192 - Exclude library headers from clang-tidy + #5193 - Suppress false positive of clang-tidy on macOS + #5194 - Check return value + #5199 - autest for slice plugin + #5201 - Replace EThread::has_event_loop with EThread::tt == REGULAR + #5204 - Moved unit test suppression file and updated it + #5205 - Adding a note into storage.config admin doc about cache invalidation … + #5208 - Adds a little wrapper script to build inside vscode + #5211 - Check return value of open + #5212 - Cache:ttl-in-cache should always override never-cache + #5214 - Ran CPP check on a few files while prodding around + #5215 - Fix compile problems with PR-5211 (hiredis autoconf) + #5216 - Fix the hiredis autoconf for the default case + #5219 - url_sig debug fix for when url is missing the signature query string + #5222 - Fix mysql-remap compilation error + #5228 - Implement prefetched OCSP stapling responses + #5239 - Adds basic version feature for traffic_layout info + #5240 - Setting the correct directory for test_Cache + #5241 - Changed how current age is determined to age out documents + #5247 - Fixed cache test, using updated shutdown + #5252 - Make host status persistent across restarts + #5255 - Remove unused variable in cache test + #5258 - Adds cache alternate update tests + #5259 - Fixed cache RWW test crash + #5261 - Fixed pthread mutex init issue with cache test + #5262 - JA3 fingerprint: Corrected usage of OpenSSL API for ec and ecpf list retrieval. + #5264 - Fix reason tag of traffic_ctl host + #5265 - Fix IntrusiveHashMap active bucket list corruption issue during expansion. + #5266 - Ignore unsupported HTTP/2 settings parameters + #5267 - Slice errorlog + #5268 - fix If-None-Match and If-Modified-Since priority problem + #5269 - Cleanup: Use internal linkage for functions which are only needed in SSLUtils.cc + #5274 - Fix HostDBReverseTest sa_family initialization. + #5275 - Fix false collapsing of reverse DNS requests. + #5277 - Tries to use linux specific tcpinfo fields + #5278 - Fixes the Brotli build issues + #5281 - Change Au test condition for minimal OpenSSL version to use traffic_layout info --versions + #5282 - Plugin reload + #5286 - Update README.md + #5289 - Don't read frames after sending GOAWAY with an error code + #5290 - MIMEScanner: Only clear scanner line buffer if at MIME_PARSE_BEFORE state + #5292 - Fix a build error in xdebug on macos + #5297 - Doc: fix proxy.config.cache.ram_cache.algorithm description + #5301 - Slice Plugin: add options for disabling or pacing detailed block stitch error logging. + #5302 - Correct config name for proxy.config.dns.connection_mode + #5305 - Throttling results in tight loop if there are no new connections + #5306 - Removes priorities for AIOs, thanks oknet + #5307 - correctly handle return value 0 from recv() + #5308 - cppcheck: Changed from C casting to C++ casting + #5309 - Removes non-existent include dir reference + #5310 - Cppcheck fix for iocore/dns + #5311 - cppcheck: change to C++ style pointer casting + #5312 - cppcheck: Minimize variable scopes and use different names to not shadow others + #5313 - cppcheck: Reduce the scope of the variable 'out_buf' + #5314 - cppcheck fixes for iocore/hostdb + #5315 - cppcheck: Fixed various issues with SSL files + #5316 - cppcheck: Removed problematic move operators for FixedBufferWriter. + #5317 - cppcheck: Fix various issues of Http2DependencyTree + #5318 - cppcheck: Fixes various issues under proxy/http/remap + #5320 - Added user defined conversion operator in ConstBuffer for string_view. + #5321 - cppcheck: Use initialization list instead of assigning in constructor body + #5322 - cppcheck: fixes issues found for tests in proxy/http + #5323 - cppcheck: fixes issues found for plugins/compress + #5324 - cppcheck: Change to C++ style pointer casting + #5325 - cppcheck: fix issue found in BufferWriterFormat.cc + #5326 - cppcheck: fixes issue found in proxy/IPAllow.cc + #5327 - cppcheck: Fixes issue found in DiagsConfig.cc + #5328 - cppcheck: fixes issues found for plugins/authproxy + #5329 - Fixes clang-analyzer error dereferencing nullptr in parent + #5330 - cppcheck: Fix various issues of Http2ConnectionState + #5331 - Off by 1 error in memcpy of redirect url + #5333 - cppcheck: Reduces variable scope for files in mgmt/... + #5334 - cppcheck: fixes issues in ink_uuid.h + #5335 - cppcheck: Change to C++ style pointer casting in Thread.cc + #5336 - cppcheck: Fixes issues found in async_http_fetch_streaming + #5337 - cppcheck: Reduce the scope of the variable 'netvc' + #5338 - cppcheck: fixes issues found in proxy/logging + #5339 - cppcheck: fixes issues found for plugins/background_fetch + #5340 - cppcheck: fixes issues found in example/thread_pool + #5344 - cppcheck: Remove an unused private function + #5345 - cppcheck: minimize variable scopes + #5346 - cppcheck: fixes issues found in example/protocol + #5347 - cppcheck: fixes issues fround in example/remap + #5348 - Don't assign if this and other are the same object + #5349 - cppcheck: Fix issues in P_UDPx.h + #5351 - cppcheck: fixes issues in example/ + #5353 - Remove log collation + #5354 - Password can not be nullptr here, so don't check + #5355 - Revert TS-374 to avoid deadlocks + #5362 - fix 3939 collision + #5365 - cppcheck: fix comparison issues found in plugins + #5366 - Adds assert, albeit not needed, makes CA happy + #5368 - Don't use the object after tests finishes and object is deleted + #5370 - Fixed clang-analyzer issues in cookie_remap + #5373 - Clang Analyzer: Fix IpMap.cc false positives. + #5374 - cppcheck: Fix various issues in proxy/http2/ + #5375 - cppcheck: Fix issues found in I_IOBuffer.h + #5376 - cppcheck: Fix various issues found in iocore/eventsystem + #5380 - Fixes spelling in src + #5381 - fixes spelling in include + #5382 - Fixes spelling in iocore + #5383 - Remove commented out includes + #5384 - Removes unreferenced, unused bits of code + #5387 - Fixes typos in various documentation files + #5388 - De-tabifies REVIEWERS + #5390 - Fixes logging after collation removal + #5392 - ssl_session_resuse: operator for redis endpoint compare functor must be const + #5396 - Rewrite the assert statement to avoid Socks Proxy triggering the assertions + #5398 - Load the Socks configuration after the host state persistence data is loaded + #5399 - Removes code related to removed configuration + #5400 - Fixes spelling in mgmt + #5401 - Fixes spelling in miscellaneous files + #5402 - Spelling fixes in plugins + #5403 - Fixes the number of traversal events + #5404 - Tries to make builds on older clang happy + #5411 - Update README.md + #5413 - TS C++ API: add member function TSSslConnection InterceptPlugin::getSslConnection() + #5414 - Add API and fix logic for TS_SSL_VERIFY_*_HOOK. + #5415 - MemSpan: Update to templated style, fix gcc9 compile error. + #5416 - Move setsockopt from UnixNetProcessor to Server::setup_fd_for_listen + #5417 - Change HostStatus to use only one stat per host. + #5420 - Adds update header only test case + #5421 - Check nullptr before call netvc->do_io_close in SSLNextProtocolAccept::mainEvent + #5423 - This fixes parsing where the [ ] section gets merged into values + #5424 - Fix ContFlags for gcc 9. + #5425 - Updates the VSCode include dirs + #5427 - gcc9 - fix class Connection. + #5428 - gcc9 - fix CryptoHash.h + #5431 - New APIs: Server/ClientCertUpdate + #5433 - gcc9 - Fix Errata.h, NumericType.h. + #5434 - gcc9 - Fix I_Store.h + #5435 - gcc9 - fix HTTPVersion. + #5436 - Additional places to propagate the per-client-ip debug tags. + #5438 - Add wait_for_cache to make all_headers test more resilient + #5439 - Removes unused TSConfig usage in ssl_sni example + #5440 - Removes unused TSConfig usage in ssl_sni_whitelist example + #5441 - Improve test resilience by waiting for TS ports to be ready. + #5442 - Removes unused TSConfig usage in verify_cert example + #5443 - Address intermittent failures of all_headers Au test (see Issue # 5437). + #5445 - Rewrite SocksProxy based on states + #5446 - Fixes use-after-free in PVCTestDriver::start_tests + #5447 - Fixed nullptr check in cookie remap + #5448 - Fixed syntax issue with clang + #5451 - Fix FREELIST macros for AArch64 + #5452 - Clang Analyzer: Fix IpMap.cc false positives. #2 + #5455 - Convert ssl_preaccept plugin to use command-line arguments + #5456 - Fixes spelling in doc + #5458 - Updates the Docker image with latest dependencies + #5460 - Fixed clang-analyzer issue calling schedule_imm with the continuation possibly being a nullptr + #5462 - gcc9: fixed issue with always printing a null char* + #5463 - clang-analyzer: Fixed err value being uninitialized + #5464 - clang-analyzer: Fix API test logic and fixed clang-analyzer issue + #5465 - Separate out common header compression logic to hdrs directory + #5466 - Set HTTP version on server side header conversion + #5467 - Add be32toh and htobe32 for macOS + #5470 - Changes traffic_wccp to use YAML as configuration format + #5472 - gcc9: Added default assignment operator + #5475 - Cleanup alarms and signals + #5477 - Removes proxy.config.http.server_tcp_init_cwnd + #5478 - Fixes some cache-tests build issues + #5480 - Add HKDF wrapper + #5482 - Document proxy.config.ssl.server.honor_cipher_order + #5489 - gcc9: set default value for printing debug message + #5490 - clang-analyzer: Fix uninitialized variable in make_to_lower_case. + #5492 - clang-analyzer: fix bogus use after free with Ptr in LogFieldInt constructor. + #5495 - Correct the clear range when cache restart + #5497 - gcc9: sprintf and strncat fixes in plugins + #5500 - Added Docker support for Fedora 29 and Fedora 30 + #5502 - This is already documented in the proper traffic_ctl page + #5507 - AcidPtr: Tweaks tests to be a bit more robust. + #5508 - Grab lock before invoke + #5509 - clang analzyer - fix false positive in Vol::handle_recover_from_data. + #5510 - TextView: clean up on strcasecmp, strcmp, and memcmp. + #5516 - Make code compilable with BoringSSL + #5518 - Adds a missing dependency, bump autest version + #5520 - Cleanup of autest prog checks, and indentation + #5521 - Check for OpenSSSL v1.1.1, for now, for this test + #5524 - clang analyzer: Fix false positive "use after free" in IpMap.cc + #5525 - clang analyzer: suppress nullptr derefence report in mime_hdr_sanity_check + #5526 - Remove f_callback_on_accept + #5528 - Allow number of settings per H2 session to be configurable + #5529 - clang analyzer: Suppress nullptr dereference error in SSLNetVConnection::update_rbio + #5530 - Removes disable_configuration_modification, making it always on + #5533 - Move logging config under toplevel YAML tag 'logging' + #5536 - More fixes and cleanup of CI scripts + #5537 - Fixed an ownership issue in autest + #5543 - Added loop detection via code and squid logging code + #5544 - Add an ignore_self_detect flag to parent.config so that the local cache host may be a member of a peering cache group. + #5547 - Make sure autest has all minimal config files + #5551 - Fix test to not break on custom layouts + #5552 - Add options to sort to reduce os differences in all_headers test + #5554 - Updates Dockerfile, and adds a comment to autest bootstrap + #5555 - Ran clang-tidy with google-readability-casting + #5556 - Minor wording changes in ssl_server_name.yaml docs + #5557 - Removes empty config load warning for YAML-based configuration files + #5558 - Removed headers that don't exist in the dir to fix clang-tidy + #5559 - Move sni config (formerly ssl_server_name) under toplevel YAML tag 'sni' + #5560 - Added pipenv config script for AuTest + #5561 - Check DH_get_2048_256() should inclue + #5565 - Add cstdio in TextBuffer for vsnprintf + #5568 - Proxy txn cleanup + #5569 - New API: TSSslClientContextsNamesGet and TSSslClientContextFindByName + #5570 - Clean up: Remove proxy.config.http.parent_proxy_routing_enable variable + #5571 - Removes the abort() from header_rewrite, and try to deal with errors + #5574 - Fix ParentSelection regression/unit tests. + #5575 - Fix order a little bit, based on F30 availability + #5579 - JA3 plugin: Fix ja3 hooks for openssl 1.0.2 + #5582 - Preserve ticket key data specified by TSSslTicketKeyUpdate. + #5585 - Do not change stream state from HALF_CLOSED_REMOTE with CONTINUATION frame + #5586 - Ignore Pipfile.lock file + #5588 - Update UDPNet for QUIC + #5589 - Adds support for set-destination SCHEME/URL to take string expansions + #5591 - Replace ProxyTransaction::get_parent()/set_parent() with get_proxy_ssn()/set_proxy_ssn() + #5592 - Fix a type mismatch in client_context_dump plugin + #5597 - Added CurlHeader tester to test curl output + #5598 - Use type info to assign an affinity thread + #5599 - Renames ssl_server_name.yaml to sni.yaml + #5600 - Use IPPROTO_TCP instead of SOL_TCP for macOS compatibility + #5603 - Eliminates most of the Rollback code, and things interacting with it + #5605 - Fix crash in MIMEScanner::append with std::string. + #5606 - Turns off TLS v1.0 and TLS v1.1 by default + #5607 - slice/HttpHeader memleak fix TSMLoc release call + #5608 - Removes the remaining code and configurations for SSL3 + #5609 - Added cert_reporting_tool plugin based off example/client_context_dump + #5610 - Removes the explicit Vary configurations and code + #5613 - Doc: Add documentation for HTTP/2 statistics + #5614 - Add Pipfile for building docs + #5615 - Separate stubs for libinknet from test_I_UDPNet.cc + #5616 - Updates README to reflect current source tree layout + #5617 - Moves Errata to tscore, removes everything else from tsconfig + #5623 - This RSB is no longer used at all, so remove + #5625 - Re-enable the disjoint-wait-for-cache Au test + #5627 - Elevate privs to load TLS Session Ticket Key file + #5628 - Allows for resizing librecords via command line option + #5631 - Removes checks for curl that snuck back into the tests + #5632 - Fix up remaining references to ssl_server_name.yaml + #5633 - HTTP/2: increment write_vio.ndone by consumed size + #5634 - HTTP/2: cancel reading buffer when ATS received GOAWAY + #5636 - HTTP/2: ignore unknown settings + #5637 - TextView: Fix bug in rtrim_if when entire view is cleared. + #5639 - update example directory structure and add examples for lua plugin + #5640 - Add reference to ts.client_request.get_pristine_url() in lua plugin + #5643 - Cleanup debug log in mime_hdr_describe + #5645 - Fix default logging.yaml with new format. + #5647 - Replaces Emergency() with Error() when parsing these records.config values + #5648 - Add metrics to track SSLv3 and TLS versions + #5649 - TS API - Adds the TSHttpTxnNextHopNameGet() function. + #5651 - TS autest extension can now auto select both ssl and nonssl port + #5653 - cookie_remap plugin Au test case changes for compatibility with PR 4964. + #5654 - Fix the number of net_connections_currently_open_stat error increase + #5656 - Reenable redirect_actions Au test as it is working now. + #5658 - New API: TSEmergency and TSFatal + #5659 - Fix options processing for ja3_fingerprint plugin + #5660 - Auto port selection for more autests + #5664 - Update MT_Hashtable interface to use smart pointer + #5666 - Program to test if multiple URLs can be cached and generates a report on the cache headers + #5667 - Combohandler: Set response as private if one of the origin responses is private + #5668 - TSIOBufferReaderCopy: copy data from a reader to a fixed buffer. + #5669 - Added end pointer to ink_atoi64 and used when parsing cache size + #5670 - Convert HdrHeap regression test into unit test using Catch + #5673 - Add ats_unique_buf + #5674 - This fixes state machine looping when using upstream connection throttling with parent selection + #5676 - Log H2 errors with the codes + #5678 - More Autest ports cleanup + #5680 - HTTP/2 - tweak for better field name handling. + #5683 - Cleanup example directory + #5685 - Fix typo in lua plugin documentation + #5686 - Reverse internal order of HPACK Dynamic Table Entries + #5690 - Fix race condition in test + #5697 - Coalesce empty objects in HdrHeap + #5698 - Remove unused LibBulkIO + #5699 - Remove unused header file ink_inout.h + #5700 - Options to roll empty logs and log trimming + #5701 - fix If-Match and If-Unmodified-Since priority problem + #5703 - Fix indents in HttpTunnel.cc made by unifdef LAZY_BUF_ALLOC + #5704 - Add dest addr information to incoming UDPPacket objects + #5705 - Make TSVConnInacitivityTimeoutCancel work as expected. + #5706 - Add optional normalization of scheme and host to lower case letters in effective URLs. + #5707 - JA3: append to the last dub if X-JA3-Sig/X-JA3-RAW exist + #5710 - Convert regression tests for XPACK into Catch based unit tests + #5711 - Fix client transaction stats + #5714 - Add a required library to "Getting Started" docs + #5715 - Sets macOS luajit linker flags only when luajit detected + #5716 - Fixes memory leak in traffic_crashlog + #5717 - Change default proxy name to be "traffic_server", not the build machine. + #5721 - Fixes autodetect of brotli + #5722 - In test_hooks Au test case, add work-around for flakeyness of VCONN start/close events. + #5723 - Update docs to document wipe_field_action that we use in production + #5724 - Enable logging of the Elliptic Curve used to communicate with the client + #5728 - Remove header_rewrite conditions deprecated in previous versions + #5730 - Cleanup and link references to sni.yaml + #5731 - Use un-deprecated records for SSL server verification + #5732 - Remove proxy.config.http.cache.allow_empty_doc + #5733 - Fix typos in log.gold file for tsapi Au test case in merged PR 5706. + #5736 - Adds voluspa - a configuration generator + #5738 - Plugins ready for Promotion (as discussed) + #5739 - Removes the various plugins as agreed upon in Beijing + #5740 - Fixes spelling in lib/records + #5745 - Cleanup debug logs around SSLWriteBuffer + #5746 - Remove unnecesary function name on debug logs in SSLNetVConnection + #5747 - Add slow logs for HTTP/2 Connection & Stream + #5748 - cppcheck: fixed uninitialized variable and scoping in healthchecks + #5749 - cppcheck: fixed leak and scoping in ts::file::copy + #5750 - Preserve the raw log fields when wiping using case insensitive contains and update container log fields + #5751 - Add soft limit for HTTP Request URI and Header field length. + #5752 - fixed datatype in example plugin + #5753 - Add QUIC draft-20 support + #5755 - Initialize EventIO + #5756 - Minor typo in CONTRIBUTING.md + #5762 - Limit resources used by regex_remap to prevent crashes on stack overflow + #5765 - Avoid a clang warning when all the defines are set + #5766 - Record HttpSM Id on new transaction + #5767 - Issue 3654 addr based loop detection + #5769 - Simplify h2 enable disable + #5770 - IPAllow: change top level key to "ip_allow". + #5771 - Fixes linker changes for luajit on macOS + #5772 - Remove ssl_error stats that aren't really errors. + #5773 - Documentation for Autest in Sphinx + #5778 - Issue 5604 - fix memory leaks for http parser. + #5779 - doc: TSL used instead of TLS in Japanese docs + #5780 - Fixed std::array initialization for older compilers + #5785 - Allocate DependencyTree only if HTTP/2 stream priority is enabled + #5786 - Mark debug logs of polling as verbose + #5789 - Add protection against null pointer access + #5792 - Rename remaining references to ip_allow.config to ip_allow.yaml + #5797 - Remove double call of the SNI action on TLS accept. + #5800 - Doc: fix manpage error which causes Makefile problem. + #5803 - Make TS_NULL_MLOC a valid C compile-time constant. + #5806 - More doc spelling fixes + #5808 - Remove unused assignment to satisfy clang-analyzer + #5813 - Fixes broken links to documentation + #5815 - Updates links to trafficserver.apache.org to https + #5817 - Fixes various issues found in docs + #5819 - make check race condition fix + #5821 - HTTP/2 rate limiting + #5823 - Avoid AWS auth v4 path/query param double encoding + #5824 - Reactivate active timeout enforcement + #5825 - Cleanup: Remove unused function & old comments + #5826 - Cleanup: Signal READ_READY event only if the buffer is readable + #5827 - compress plugin: document undocumented options + #5828 - Make client_context_dump test resilient to dump order changes + #5830 - Make proxy.config.http.per_server.min_keep_alive_connections overridable + #5831 - Fix QUIC build + #5833 - Fix H2 internal counters + #5834 - Ran clang-tidy before 9.0.x branching + #5839 - Fix inactivity timeout on QUIC + #5841 - Cleanup: unifdef WRITE_AND_TRANSFER + #5844 - Explain how SRV origin selection works + #5847 - Cleanup: Remove unused empty files + #5856 - Fixes 'traffic_ctl server restart' to restart From 24daee0b63fab4ca43501bf3c304de06bc5da6b3 Mon Sep 17 00:00:00 2001 From: Susan Hinrichs Date: Fri, 9 Aug 2019 20:27:49 +0000 Subject: [PATCH 002/718] Fix no_activity timeout for server session reuse. (cherry picked from commit 924c8f9f70a9d30d70f4b130a43af82b79c90eda) --- proxy/http/HttpSM.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc index 523feec90cf..346eab562f7 100644 --- a/proxy/http/HttpSM.cc +++ b/proxy/http/HttpSM.cc @@ -5975,6 +5975,13 @@ HttpSM::setup_server_send_request() milestones[TS_MILESTONE_SERVER_BEGIN_WRITE] = Thread::get_hrtime(); server_entry->write_vio = server_entry->vc->do_io_write(this, hdr_length, buf_start); + + // Make sure the VC is using correct timeouts. We may be reusing a previously used server session + if (t_state.api_txn_no_activity_timeout_value != -1) { + server_session->get_netvc()->set_inactivity_timeout(HRTIME_MSECONDS(t_state.api_txn_no_activity_timeout_value)); + } else { + server_session->get_netvc()->set_inactivity_timeout(HRTIME_SECONDS(t_state.txn_conf->transaction_no_activity_timeout_out)); + } } void From 3c93d86f48182b4defbe2d1b5dd0d42fa577e244 Mon Sep 17 00:00:00 2001 From: Zizhong Zhang Date: Tue, 20 Aug 2019 18:18:56 -0700 Subject: [PATCH 003/718] correct the size of DNS buffers (cherry picked from commit 1b98e7f4c786a0a1ff675e95d23a59ecd6a852c2) --- iocore/dns/DNS.cc | 12 ++++++------ iocore/dns/I_DNSProcessor.h | 19 ++++++++++--------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/iocore/dns/DNS.cc b/iocore/dns/DNS.cc index 7a7df3b6a36..8d91744c8dc 100644 --- a/iocore/dns/DNS.cc +++ b/iocore/dns/DNS.cc @@ -597,7 +597,7 @@ static inline int _ink_res_mkquery(ink_res_state res, char *qname, int qtype, unsigned char *buffer, bool over_tcp = false) { int offset = over_tcp ? tcp_data_length_offset : 0; - int r = ink_res_mkquery(res, QUERY, qname, C_IN, qtype, nullptr, 0, nullptr, buffer + offset, MAX_DNS_PACKET_LEN); + int r = ink_res_mkquery(res, QUERY, qname, C_IN, qtype, nullptr, 0, nullptr, buffer + offset, MAX_DNS_REQUEST_LEN - offset); if (over_tcp) { NS_PUT16(r, buffer); } @@ -629,7 +629,7 @@ DNSHandler::retry_named(int ndx, ink_hrtime t, bool reopen) } bool over_tcp = dns_conn_mode == DNS_CONN_MODE::TCP_ONLY; int con_fd = over_tcp ? tcpcon[ndx].fd : udpcon[ndx].fd; - unsigned char buffer[MAX_DNS_PACKET_LEN]; + unsigned char buffer[MAX_DNS_REQUEST_LEN]; Debug("dns", "trying to resolve '%s' from DNS connection, ndx %d", try_server_names[try_servers], ndx); int r = _ink_res_mkquery(m_res, try_server_names[try_servers], T_A, buffer, over_tcp); try_servers = (try_servers + 1) % countof(try_server_names); @@ -650,7 +650,7 @@ DNSHandler::try_primary_named(bool reopen) open_cons(&ip.sa, true, 0); } if ((t - last_primary_retry) > DNS_PRIMARY_RETRY_PERIOD) { - unsigned char buffer[MAX_DNS_PACKET_LEN]; + unsigned char buffer[MAX_DNS_REQUEST_LEN]; bool over_tcp = dns_conn_mode == DNS_CONN_MODE::TCP_ONLY; int con_fd = over_tcp ? tcpcon[0].fd : udpcon[0].fd; last_primary_retry = t; @@ -824,7 +824,7 @@ DNSHandler::recv_dns(int /* event ATS_UNUSED */, Event * /* e ATS_UNUSED */) goto Lerror; } dnsc->tcp_data.total_length = ntohs(dnsc->tcp_data.total_length); - if (res != sizeof(dnsc->tcp_data.total_length) || dnsc->tcp_data.total_length > MAX_DNS_PACKET_LEN) { + if (res != sizeof(dnsc->tcp_data.total_length)) { goto Lerror; } } @@ -852,7 +852,7 @@ DNSHandler::recv_dns(int /* event ATS_UNUSED */, Event * /* e ATS_UNUSED */) hostent_cache = dnsBufAllocator.alloc(); } - res = socketManager.recvfrom(dnsc->fd, hostent_cache->buf, MAX_DNS_PACKET_LEN, 0, &from_ip.sa, &from_length); + res = socketManager.recvfrom(dnsc->fd, hostent_cache->buf, MAX_DNS_RESPONSE_LEN, 0, &from_ip.sa, &from_length); Debug("dns", "DNSHandler::recv_dns res = [%d]", res); if (res == -EAGAIN) { break; @@ -1092,7 +1092,7 @@ static bool write_dns_event(DNSHandler *h, DNSEntry *e, bool over_tcp) { ProxyMutex *mutex = h->mutex.get(); - unsigned char buffer[MAX_DNS_PACKET_LEN]; + unsigned char buffer[MAX_DNS_REQUEST_LEN]; int offset = over_tcp ? tcp_data_length_offset : 0; HEADER *header = reinterpret_cast
(buffer + offset); int r = 0; diff --git a/iocore/dns/I_DNSProcessor.h b/iocore/dns/I_DNSProcessor.h index a0ec65115eb..83f4bd230b1 100644 --- a/iocore/dns/I_DNSProcessor.h +++ b/iocore/dns/I_DNSProcessor.h @@ -28,11 +28,12 @@ const int DOMAIN_SERVICE_PORT = NAMESERVER_PORT; const int DEFAULT_DOMAIN_NAME_SERVER = 0; -const int MAX_DNS_PACKET_LEN = 8192; -const int DNS_RR_MAX_COUNT = (MAX_DNS_PACKET_LEN - HFIXEDSZ + RRFIXEDSZ - 1) / RRFIXEDSZ; -const int DNS_MAX_ALIASES = DNS_RR_MAX_COUNT; -const int DNS_MAX_ADDRS = DNS_RR_MAX_COUNT; -const int DNS_HOSTBUF_SIZE = MAX_DNS_PACKET_LEN; +const int MAX_DNS_REQUEST_LEN = NS_PACKETSZ; +const int MAX_DNS_RESPONSE_LEN = 65536; +const int DNS_RR_MAX_COUNT = (MAX_DNS_RESPONSE_LEN - HFIXEDSZ + RRFIXEDSZ - 1) / RRFIXEDSZ; +const int DNS_MAX_ALIASES = DNS_RR_MAX_COUNT; +const int DNS_MAX_ADDRS = DNS_RR_MAX_COUNT; +const int DNS_HOSTBUF_SIZE = MAX_DNS_RESPONSE_LEN; /** All buffering required to handle a DNS receipt. For asynchronous DNS, @@ -41,10 +42,10 @@ const int DNS_HOSTBUF_SIZE = MAX_DNS_PACKET_LEN; */ struct HostEnt : RefCountObj { - struct hostent ent = {.h_name = nullptr, .h_aliases = nullptr, .h_addrtype = 0, .h_length = 0, .h_addr_list = nullptr}; - uint32_t ttl = 0; - int packet_size = 0; - char buf[MAX_DNS_PACKET_LEN] = {0}; + struct hostent ent = {.h_name = nullptr, .h_aliases = nullptr, .h_addrtype = 0, .h_length = 0, .h_addr_list = nullptr}; + uint32_t ttl = 0; + int packet_size = 0; + char buf[MAX_DNS_RESPONSE_LEN] = {0}; u_char *host_aliases[DNS_MAX_ALIASES] = {nullptr}; u_char *h_addr_ptrs[DNS_MAX_ADDRS + 1] = {nullptr}; u_char hostbuf[DNS_HOSTBUF_SIZE] = {0}; From 5d5d4cc288e2101ae3987b4070f93bd41713c4b0 Mon Sep 17 00:00:00 2001 From: Gancho Tenev Date: Wed, 21 Aug 2019 16:11:48 -0700 Subject: [PATCH 004/718] cachekey: added --canonical-prefix parameter In certain use-cases when calculating the prefix (the initial value of the new cache key) we need to have the scheme, host and port in their original form from the request URI, i.e. when hosting.config is used the cache key is expected to contain a valid URI authority element used for volume selection. More details about the new parameter and its functionality can be found in doc/admin-guide/plugins/cachekey.en.rst (cherry picked from commit 0f86efc7678248c09f87ec8b99bc026456edc3f7) --- doc/admin-guide/plugins/cachekey.en.rst | 21 ++++-- plugins/cachekey/cachekey.cc | 90 ++++++++++++++++++------- plugins/cachekey/cachekey.h | 3 +- plugins/cachekey/configs.cc | 11 +++ plugins/cachekey/configs.h | 6 ++ plugins/cachekey/plugin.cc | 2 +- 6 files changed, 102 insertions(+), 31 deletions(-) diff --git a/doc/admin-guide/plugins/cachekey.en.rst b/doc/admin-guide/plugins/cachekey.en.rst index 5342d8b52b8..51f4ef174a8 100644 --- a/doc/admin-guide/plugins/cachekey.en.rst +++ b/doc/admin-guide/plugins/cachekey.en.rst @@ -70,20 +70,29 @@ Cache key structure and related plugin parameters :: - Optional components | ┌─────────────────┬──────────────────┬──────────────────────┐ + Optional components | ┌─────────────────┬────────────── ───┬──────────────────────┐ (included in this order) | │ --static-prefix | --capture-prefix │ --capture-prefix-uri │ | ├─────────────────┴──────────────────┴──────────────────────┤ - Default values if no | │ /host/port | + Default values if no | │ /host/port or scheme://host:port (see the table below) | optional components | └───────────────────────────────────────────────────────────┘ configured | + ┌────────────────────┬─────────────────────────┬──────────────────────┐ + │ --canonical-prefix | default value if no │ input used for │ + │ | prefix parameters used │ --capture-prefix │ + ├────────────────────┴─────────────────────────┴──────────────────────┤ + │ fasle | /host/port | host:port | + ├────────────────────┴─────────────────────────┴──────────────────────┤ + │ true | scheme://host:port | scheme://host:port | + └──────────────────────────────────────────────┴──────────────────────┘ + + * ``--static-prefix=`` (default: empty string) - if specified and not an empty string the ```` will be added to the cache key. -* ``--capture-prefix=`` (default: empty string) - if specified and not empty then strings are captured from ``host:port`` based on the ```` and are added to the cache key. +* ``--capture-prefix=`` (default: empty string) - if specified and not empty then strings are captured based on the value of ``--canonical-prefix`` parameter (see the table above) and ```` and are added to the cache key. * ``--capture-prefix-uri=`` (default: empty string) - if specified and not empty then strings are captured from the entire URI based on the ```` and are added to the cache key. * If any of the "Prefix" related plugin parameters are used together in the plugin configuration they are added to the cache key in the order shown in the diagram. -* ``--remove-prefix= default prefix */ + append(getCanonicalUrl(_buf, _url, canonicalPrefix, /* provideDefaultKey */ true), /* useSeparator */ false); CacheKeyDebug("added default prefix, key: '%s'", _key.c_str()); } } diff --git a/plugins/cachekey/cachekey.h b/plugins/cachekey/cachekey.h index 7ea058cb6cf..0922ed104ab 100644 --- a/plugins/cachekey/cachekey.h +++ b/plugins/cachekey/cachekey.h @@ -55,9 +55,10 @@ class CacheKey void append(unsigned number); void append(const String &); + void append(const String &s, bool useSeparator); void append(const char *s); void append(const char *n, unsigned s); - void appendPrefix(const String &prefix, Pattern &prefixCapture, Pattern &prefixCaptureUri); + void appendPrefix(const String &prefix, Pattern &prefixCapture, Pattern &prefixCaptureUri, bool canonicalPrefix); void appendPath(Pattern &pathCapture, Pattern &pathCaptureUri); void appendHeaders(const ConfigHeaders &config); void appendQuery(const ConfigQuery &config); diff --git a/plugins/cachekey/configs.cc b/plugins/cachekey/configs.cc index 2320db14336..a56565c7d93 100644 --- a/plugins/cachekey/configs.cc +++ b/plugins/cachekey/configs.cc @@ -397,6 +397,8 @@ Configs::init(int argc, const char *argv[], bool perRemapConfig) {const_cast("separator"), optional_argument, nullptr, 's'}, {const_cast("uri-type"), optional_argument, nullptr, 't'}, {const_cast("capture-header"), optional_argument, nullptr, 'u'}, + {const_cast("canonical-prefix"), optional_argument, nullptr, 'v'}, + /* reserve 'z' for 'config' files */ {nullptr, 0, nullptr, 0}, }; @@ -504,6 +506,9 @@ Configs::init(int argc, const char *argv[], bool perRemapConfig) case 'u': /* capture-header */ _headers.addCapture(optarg); break; + case 'v': /* canonical-prefix */ + _canonicalPrefix = isTrue(optarg); + break; } } @@ -535,6 +540,12 @@ Configs::pathToBeRemoved() return _pathToBeRemoved; } +bool +Configs::canonicalPrefix() +{ + return _canonicalPrefix; +} + void Configs::setSeparator(const char *arg) { diff --git a/plugins/cachekey/configs.h b/plugins/cachekey/configs.h index 947b21931ea..5ff41f03ccc 100644 --- a/plugins/cachekey/configs.h +++ b/plugins/cachekey/configs.h @@ -162,6 +162,11 @@ class Configs */ bool pathToBeRemoved(); + /** + * @brief keep URI scheme and authority elements. + */ + bool canonicalPrefix(); + /** * @brief set the cache key elements separator string. */ @@ -205,6 +210,7 @@ class Configs bool _prefixToBeRemoved = false; /**< @brief instructs the prefix (i.e. host:port) not to added to the cache key */ bool _pathToBeRemoved = false; /**< @brief instructs the path not to added to the cache key */ + bool _canonicalPrefix = false; /**< @brief keep the URI scheme and authority element used as input to transforming into key */ String _separator = "/"; /**< @brief a separator used to separate the cache key elements extracted from the URI */ CacheKeyUriType _uriType = REMAP; /**< @brief shows which URI the cache key will be based on */ }; diff --git a/plugins/cachekey/plugin.cc b/plugins/cachekey/plugin.cc index 43bad79e3c0..afb9503b0ce 100644 --- a/plugins/cachekey/plugin.cc +++ b/plugins/cachekey/plugin.cc @@ -43,7 +43,7 @@ setCacheKey(TSHttpTxn txn, Configs *config, TSRemapRequestInfo *rri = nullptr) /* Append custom prefix or the host:port */ if (!config->prefixToBeRemoved()) { - cachekey.appendPrefix(config->_prefix, config->_prefixCapture, config->_prefixCaptureUri); + cachekey.appendPrefix(config->_prefix, config->_prefixCapture, config->_prefixCaptureUri, config->canonicalPrefix()); } /* Classify User-Agent and append the class name to the cache key if matched. */ cachekey.appendUaClass(config->_classifier); From 93ee51a65f0cef90be03d953b59066270619274f Mon Sep 17 00:00:00 2001 From: Oknet Xu Date: Fri, 23 Aug 2019 17:06:30 +0800 Subject: [PATCH 005/718] PR#5867: Explain how to use open_con(). The DNS sub-system has 2 work modes: - Primary-Secondary mode - Round-Robin mode The `open_con()` and `open_cons()` are shared with these 2 modes. Within the Primary-Secondary mode: - The `DNSHandler::ip` is used to store the Primary DNS server address. - The `validate_ip()` is the API to load the first DNS server address into The `DNSHandler::ip`. - The `open_con()` is the API to update `DNSHandler::ip` with `target` and connect to the address, but you cannot update `DNSHandler::ip` with it self. Within the Round-Robin mode: - The `DNSHandler::ip` is useless. - The `open_con()` is the API to connect to `target`. The SplitDNS is only available in the Primary-Secondary mode: - I suspect that the Round-Robin mode is a feature that was added later. - The author only made this functionality for the DNS sub-system, and forgot to do it for SplitDNS. (cherry picked from commit 678ab7a778d66f83475b478868f254aa62ff8344) --- iocore/dns/DNS.cc | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/iocore/dns/DNS.cc b/iocore/dns/DNS.cc index 8d91744c8dc..6713003b329 100644 --- a/iocore/dns/DNS.cc +++ b/iocore/dns/DNS.cc @@ -468,6 +468,15 @@ DNSHandler::open_cons(sockaddr const *target, bool failed, int icon) Open (and close) connections as necessary and also assures that the epoll fd struct is properly updated. + target == nullptr : + open connection to DNSHandler::ip. + generally, the icon should be 0 if target == nullptr. + + target != nullptr and icon == 0 : + open connection to target, and the target is assigned to DNSHandler::ip. + + target != nullptr and icon > 0 : + open connection to target. */ void DNSHandler::open_con(sockaddr const *target, bool failed, int icon, bool over_tcp) @@ -475,6 +484,8 @@ DNSHandler::open_con(sockaddr const *target, bool failed, int icon, bool over_tc ip_port_text_buffer ip_text; PollDescriptor *pd = get_PollDescriptor(dnsProcessor.thread); + ink_assert(target != &ip.sa); + if (!icon && target) { ats_ip_copy(&ip, target); } else if (!target) { @@ -549,6 +560,12 @@ DNSHandler::startEvent(int /* event ATS_UNUSED */, Event *e) dns_handler_initialized = 1; SET_HANDLER(&DNSHandler::mainEvent); if (dns_ns_rr) { + /* Round Robin mode: + * Establish a connection to each DNS server to make it a connection pool. + * For each DNS Request, a connection is picked up from the pool by round robin method. + * + * The first DNS server is assigned to DNSHandler::ip within open_con() function. + */ int max_nscount = m_res->nscount; if (max_nscount > MAX_NAMED) { max_nscount = MAX_NAMED; @@ -565,6 +582,18 @@ DNSHandler::startEvent(int /* event ATS_UNUSED */, Event *e) } dns_ns_rr_init_down = 0; } else { + /* Primary - Secondary mode: + * Establish a connection to the Primary DNS server. + * It always send DNS requests to the Primary DNS server. + * If the Primary DNS server dies, + * - it will attempt to send DNS requests to the secondary DNS server until the Primary DNS server is back. + * - and keep to detect the health of the Primary DNS server. + * If DNSHandler::recv_dns() got a valid DNS response from the Primary DNS server, + * - it means that the Primary DNS server returns. + * - it send all DNS requests to the Primary DNS server. + * + * The first DNS server is the Primary DNS server, and it is assigned to DNSHandler::ip within validate_ip() function. + */ open_cons(nullptr); // use current target address. n_con = 1; } @@ -587,8 +616,8 @@ DNSHandler::startEvent_sdns(int /* event ATS_UNUSED */, Event *e) this->validate_ip(); SET_HANDLER(&DNSHandler::mainEvent); - open_cons(&ip.sa, false, n_con); - ++n_con; // TODO should n_con be zeroed? + open_cons(nullptr, false, 0); + n_con = 1; return EVENT_CONT; } @@ -647,7 +676,7 @@ DNSHandler::try_primary_named(bool reopen) if (reopen && ((t - last_primary_reopen) > DNS_PRIMARY_REOPEN_PERIOD)) { Debug("dns", "try_primary_named: reopening primary DNS connection"); last_primary_reopen = t; - open_cons(&ip.sa, true, 0); + open_cons(nullptr, true, 0); } if ((t - last_primary_retry) > DNS_PRIMARY_RETRY_PERIOD) { unsigned char buffer[MAX_DNS_REQUEST_LEN]; From dbe00ba98224c3acd5dd5064b9506f255cbff9ad Mon Sep 17 00:00:00 2001 From: YuanYingdong <1975643103@qq.com> Date: Fri, 23 Aug 2019 20:17:33 +0800 Subject: [PATCH 006/718] Update HttpTransact.cc Once we get hit stale and cannot connec t to source site but we decice to serve from cache ,we need to set s->source = SOURCE_CACHE or we will get coredump in HttpTransact::handle_content_length_header (cherry picked from commit 5b700d270b021c9facf664914fdefb3887800975) --- proxy/http/HttpTransact.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc index 3dbc1760779..20236884b83 100644 --- a/proxy/http/HttpTransact.cc +++ b/proxy/http/HttpTransact.cc @@ -3704,7 +3704,7 @@ HttpTransact::handle_server_connection_not_open(State *s) ink_assert(s->cache_info.object_read != nullptr); ink_assert(s->cache_info.action == CACHE_DO_UPDATE || s->cache_info.action == CACHE_DO_SERVE); ink_assert(s->internal_msg_buffer == nullptr); - + s->source = SOURCE_CACHE; TxnDebug("http_trans", "[hscno] serving stale doc to client"); build_response_from_cache(s, HTTP_WARNING_CODE_REVALIDATION_FAILED); } else { From da2e0dc7a76855fadba7caeef76c5645219a4614 Mon Sep 17 00:00:00 2001 From: John Plevyak Date: Fri, 23 Aug 2019 11:44:42 -0700 Subject: [PATCH 007/718] Fix bad limit in poll loop. jtest -c1 now works again. Note: for poll() we must scan the entire array passed in because, unlink epoll() poll() does not populate the output with only the ready fds, instead it sets event bits over the entire array which was passed in. Also fix port endian-ness in verbose message. Signed-off-by: John Plevyak (cherry picked from commit 209a0b243303a60487ede65ae66b0c0c1cc94c02) --- tools/jtest/jtest.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/jtest/jtest.cc b/tools/jtest/jtest.cc index 4253d04bbc7..b8564695109 100644 --- a/tools/jtest/jtest.cc +++ b/tools/jtest/jtest.cc @@ -606,7 +606,7 @@ static void poll_set(int sock, poll_cb read_cb, poll_cb write_cb = nullptr) { if (verbose) { - printf("adding poll %d\n", sock); + printf("adding poll %d %s %s\n", sock, read_cb ? "READ" : "-", write_cb ? "WRITE" : "-"); } fd[sock].fd = sock; fd[sock].read_cb = read_cb; @@ -1770,7 +1770,7 @@ open_server(unsigned short int port, accept_fn_t accept_fn) } if (verbose) { - printf("opening server on %d port %d\n", sock, name.sin_port); + printf("opening server on %d port %d\n", sock, port); } poll_init_set(sock, accept_fn); @@ -1806,7 +1806,7 @@ poll_loop() if (ip >= POLL_GROUP_SIZE || i == last_fd) { int n = poll(pfd, ip, POLL_TIMEOUT); if (n > 0) { - for (int j = 0; j < n; j++) { + for (int j = 0; j < ip; j++) { if (pfd[j].revents & (POLLIN | POLLERR | POLLHUP | POLLNVAL)) { if (verbose) { printf("poll read %d %X\n", pfd[j].fd, pfd[j].revents); From 57e5a4bd2619fd1a2a4e8568d4e84037e4e5df8a Mon Sep 17 00:00:00 2001 From: Gancho Tenev Date: Fri, 23 Aug 2019 14:26:26 -0700 Subject: [PATCH 008/718] cachekey: added --key-type (for parent selection) Added ability to apply all transformations, available for modifying the cache key, to parent selection URL: * --key-type=cache_key - apply transformations to cache key * --key-type=parent_selection_url - apply transformations to parent selection URL TODO/TBD: After this change all transformations can be applied not only to the cache key but to parent selection URL as well. It would make sense to give the cachekey plugin a new, more suitable name. (cherry picked from commit af7299dd06a2a7b5e862edf5aea0693dd1bde2c1) --- doc/admin-guide/plugins/cachekey.en.rst | 167 ++++++++++++++---------- doc/admin-guide/plugins/index.en.rst | 4 +- plugins/cachekey/cachekey.cc | 69 ++++++++-- plugins/cachekey/cachekey.h | 10 +- plugins/cachekey/configs.cc | 62 ++++++++- plugins/cachekey/configs.h | 29 +++- plugins/cachekey/plugin.cc | 2 +- 7 files changed, 248 insertions(+), 95 deletions(-) diff --git a/doc/admin-guide/plugins/cachekey.en.rst b/doc/admin-guide/plugins/cachekey.en.rst index 51f4ef174a8..3ee09484da2 100644 --- a/doc/admin-guide/plugins/cachekey.en.rst +++ b/doc/admin-guide/plugins/cachekey.en.rst @@ -21,22 +21,24 @@ .. _admin-plugins-cachekey: -Cache Key Manipulation Plugin -***************************** +Cache Key and Parent Selection URL Manipulation Plugin +****************************************************** Description =========== -This plugin allows some common cache key manipulations based on various HTTP request components. It can +This plugin allows some common `cache key` or `parent selection URL` manipulations based on various HTTP request components. +Although `cache key` is used everywhere in this document, the same manipulations can be applied to `parent selection URL` +by switching `key type`_. The plugin can * sort query parameters to prevent query parameter reordering being a cache miss -* ignore specific query parameters from the cache key by name or regular expression -* ignore all query parameters from the cache key -* only use specific query parameters in the cache key by name or regular expression +* ignore specific query parameters from the `cache key` by name or regular expression +* ignore all query parameters from the `cache key` +* only use specific query parameters in the `cache key` by name or regular expression * include headers or cookies by name * capture values from the ``User-Agent`` header. * classify request using ``User-Agent`` and a list of regular expressions -* capture and replace strings from the URI and include them in the cache key +* capture and replace strings from the URI and include them in the `cache key` * do more - please find more examples below. URI type @@ -46,6 +48,17 @@ The plugin manipulates the ``remap`` URI (value set during URI remap) by default * ``--uri-type=[remap|pristine]`` (default: ``remap``) +Key type +======== + +The plugin manipulates the `cache key` by default. If `parent selection URL` manipulation is needed the following option can be used: + +* ``--key-type=[cache_key|parent_selection_url]`` (default: ``cache_key``) + +One instance of this plugin can used either for `cache key` or `parent selection URL` manupulation but never both. +If `simultaneous cache key and parent selection URL manipulation`_ is needed two separate instances of the plugin +have to be loaded for each key type. + Cache key structure and related plugin parameters ================================================= @@ -59,11 +72,11 @@ Cache key structure and related plugin parameters │ (default) | (optional) │ (optional) │ (optional) │ (default) │ (default) │ └─────────────┴──────────────┴──────────────┴──────────────┴─────────────┴─────────────┘ -* The cache key set by the cachekey plugin can be considered as divided into several sections. +* The `cache key` set by the cachekey plugin can be considered as divided into several sections. * Every section is manipulated separately by the related plugin parameters (more info in each section description below). -* "User-Agent", "Headers" and "Cookies" sections are optional and will be missing from the cache key if no related plugin parameters are used. +* "User-Agent", "Headers" and "Cookies" sections are optional and will be missing from the `cache key` if no related plugin parameters are used. * "Prefix", "Path" and "Query" sections always have default values even if no related plugin parameters are used. -* All cachekey plugin parameters are optional and if missing some of the cache key sections will be missing (the optional sections) or their values will be left to their defaults. +* All cachekey plugin parameters are optional and if missing some of the `cache key` sections will be missing (the optional sections) or their values will be left to their defaults. "Prefix" section ^^^^^^^^^^^^^^^^ @@ -81,19 +94,20 @@ Cache key structure and related plugin parameters │ --canonical-prefix | default value if no │ input used for │ │ | prefix parameters used │ --capture-prefix │ ├────────────────────┴─────────────────────────┴──────────────────────┤ - │ fasle | /host/port | host:port | + │ false | /host/port | host:port | ├────────────────────┴─────────────────────────┴──────────────────────┤ │ true | scheme://host:port | scheme://host:port | └──────────────────────────────────────────────┴──────────────────────┘ -* ``--static-prefix=`` (default: empty string) - if specified and not an empty string the ```` will be added to the cache key. -* ``--capture-prefix=`` (default: empty string) - if specified and not empty then strings are captured based on the value of ``--canonical-prefix`` parameter (see the table above) and ```` and are added to the cache key. -* ``--capture-prefix-uri=`` (default: empty string) - if specified and not empty then strings are captured from the entire URI based on the ```` and are added to the cache key. -* If any of the "Prefix" related plugin parameters are used together in the plugin configuration they are added to the cache key in the order shown in the diagram. -* ``--remove-prefix=true|false|yes|no|0|1`` (default: false) - if specified the prefix elements (host, port) are not processed nor appended to the cachekey. All prefix related plugin parameters are ignored if this parameter is ``true``, ``yes`` or ``1``. +* ``--static-prefix=`` (default: empty string) - if specified and not an empty string the ```` will be added to the `cache key`. +* ``--capture-prefix=`` (default: empty string) - if specified and not empty then strings are captured from ``host:port`` based on the ```` and are added to the `cache key`. +* ``--capture-prefix-uri=`` (default: empty string) - if specified and not empty then strings are captured from the entire URI based on the ```` and are added to the `cache key`. +* If any of the "Prefix" related plugin parameters are used together in the plugin configuration they are added to the `cache key` in the order shown in the diagram. +* ``--remove-prefix=:`` (default: empty string) - loads a regex patterns list from a file ````, the patterns are matched against the ``User-Agent`` header and if **not** matched ```` is added it to the key. * Multiple ``--ua-whitelist`` and ``--ua-blacklist`` can be used and the result will be defined by their order in the plugin configuration. * ``User-Agent`` regex capturing and replacement - * ``--ua-capture=`` (default: empty string) - if specified and not empty then strings are captured from the ``User-Agent`` header based on ```` (see below) and are added to the cache key. -* If any ``User-Agent`` classification and regex capturing and replacement plugin parameters are used together they are added to the cache key in the order shown in the diagram. + * ``--ua-capture=`` (default: empty string) - if specified and not empty then strings are captured from the ``User-Agent`` header based on ```` (see below) and are added to the `cache key`. +* If any ``User-Agent`` classification and regex capturing and replacement plugin parameters are used together they are added to the `cache key` in the order shown in the diagram. "Headers" section ^^^^^^^^^^^^^^^^^ @@ -126,9 +140,9 @@ Cache key structure and related plugin parameters optional components | └───────────────────┴───────────────────┘ configured | -* ``--include-headers`` (default: empty list) - comma separated list of headers to be added to the cache key. The list of headers defined by ``--include-headers`` are always sorted before adding them to the cache key. +* ``--include-headers`` (default: empty list) - comma separated list of headers to be added to the `cache key`. The list of headers defined by ``--include-headers`` are always sorted before adding them to the `cache key`. -* ``--capture-header=:`` (default: empty) - captures elements from header using and adds them to the cache key. +* ``--capture-header=:`` (default: empty) - captures elements from header using and adds them to the `cache key`. "Cookies" section ^^^^^^^^^^^^^^^^^ @@ -142,7 +156,7 @@ Cache key structure and related plugin parameters optional components | └───────────────────┘ configured | -* ``--include-cookies`` (default: empty list) - comma separated list of cookies to be added to the cache key. The list of cookies defined by ``--include-cookies`` are always sorted before adding them to the cache key. +* ``--include-cookies`` (default: empty list) - comma separated list of cookies to be added to the `cache key`. The list of cookies defined by ``--include-cookies`` are always sorted before adding them to the `cache key`. "Path" section ^^^^^^^^^^^^^^ @@ -156,19 +170,19 @@ Cache key structure and related plugin parameters optional components | └─────────────────────────────────────┘ configured | -* if no path related plugin parameters are used, the URI path string is included in the cache key. -* ``--capture-path=`` (default: empty string) - if specified and not empty then strings are captured from URI path based on the ```` and are added to the cache key. -* ``--capture-path-uri=`` (default: empty string) - if specified and not empty then strings are captured from the entire URI based on the ```` and are added to the cache key. +* if no path related plugin parameters are used, the URI path string is included in the `cache key`. +* ``--capture-path=`` (default: empty string) - if specified and not empty then strings are captured from URI path based on the ```` and are added to the `cache key`. +* ``--capture-path-uri=`` (default: empty string) - if specified and not empty then strings are captured from the entire URI based on the ```` and are added to the `cache key`. * ``--remove-path=`` can be in the following formats - * ```` - ```` defines regex capturing groups, up to 10 captured strings based on ```` will be added to the cache key. - * ``///`` - ```` defines regex capturing groups, ```` defines a pattern where the captured strings referenced with ``$0`` ... ``$9`` will be substituted and the result will be added to the cache key. + * ```` - ```` defines regex capturing groups, up to 10 captured strings based on ```` will be added to the `cache key`. + * ``///`` - ```` defines regex capturing groups, ```` defines a pattern where the captured strings referenced with ``$0`` ... ``$9`` will be substituted and the result will be added to the `cache key`. Cache key elements separator ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -* ``--separator=`` - the cache key is constructed by extracting elements from HTTP URI and headers or by using the UA classifiers and they are appended during the key construction and separated by ``/`` (by default). This options allows to override the default separator to any string (including an empty string). +* ``--separator=`` - the `cache key` is constructed by extracting elements from HTTP URI and headers or by using the UA classifiers and they are appended during the key construction and separated by ``/`` (by default). This options allows to override the default separator to any string (including an empty string). How to run the plugin @@ -300,13 +314,13 @@ HTTP request :: * Connection #0 to host 127.0.0.1 left intact * Closing connection #0 -The response header ``X-Cache-Key`` header contains the cache key: :: +The response header ``X-Cache-Key`` header contains the `cache key`: :: /www.example.com/80/popular/Mozilla/5.0/H1:v1/H2:v2/C1=v1;C2=v2/path/to/data?a=1&b=2&c=3 -The ``xdebug.so`` plugin and ``X-Debug`` request header are used just to demonstrate basic cache key troubleshooting. +The ``xdebug.so`` plugin and ``X-Debug`` request header are used just to demonstrate basic `cache key` troubleshooting. -If we add ``--static-prefix=nice_custom_prefix`` to the remap rule then the cache key would look like the following: :: +If we add ``--static-prefix=nice_custom_prefix`` to the remap rule then the `cache key` would look like the following: :: /nice_custom_prefix/popular/Mozilla/5.0/H1:v1/H2:v2/C1=v1;C2=v2/path/to/data?a=1&b=2&c=3 @@ -318,50 +332,50 @@ URI query parameters Ignore the query string (all query parameters) """""""""""""""""""""""""""""""""""""""""""""" -The following added to the remap rule will ignore the query, removing it from the cache key. :: +The following added to the remap rule will ignore the query, removing it from the `cache key`. :: @plugin=cachekey.so @pparam=--remove-all-params=true Cache key normalization by sorting the query parameters """"""""""""""""""""""""""""""""""""""""""""""""""""""" -The following will normalize the cache key by sorting the query parameters. :: +The following will normalize the `cache key` by sorting the query parameters. :: @plugin=cachekey.so @pparam=--sort-params=true -If the URI has the following query string ``c=1&a=1&b=2&x=1&k=1&u=1&y=1`` the cache key will use ``a=1&b=2&c=1&k=1&u=1&x=1&y=1`` +If the URI has the following query string ``c=1&a=1&b=2&x=1&k=1&u=1&y=1`` the `cache key` will use ``a=1&b=2&c=1&k=1&u=1&x=1&y=1`` Ignore (exclude) certain query parameters """"""""""""""""""""""""""""""""""""""""" -The following will make sure query parameters `a` and `b` will **not** be used when constructing the cache key. :: +The following will make sure query parameters `a` and `b` will **not** be used when constructing the `cache key`. :: @plugin=cachekey.so @pparam=--exclude-params=a,b -If the URI has the following query string ``c=1&a=1&b=2&x=1&k=1&u=1&y=1`` the cache key will use ``c=1&x=1&k=1&u=1&y=1`` +If the URI has the following query string ``c=1&a=1&b=2&x=1&k=1&u=1&y=1`` the `cache key` will use ``c=1&x=1&k=1&u=1&y=1`` Ignore (exclude) certain query parameters from the cache key by using regular expression (PCRE) """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -The following will make sure query parameters ``a`` and ``b`` will **not** be used when constructing the cache key. :: +The following will make sure query parameters ``a`` and ``b`` will **not** be used when constructing the `cache key`. :: @plugin=cachekey.so @pparam=--exclude-match-params=(a|b) -If the URI has the following query string ``c=1&a=1&b=2&x=1&k=1&u=1&y=1`` the cache key will use ``c=1&x=1&k=1&u=1&y=1`` +If the URI has the following query string ``c=1&a=1&b=2&x=1&k=1&u=1&y=1`` the `cache key` will use ``c=1&x=1&k=1&u=1&y=1`` Include only certain query parameters """"""""""""""""""""""""""""""""""""" -The following will make sure only query parameters `a` and `c` will be used when constructing the cache key and the rest will be ignored. :: +The following will make sure only query parameters `a` and `c` will be used when constructing the `cache key` and the rest will be ignored. :: @plugin=cachekey.so @pparam=--include-params=a,c -If the URI has the following query string ``c=1&a=1&b=2&x=1&k=1&u=1&y=1`` the cache key will use ``c=1&a=1`` +If the URI has the following query string ``c=1&a=1&b=2&x=1&k=1&u=1&y=1`` the `cache key` will use ``c=1&a=1`` Include only certain query parameters by using regular expression (PCRE) """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -The following will make sure only query parameters ``a`` and ``c`` will be used when constructing the cache key and the rest will be ignored. :: +The following will make sure only query parameters ``a`` and ``c`` will be used when constructing the `cache key` and the rest will be ignored. :: @plugin=cachekey.so @pparam=--include-match-params=(a|c) -If the URI has the following query string ``c=1&a=1&b=2&x=1&k=1&u=1&y=1`` the cache key will use ``c=1&a=1`` +If the URI has the following query string ``c=1&a=1&b=2&x=1&k=1&u=1&y=1`` the `cache key` will use ``c=1&a=1`` White-list + black-list certain parameters using multiple parameters in the same remap rule. """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" @@ -374,7 +388,7 @@ If the plugin is used with the following plugin parameters in the remap rule: :: @pparam=--include-params=y,c \ @pparam=--include-params=x,b -and if the URI has the following query string ``c=1&a=1&b=2&x=1&k=1&u=1&y=1`` the cache key will use ``c=1&b=1`` +and if the URI has the following query string ``c=1&a=1&b=2&x=1&k=1&u=1&y=1`` the `cache key` will use ``c=1&b=1`` White-list + black-list certain parameters using multiple parameters in the same remap rule and regular expressions (PCRE). """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" @@ -387,7 +401,7 @@ If the plugin is used with the following plugin parameters in the remap rule: :: @pparam=--include-match-params=(y|c) \ @pparam=--include-match-params=(x|b) -and if the URI has the following query string ``c=1&a=1&b=2&x=1&k=1&u=1&y=1`` the cache key will use ``c=1&b=1`` +and if the URI has the following query string ``c=1&a=1&b=2&x=1&k=1&u=1&y=1`` the `cache key` will use ``c=1&b=1`` Mixing --include-params, --exclude-params, --include-match-param and --exclude-match-param """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" @@ -400,18 +414,18 @@ If the plugin is used with the following plugin parameters in the remap rule: :: @pparam=--include-params=y,c \ @pparam=--include-match-params=(x|b) -and if the URI has the following query string ``c=1&a=1&b=2&x=1&k=1&u=1&y=1`` the cache key will use ``c=1&b=1`` +and if the URI has the following query string ``c=1&a=1&b=2&x=1&k=1&u=1&y=1`` the `cache key` will use ``c=1&b=1`` HTTP Headers ^^^^^^^^^^^^ Include certain headers in the cache key """""""""""""""""""""""""""""""""""""""" -The following headers ``HeaderA`` and ``HeaderB`` will be used when constructing the cache key and the rest will be ignored. :: +The following headers ``HeaderA`` and ``HeaderB`` will be used when constructing the `cache key` and the rest will be ignored. :: @plugin=cachekey.so @pparam=--include-headers=HeaderA,HeaderB -The following would capture from the ``Authorization`` header and will add the captured element to the cache key :: +The following would capture from the ``Authorization`` header and will add the captured element to the `cache key` :: @plugin=cachekey.so \ @pparam=--capture-header=Authorization:/AWS\s(?[^:]+).*/clientID:$1/ @@ -421,7 +435,7 @@ If the request looks like the following:: http://example-cdn.com/path/file Authorization: AWS MKIARYMOG51PT0DLD:DLiWQ2lyS49H4Zyx34kW0URtg6s= -Cache key would be set to:: +The `cache key` would be set to:: /example-cdn.com/80/clientID:MKIARYMOG51PTCKQ0DLD/path/file @@ -432,7 +446,7 @@ HTTP Cookies Include certain cookies in the cache key """""""""""""""""""""""""""""""""""""""" -The following headers ``CookieA`` and ``CookieB`` will be used when constructing the cache key and the rest will be ignored. :: +The following headers ``CookieA`` and ``CookieB`` will be used when constructing the `cache key` and the rest will be ignored. :: @plugin=cachekey.so @pparam=--include-headers=CookieA,CookieB @@ -446,7 +460,7 @@ If the plugin is used with the following plugin parameter in the remap rule. :: @plugin=cachekey.so @pparam=--static-prefix=static_prefix -the cache key will be prefixed with ``/static_prefix`` instead of ``host:port`` when ``--static-prefix`` is not used. +the `cache key` will be prefixed with ``/static_prefix`` instead of ``host:port`` when ``--static-prefix`` is not used. Capturing from the host:port and adding it to the prefix section """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" @@ -455,7 +469,7 @@ If the plugin is used with the following plugin parameter in the remap rule. :: @plugin=cachekey.so \ @pparam=--capture-prefix=(test_prefix).*:([^\s\/$]*) -the cache key will be prefixed with ``/test_prefix/80`` instead of ``test_prefix_371.example.com:80`` when ``--capture-prefix`` is not used. +the `cache key` will be prefixed with ``/test_prefix/80`` instead of ``test_prefix_371.example.com:80`` when ``--capture-prefix`` is not used. Capturing from the entire URI and adding it to the prefix section """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" @@ -468,7 +482,7 @@ and if the request URI is the following :: http://test_prefix_123.example.com/path/to/object?a=1&b=2&c=3 -the the cache key will be prefixed with ``/test_prefix_object`` instead of ``test_prefix_123.example.com:80`` when ``--capture-prefix-uri`` is not used. +the the `cache key` will be prefixed with ``/test_prefix_object`` instead of ``test_prefix_123.example.com:80`` when ``--capture-prefix-uri`` is not used. Combining prefix plugin parameters, i.e. --static-prefix and --capture-prefix """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" @@ -478,7 +492,7 @@ If the plugin is used with the following plugin parameters in the remap rule. :: @pparam=--capture-prefix=(test_prefix).*:([^\s\/$]*) \ @pparam=--static-prefix=static_prefix -the cache key will be prefixed with ``/static_prefix/test_prefix/80`` instead of ``test_prefix_371.example.com:80`` when either ``--capture-prefix`` nor ``--static-prefix`` are used. +the `cache key` will be prefixed with ``/static_prefix/test_prefix/80`` instead of ``test_prefix_371.example.com:80`` when either ``--capture-prefix`` nor ``--static-prefix`` are used. Path, capture and replace from the path or entire URI @@ -496,7 +510,7 @@ and the request URI is the following :: http://test_path_123.example.com/path/to/object?a=1&b=2&c=3 -then the cache key will have ``/const_path_object`` in the path section of the cache key instead of ``/path/to/object`` when either ``--capture-path`` nor ``--capture-path-uri`` are used. +then the `cache key` will have ``/const_path_object`` in the path section of the `cache key` instead of ``/path/to/object`` when either ``--capture-path`` nor ``--capture-path-uri`` are used. Capture and replace groups from whole URI for the "Path" section @@ -511,7 +525,7 @@ and the request URI is the following :: http://test_path_123.example.com/path/to/object?a=1&b=2&c=3 -the the cache key will have ``/test_path_object`` in the path section of the cache key instead of ``/path/to/object`` when either ``--capture-path`` nor ``--capture-path-uri`` are used. +the the `cache key` will have ``/test_path_object`` in the path section of the `cache key` instead of ``/path/to/object`` when either ``--capture-path`` nor ``--capture-path-uri`` are used. Combining path plugin parameters --capture-path and --capture-path-uri @@ -527,7 +541,7 @@ and the request URI is the following :: http://test_path_123.example.com/path/to/object?a=1&b=2&c=3 -the the cache key will have ``/test_path_object/const_path_object`` in the path section of the cache key instead of ``/path/to/object`` when either ``--capture-path`` nor ``--capture-path-uri`` are used. +the the `cache key` will have ``/test_path_object/const_path_object`` in the path section of the `cache key` instead of ``/path/to/object`` when either ``--capture-path`` nor ``--capture-path-uri`` are used. User-Agent capturing, replacement and classification ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -589,16 +603,16 @@ then ``browser`` will be used when constructing the key. Cacheurl plugin to cachekey plugin migration ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The plugin `cachekey` was not meant to replace the cacheurl plugin in terms of having exactly the same cache key strings generated. It just allows the operator to extract elements from the HTTP URI in the same way the `cacheurl` does (through a regular expression, please see `` above). +The plugin `cachekey` was not meant to replace the cacheurl plugin in terms of having exactly the same `cache key` strings generated. It just allows the operator to extract elements from the HTTP URI in the same way the `cacheurl` does (through a regular expression, please see `` above). -The following examples demonstrate different ways to achieve `cacheurl` compatibility on a cache key string level in order to avoid invalidation of the cache. +The following examples demonstrate different ways to achieve `cacheurl` compatibility on a `cache key` string level in order to avoid invalidation of the cache. The operator could use `--capture-path-uri`, `--capture-path`, `--capture-prefix-uri`, `--capture-prefix` to capture elements from the URI, path and authority elements. -By using `--separator=` the operator could override the default separator to an empty string `--separator=` and thus make sure there are no cache key element separators. +By using `--separator=` the operator could override the default separator to an empty string `--separator=` and thus make sure there are no `cache key` element separators. -Example 1: Let us say we have a capture definition used in `cacheurl`. Now by using `--capture-prefix-uri` one could extract elements through the same capture definition used with `cacheurl`, remove the cache key element separator `--separator=` and by using `--capture-path-uri` could remove the URI path and by using `--remove-all-params=true` could remove the query string:: +Example 1: Let us say we have a capture definition used in `cacheurl`. Now by using `--capture-prefix-uri` one could extract elements through the same capture definition used with `cacheurl`, remove the `cache key` element separator `--separator=` and by using `--capture-path-uri` could remove the URI path and by using `--remove-all-params=true` could remove the query string:: @plugin=cachekey.so \ @pparam=--capture-prefix-uri=/.*/$0/ \ @@ -606,7 +620,7 @@ Example 1: Let us say we have a capture definition used in `cacheurl`. Now by us @pparam=--remove-all-params=true \ @pparam=--separator= -Example 2: A more efficient way would be achieved by using `--capture-prefix-uri` to capture from the URI, remove the cache key element separator `--separator=` and by using `--remove-path` to remove the URI path and `--remove-all-params=true` to remove the query string:: +Example 2: A more efficient way would be achieved by using `--capture-prefix-uri` to capture from the URI, remove the `cache key` element separator `--separator=` and by using `--remove-path` to remove the URI path and `--remove-all-params=true` to remove the query string:: @plugin=cachekey.so \ @pparam=--capture-prefix-uri=/.*/$0/ \ @@ -614,7 +628,7 @@ Example 2: A more efficient way would be achieved by using `--capture-prefix-uri @pparam=--remove-all-params=true \ @pparam=--separator= -Example 3: Same result as the above but this time by using `--capture-path-uri` to capture from the URI, remove the cache key element separator `--separator=` and by using `--remove-prefix` to remove the URI authority elements and by using `--remove-all-params=true` to remove the query string:: +Example 3: Same result as the above but this time by using `--capture-path-uri` to capture from the URI, remove the `cache key` element separator `--separator=` and by using `--remove-prefix` to remove the URI authority elements and by using `--remove-all-params=true` to remove the query string:: @plugin=cachekey.so \ @pparam=--capture-path-uri=/(.*)/$0/ \ @@ -629,3 +643,24 @@ Example 4: Let us say that we would like to capture from URI in similar to `cach @pparam=--remove-path=true \ @pparam=--sort-params=true \ @pparam=--separator= + + +Simultaneous cache key and parent selection URL manipulation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following is an example of how to manipulate both `cache key` and `parent selection URL` in the same remap rule. +For this purpose two separate instances are loaded for that remap rule: + +:: + + @plugin=cachekey.so \ + @pparam=--key-type=parent_selection_url \ + @pparam=--static-prefix=this://goes.to/parent/selection/url \ + @pparam=--canonical-prefix=true \ + @plugin=cachekey.so \ + @pparam=--key-type=cache_key \ + @pparam=--static-prefix=this://goes.to/cache/key \ + @pparam=--canonical-prefix=true + +In the example above the first instance of the plugin sets the prefix to the parent selection URI and +the second instance of the plugin sets the prefix to the cache key. diff --git a/doc/admin-guide/plugins/index.en.rst b/doc/admin-guide/plugins/index.en.rst index e2ff09a4842..48e9825bd0d 100644 --- a/doc/admin-guide/plugins/index.en.rst +++ b/doc/admin-guide/plugins/index.en.rst @@ -77,8 +77,8 @@ Plugins that are considered stable are installed by default in |TS| releases. :doc:`Background Fetch ` Proactively fetch content from Origin in a way that it will fill the object into cache. -:doc:`Cache Key Manipulation ` - Allows some common cache key manipulations based on various HTTP request elements. +:doc:`Cache Key and Parent Selection URL Manipulation ` + Allows some common cache key or parent selection URL manipulations based on various HTTP request elements. :doc:`Cache Promotion Policies ` Allows for control over which assets should be written to cache, or not. diff --git a/plugins/cachekey/cachekey.cc b/plugins/cachekey/cachekey.cc index 95640e19005..5f128894bfa 100644 --- a/plugins/cachekey/cachekey.cc +++ b/plugins/cachekey/cachekey.cc @@ -240,8 +240,8 @@ getCanonicalUrl(TSMBuffer buf, TSMLoc url, bool canonicalPrefix, bool provideDef * @param uriType type of the URI used to create the cachekey ("remap" or "pristine") * @param rri remap request info */ -CacheKey::CacheKey(TSHttpTxn txn, String separator, CacheKeyUriType uriType, TSRemapRequestInfo *rri) - : _txn(txn), _separator(std::move(separator)), _uriType(uriType) +CacheKey::CacheKey(TSHttpTxn txn, String separator, CacheKeyUriType uriType, CacheKeyKeyType keyType, TSRemapRequestInfo *rri) + : _txn(txn), _separator(std::move(separator)), _uriType(uriType), _keyType(keyType) { _key.reserve(512); @@ -250,8 +250,9 @@ CacheKey::CacheKey(TSHttpTxn txn, String separator, CacheKeyUriType uriType, TSR /* Get the URI and header to base the cachekey on. * @TODO it might make sense to add more supported URI types */ + CacheKeyDebug("setting %s from a %s plugin", getCacheKeyKeyTypeName(_keyType), _remap ? "remap" : "global"); + if (_remap) { - CacheKeyDebug("setting cache key from a remap plugin"); if (PRISTINE == _uriType) { if (TS_SUCCESS != TSHttpTxnPristineUrlGet(_txn, &_buf, &_url)) { /* Failing here is unlikely. No action seems the only reasonable thing to do from within this plug-in */ @@ -266,7 +267,6 @@ CacheKey::CacheKey(TSHttpTxn txn, String separator, CacheKeyUriType uriType, TSR } _hdrs = rri->requestHdrp; } else { - CacheKeyDebug("setting cache key from a global plugin"); if (TS_SUCCESS != TSHttpTxnClientReqGet(_txn, &_buf, &_hdrs)) { /* Failing here is unlikely. No action seems the only reasonable thing to do from within this plug-in */ CacheKeyError("failed to get client request handle"); @@ -745,24 +745,67 @@ CacheKey::appendUaClass(Classifier &classifier) bool CacheKey::finalize() const { - bool res = true; - CacheKeyDebug("finalizing cache key '%s' from a %s plugin", _key.c_str(), (_remap ? "remap" : "global")); - if (TS_SUCCESS != TSCacheUrlSet(_txn, &(_key[0]), _key.size())) { - int len; - char *url = TSHttpTxnEffectiveUrlStringGet(_txn, &len); - if (nullptr != url) { + bool res = false; + String msg; + + CacheKeyDebug("finalizing %s '%s' from a %s plugin", getCacheKeyKeyTypeName(_keyType), _key.c_str(), + (_remap ? "remap" : "global")); + switch (_keyType) { + case CACHE_KEY: { + if (TS_SUCCESS == TSCacheUrlSet(_txn, &(_key[0]), _key.size())) { + /* Set cache key succesfully */ + msg.assign("set cache key to ").append(_key); + res = true; + } else { if (_remap) { /* Remap instance. Always runs first by design (before TS_HTTP_POST_REMAP_HOOK) */ - CacheKeyError("failed to set cache key for url %.*s", len, url); + msg.assign("failed to set cache key"); } else { /* Global instance. We would fail and get here if a per-remap instance has already set the cache key * (currently TSCacheUrlSet() can be called only once successfully). Don't error, just debug. * @todo avoid the consecutive attempts and error only on unexpected failures. */ - CacheKeyDebug("failed to set cache key for url %.*s", len, url); + msg.assign("failed to set cache key"); + } + } + } break; + case PARENT_SELECTION_URL: { + /* parent selection */ + const char *start = _key.c_str(); + const char *end = _key.c_str() + _key.length(); + TSMLoc new_url_loc; + if (TS_SUCCESS == TSUrlCreate(_buf, &new_url_loc)) { + if (TS_PARSE_DONE == TSUrlParse(_buf, new_url_loc, &start, end)) { + if (TS_SUCCESS == TSHttpTxnParentSelectionUrlSet(_txn, _buf, new_url_loc)) { + msg.assign("set parent selection URL to ").append(_key); + res = true; + } else { + msg.assign("failed to set parent selection URL"); + } + } else { + msg.assign("failed to parse parent selection URL"); } + TSHandleMLocRelease(_buf, TS_NULL_MLOC, new_url_loc); + } else { + msg.assign("failed to create parent selection URL"); + } + } break; + default: { + msg.assign("unknown target URI type"); + } break; + } + + /* Report status - debug level in case of success, error in case of failure. + * Since getting effective URI is expensive add it only in case of failure */ + if (res) { + CacheKeyDebug("%.*s", static_cast(msg.length()), msg.c_str()); + } else { + int len; + char *url = TSHttpTxnEffectiveUrlStringGet(_txn, &len); + if (nullptr != url) { + msg.append(" for url ").append(url, len); TSfree(url); } - res = false; + CacheKeyError("%.*s", static_cast(msg.length()), msg.c_str()); } return res; } diff --git a/plugins/cachekey/cachekey.h b/plugins/cachekey/cachekey.h index 0922ed104ab..0b47e85984d 100644 --- a/plugins/cachekey/cachekey.h +++ b/plugins/cachekey/cachekey.h @@ -50,7 +50,8 @@ class CacheKey { public: - CacheKey(TSHttpTxn txn, String separator, CacheKeyUriType urlType, TSRemapRequestInfo *rri = nullptr); + CacheKey(TSHttpTxn txn, String separator, CacheKeyUriType urlType, CacheKeyKeyType targetUrlType, + TSRemapRequestInfo *rri = nullptr); ~CacheKey(); void append(unsigned number); @@ -86,7 +87,8 @@ class CacheKey bool _valid = false; /**< @brief shows if the constructor discovered the input correctly */ bool _remap = false; /**< @brief shows if the input URI was from remap info */ - String _key; /**< @brief cache key */ - String _separator; /**< @brief a separator used to separate the cache key elements extracted from the URI */ - CacheKeyUriType _uriType; /**< @brief the URI type used as a cachekey base: pristine, remap, etc. */ + String _key; /**< @brief cache key */ + String _separator; /**< @brief a separator used to separate the cache key elements extracted from the URI */ + CacheKeyUriType _uriType = REMAP; /**< @brief the URI type used as a cachekey base: pristine, remap, etc. */ + CacheKeyKeyType _keyType = CACHE_KEY; /**< @brief the target URI type: cache key, parent selection, etc. */ }; diff --git a/plugins/cachekey/configs.cc b/plugins/cachekey/configs.cc index a56565c7d93..335bb2d5a06 100644 --- a/plugins/cachekey/configs.cc +++ b/plugins/cachekey/configs.cc @@ -396,8 +396,9 @@ Configs::init(int argc, const char *argv[], bool perRemapConfig) {const_cast("remove-path"), optional_argument, nullptr, 'r'}, {const_cast("separator"), optional_argument, nullptr, 's'}, {const_cast("uri-type"), optional_argument, nullptr, 't'}, - {const_cast("capture-header"), optional_argument, nullptr, 'u'}, - {const_cast("canonical-prefix"), optional_argument, nullptr, 'v'}, + {const_cast("key-type"), optional_argument, nullptr, 'u'}, + {const_cast("capture-header"), optional_argument, nullptr, 'v'}, + {const_cast("canonical-prefix"), optional_argument, nullptr, 'w'}, /* reserve 'z' for 'config' files */ {nullptr, 0, nullptr, 0}, }; @@ -503,10 +504,13 @@ Configs::init(int argc, const char *argv[], bool perRemapConfig) case 't': /* uri-type */ setUriType(optarg); break; - case 'u': /* capture-header */ + case 'u': /* key-type */ + setKeyType(optarg); + break; + case 'v': /* capture-header */ _headers.addCapture(optarg); break; - case 'v': /* canonical-prefix */ + case 'w': /* canonical-prefix */ _canonicalPrefix = isTrue(optarg); break; } @@ -578,8 +582,58 @@ Configs::setUriType(const char *arg) } } +void +Configs::setKeyType(const char *arg) +{ + if (nullptr != arg) { + if (9 == strlen(arg) && 0 == strncasecmp(arg, "cache_key", 9)) { + _keyType = CacheKeyKeyType::CACHE_KEY; + CacheKeyDebug("setting cache key"); + } else if (20 == strlen(arg) && 0 == strncasecmp(arg, "parent_selection_url", 20)) { + _keyType = CacheKeyKeyType::PARENT_SELECTION_URL; + CacheKeyDebug("setting parent selection URL"); + } else { + CacheKeyError("unrecognized key type '%s', using default 'cache_key'", arg); + } + } else { + CacheKeyError("found an empty key type, using default 'cache_key'"); + } +} + CacheKeyUriType Configs::getUriType() { return _uriType; } + +CacheKeyKeyType +Configs::getKeyType() +{ + return _keyType; +} + +const char * +getCacheKeyUriTypeName(CacheKeyUriType type) +{ + switch (type) { + case REMAP: + return "remap"; + case PRISTINE: + return "pristine"; + default: + return "unknown"; + } +} + +const char * +getCacheKeyKeyTypeName(CacheKeyKeyType type) +{ + switch (type) { + case CACHE_KEY: + return "cache key"; + case PARENT_SELECTION_URL: + return "parent selection url"; + default: + return "unknown"; + } +} diff --git a/plugins/cachekey/configs.h b/plugins/cachekey/configs.h index 5ff41f03ccc..26cd9beb9f3 100644 --- a/plugins/cachekey/configs.h +++ b/plugins/cachekey/configs.h @@ -33,6 +33,14 @@ enum CacheKeyUriType { PRISTINE, }; +enum CacheKeyKeyType { + CACHE_KEY, + PARENT_SELECTION_URL, +}; + +const char *getCacheKeyUriTypeName(CacheKeyUriType type); +const char *getCacheKeyKeyTypeName(CacheKeyKeyType type); + /** * @brief Plug-in configuration elements (query / headers / cookies). * @@ -182,11 +190,21 @@ class Configs */ void setUriType(const char *arg); + /** + * @brief sets the target URI Type. + */ + void setKeyType(const char *arg); + /** * @brief get URI type. */ CacheKeyUriType getUriType(); + /** + * @brief get target URI type. + */ + CacheKeyKeyType getKeyType(); + /* Make the following members public to avoid unnecessary accessors */ ConfigQuery _query; /**< @brief query parameter related configuration */ ConfigHeaders _headers; /**< @brief headers related configuration */ @@ -208,9 +226,10 @@ class Configs */ bool loadClassifiers(const String &args, bool blacklist = true); - bool _prefixToBeRemoved = false; /**< @brief instructs the prefix (i.e. host:port) not to added to the cache key */ - bool _pathToBeRemoved = false; /**< @brief instructs the path not to added to the cache key */ - bool _canonicalPrefix = false; /**< @brief keep the URI scheme and authority element used as input to transforming into key */ - String _separator = "/"; /**< @brief a separator used to separate the cache key elements extracted from the URI */ - CacheKeyUriType _uriType = REMAP; /**< @brief shows which URI the cache key will be based on */ + bool _prefixToBeRemoved = false; /**< @brief instructs the prefix (i.e. host:port) not to added to the cache key */ + bool _pathToBeRemoved = false; /**< @brief instructs the path not to added to the cache key */ + bool _canonicalPrefix = false; /**< @brief keep the URI scheme and authority element used as input to transforming into key */ + String _separator = "/"; /**< @brief a separator used to separate the cache key elements extracted from the URI */ + CacheKeyUriType _uriType = REMAP; /**< @brief shows which URI the cache key will be based on */ + CacheKeyKeyType _keyType = CACHE_KEY; /**< @brief target URI to be modified, cache key or paren selection */ }; diff --git a/plugins/cachekey/plugin.cc b/plugins/cachekey/plugin.cc index afb9503b0ce..aff94f96736 100644 --- a/plugins/cachekey/plugin.cc +++ b/plugins/cachekey/plugin.cc @@ -39,7 +39,7 @@ static void setCacheKey(TSHttpTxn txn, Configs *config, TSRemapRequestInfo *rri = nullptr) { /* Initial cache key facility from the requested URL. */ - CacheKey cachekey(txn, config->getSeparator(), config->getUriType(), rri); + CacheKey cachekey(txn, config->getSeparator(), config->getUriType(), config->getKeyType(), rri); /* Append custom prefix or the host:port */ if (!config->prefixToBeRemoved()) { From 8d9d0558b897e92f5f66d9583afa5d5b7fe80da0 Mon Sep 17 00:00:00 2001 From: Fei Deng Date: Tue, 27 Aug 2019 11:20:25 -0500 Subject: [PATCH 009/718] static linking asan, tsan, lsan (cherry picked from commit 211d6c9aaa5c9704bf8afed5b8b543f70002b2c8) --- configure.ac | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index c77b2841a27..112afa40459 100644 --- a/configure.ac +++ b/configure.ac @@ -974,26 +974,97 @@ fi # Flags for ASAN if test "x${enable_asan}" = "xyes"; then - if test "x${enable_tsan}" = "xyes"; then + if test "x${enable_tsan}" = "xyes" -o "x${enable_tsan}" = "xstatic"; then AC_ERROR([Cannot have ASAN and TSAN options at the same time, pick one]) fi TS_ADDTO(AM_CFLAGS, [-fno-omit-frame-pointer -fsanitize=address]) TS_ADDTO(AM_CXXFLAGS, [-fno-omit-frame-pointer -fsanitize=address]) +elif test "x${enable_asan}" = "xstatic"; then + if test "x${enable_tsan}" = "xyes" -o "x${enable_tsan}" = "xstatic"; then + AC_ERROR([Cannot have ASAN and TSAN options at the same time, pick one]) + fi + asan_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -fno-omit-frame-pointer -fsanitize=address -static-libasan" + AC_LANG_PUSH(C++) + AC_MSG_CHECKING([static ASAN library is available]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([#include ], [])], + [AC_MSG_RESULT([yes])], + [ + AC_MSG_RESULT([no]) + AC_ERROR([Cannot find static ASAN library.]) + ] + ) + AC_LANG_POP + CXXFLAGS="$asan_CXXFLAGS" + TS_ADDTO(AM_CFLAGS, [-fno-omit-frame-pointer -fsanitize=address -static-libasan]) + TS_ADDTO(AM_CXXFLAGS, [-fno-omit-frame-pointer -fsanitize=address -static-libasan]) fi # Flags for LSAN stand-alone mode if test "x${enable_lsan}" = "xyes"; then - if test "x${enable_asan}" = "xyes"; then + if test "x${enable_asan}" = "xyes" -o "x${enable_asan}" = "xstatic"; then AC_ERROR([ASAN already specified, --enable-lsan is meant only for lsan stand-alone mode]) fi + if test "x${enable_tsan}" = "xyes" -o "x${enable_tsan}" = "xstatic"; then + AC_ERROR([Cannot have LSAN and TSAN options at the same time, pick one]) + fi TS_ADDTO(AM_CFLAGS, [-fno-omit-frame-pointer -fsanitize=leak]) TS_ADDTO(AM_CXXFLAGS, [-fno-omit-frame-pointer -fsanitize=leak]) +elif test "x${enable_lsan}" = "xstatic"; then + if test "x${enable_asan}" = "xyes" -o "x${enable_asan}" = "xstatic"; then + AC_ERROR([ASAN already specified, --enable-lsan is meant only for lsan stand-alone mode]) + fi + if test "x${enable_tsan}" = "xyes" -o "x${enable_tsan}" = "xstatic"; then + AC_ERROR([Cannot have LSAN and TSAN options at the same time, pick one]) + fi + AC_CHECK_LIB(lsan, _init, [lsan_have_libs=yes], [lsan_have_libs=no]) + if test "x${lsan_have_libs}" == "xno"; then + AC_ERROR([Cannot find LSAN static library]) + fi + lsan_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -fno-omit-frame-pointer -fsanitize=leak -static-liblsan" + AC_LANG_PUSH(C++) + AC_MSG_CHECKING([static LSAN library is available]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([#include ], [])], + [AC_MSG_RESULT([yes])], + [ + AC_MSG_RESULT([no]) + AC_ERROR([Cannot find static LSAN library.]) + ] + ) + AC_LANG_POP + CXXFLAGS="$lsan_CXXFLAGS" + TS_ADDTO(AM_CFLAGS, [-fno-omit-frame-pointer -fsanitize=leak -static-liblsan]) + TS_ADDTO(AM_CXXFLAGS, [-fno-omit-frame-pointer -fsanitize=leak -static-liblsan]) fi # Flags for TSAN if test "x${enable_tsan}" = "xyes"; then TS_ADDTO(AM_CFLAGS, [-fsanitize=thread]) TS_ADDTO(AM_CXXFLAGS, [-fsanitize=thread]) +elif test "x${enable_tsan}" = "xstatic"; then + AC_CHECK_LIB(tsan, _init, [tsan_have_libs=yes], [tsan_have_libs=no]) + if test "x${tsan_have_libs}" == "xno"; then + AC_ERROR([Cannot find TSAN static library]) + fi + tsan_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -fsanitize=thread -static-libtsan" + AC_LANG_PUSH(C++) + AC_MSG_CHECKING([static TSAN library is available]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([#include ], [])], + [AC_MSG_RESULT([yes])], + [ + AC_MSG_RESULT([no]) + AC_ERROR([Cannot find static TSAN library.]) + ] + ) + AC_LANG_POP + CXXFLAGS="$tsan_CXXFLAGS" + TS_ADDTO(AM_CFLAGS, [-fsanitize=thread -static-libtsan]) + TS_ADDTO(AM_CXXFLAGS, [-fsanitize=thread -static-libtsan]) fi # Checks for pointer size. From 8afbe11ff316e97c34eb1dd1bf69a4c945c5cf70 Mon Sep 17 00:00:00 2001 From: Bryan Call Date: Tue, 27 Aug 2019 15:58:51 -0700 Subject: [PATCH 010/718] Fixed const issue with magick plugin (cherry picked from commit 58a1451ba0ab6a06308dc6ac405da74395f9dff8) --- plugins/experimental/magick/magick.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/experimental/magick/magick.cc b/plugins/experimental/magick/magick.cc index 00f4755a3de..2e6a18b767a 100644 --- a/plugins/experimental/magick/magick.cc +++ b/plugins/experimental/magick/magick.cc @@ -184,7 +184,7 @@ struct EVPKey { EVPKey() : key(EVP_PKEY_new()) { assert(nullptr != key); } bool - assign(const char *const k) const + assign(char *k) const { assert(nullptr != k); const int rc = EVP_PKEY_assign_RSA(key, k); @@ -196,7 +196,7 @@ struct EVPKey { bool assign(T &t) { - return assign(reinterpret_cast(t)); + return assign(reinterpret_cast(t)); } }; From 5908c0093a6225c6b8b6d50469e0e92187840136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ask=20Bj=C3=B8rn=20Hansen?= Date: Thu, 5 Sep 2019 15:54:55 -0700 Subject: [PATCH 011/718] Enable stdout logging on FreeBSD (cherry picked from commit cda2d845e638011e4c4854c4e3b355b48a43cdc5) --- rc/trafficserver.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rc/trafficserver.in b/rc/trafficserver.in index 63539e85c75..2d4e6489826 100644 --- a/rc/trafficserver.in +++ b/rc/trafficserver.in @@ -331,7 +331,7 @@ case "$1" in echo "Starting ${TS_PACKAGE_NAME}" name="$TM_NAME" command="/usr/sbin/daemon" - command_args="$TM_DAEMON $TM_DAEMON_ARGS" + command_args="-o $STDOUTLOG $TM_DAEMON $TM_DAEMON_ARGS" pidfile="$TM_PIDFILE" run_rc_command "$1" else From b1ceba7cc9f64a5f77abba21786911e8f712d6fe Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Sat, 28 Sep 2019 14:31:06 -0600 Subject: [PATCH 012/718] First cut at a layout for Release Notes (cherry picked from commit 8a558cb9dd6775a04f4d23782228f596aeb80cee) Conflicts: doc/developer-guide/api/functions/TSHttpTxnRedoCacheLookup.en.rst --- doc/index.rst | 1 + doc/release-notes/index.en.rst | 27 ++++++++++++++++ doc/release-notes/upgrading.en.rst | 51 ++++++++++++++++++++++++++++++ doc/release-notes/whats-new.en.rst | 41 ++++++++++++++++++++++++ 4 files changed, 120 insertions(+) create mode 100644 doc/release-notes/index.en.rst create mode 100644 doc/release-notes/upgrading.en.rst create mode 100644 doc/release-notes/whats-new.en.rst diff --git a/doc/index.rst b/doc/index.rst index 36ac32cf381..0495c31436f 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -27,6 +27,7 @@ Apache Traffic Server Manual preface/index.en getting-started/index.en + release-notes/index.en admin-guide/index.en developer-guide/index.en appendices/index.en diff --git a/doc/release-notes/index.en.rst b/doc/release-notes/index.en.rst new file mode 100644 index 00000000000..1a770aca200 --- /dev/null +++ b/doc/release-notes/index.en.rst @@ -0,0 +1,27 @@ +.. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +.. include:: ../common.defs + +Release Notes +************* + +.. toctree:: + :maxdepth: 1 + + whats-new.en + upgrading.en diff --git a/doc/release-notes/upgrading.en.rst b/doc/release-notes/upgrading.en.rst new file mode 100644 index 00000000000..8fd28b9d71f --- /dev/null +++ b/doc/release-notes/upgrading.en.rst @@ -0,0 +1,51 @@ +.. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +.. include:: ../common.defs + +.. _upgrading: + +Upgrading to ATS v10.x +====================== + +.. toctree:: + :maxdepth: 1 + +Deprecated or Removed Features +------------------------------ +The following features, configurations and plugins are either removed or deprecated in this +version of ATS. Deprecated features should be avoided, with the expectation that they will be +removed in the next major release of ATS. + + +API Changes +----------- +The following APIs have changed, either in semanatics, interfaces, or both. + + +Cache +----- +The cache in this releases of ATS is compatible with previous versions of ATS. You would not expect +to lose your cache, or have to reinitialize the cache when upgrading. + +Configuration changes +--------------------- +The following incompatible changes to the configurations have been made in this version of ATS. + + +Plugins +------- diff --git a/doc/release-notes/whats-new.en.rst b/doc/release-notes/whats-new.en.rst new file mode 100644 index 00000000000..e369c9ad1e3 --- /dev/null +++ b/doc/release-notes/whats-new.en.rst @@ -0,0 +1,41 @@ +.. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +.. include:: ../common.defs + +.. _whats_new: + +What's New in ATS v10.x +======================= + +This version of ATS includes over commits, from pull requests. A total of contributors +have participated in this development cycle. + +.. toctree:: + :maxdepth: 1 + +New Features +------------ + +New or modifed Configurations +----------------------------- + +Logging and Metrics +------------------- + +Plugins +------- From fc9f1260b38ca7c1c50ad330fdfeda79d0ad9d98 Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Mon, 30 Sep 2019 16:13:04 -0600 Subject: [PATCH 013/718] Change the version to v9.x for this doc set --- doc/release-notes/upgrading.en.rst | 2 +- doc/release-notes/whats-new.en.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/release-notes/upgrading.en.rst b/doc/release-notes/upgrading.en.rst index 8fd28b9d71f..9f9204fbae0 100644 --- a/doc/release-notes/upgrading.en.rst +++ b/doc/release-notes/upgrading.en.rst @@ -19,7 +19,7 @@ .. _upgrading: -Upgrading to ATS v10.x +Upgrading to ATS v9.x ====================== .. toctree:: diff --git a/doc/release-notes/whats-new.en.rst b/doc/release-notes/whats-new.en.rst index e369c9ad1e3..f335fed5518 100644 --- a/doc/release-notes/whats-new.en.rst +++ b/doc/release-notes/whats-new.en.rst @@ -19,7 +19,7 @@ .. _whats_new: -What's New in ATS v10.x +What's New in ATS v9.x ======================= This version of ATS includes over commits, from pull requests. A total of contributors From 5083a8a9f5cdd166e7c7776e18c8dd0a998fbc12 Mon Sep 17 00:00:00 2001 From: Susan Hinrichs Date: Fri, 6 Sep 2019 14:46:14 +0000 Subject: [PATCH 014/718] Update documentation for connect_attempts_timeout. (cherry picked from commit 13b623775247fc76f93081ec0813075b9ff91e7c) --- doc/admin-guide/files/records.config.en.rst | 4 ++-- doc/admin-guide/performance/index.en.rst | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst index 05bdbd2f2ec..6fec39e368f 100644 --- a/doc/admin-guide/files/records.config.en.rst +++ b/doc/admin-guide/files/records.config.en.rst @@ -1528,8 +1528,8 @@ Origin Server Connect Attempts :reloadable: :overridable: - The timeout value (in seconds) for time to first byte for an origin server - connection. + The timeout value (in seconds) for time to set up a connection to the origin. After the connection is established the value of + ``proxy.config.http.transaction_no_activity_timeout_out`` is used to established timeouts on the data over the connection. See :ref:`admin-performance-timeouts` for more discussion on |TS| timeouts. diff --git a/doc/admin-guide/performance/index.en.rst b/doc/admin-guide/performance/index.en.rst index 64520ee03e7..85c2f722444 100644 --- a/doc/admin-guide/performance/index.en.rst +++ b/doc/admin-guide/performance/index.en.rst @@ -327,7 +327,9 @@ Origin Connection Timeouts Origin server connection timeouts are configured with :ts:cv:`proxy.config.http.connect_attempts_timeout`, which is applied both to the initial connection as well as any retries attempted, should an attempt timeout. The timeout applies from the moment |TS| begins the -connection attempt until the origin returns the first byte. +connection attempt until the origin fully establishes a connection (the connection is ready to write). +After the connection is established the value of +:ts:cv:`proxy.config.http.transaction_no_activity_timeout_out` is used to established timeouts on the data over the connection. In the case where you wish to have a different (generally longer) timeout for ``POST`` and ``PUT`` connections to an origin server, you may also adjust From 264ec459cf34ee872f9430e096c097e56d6aa678 Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Tue, 10 Sep 2019 08:53:54 +0900 Subject: [PATCH 015/718] Cleanup: VIO - No logical changes - Remove unnecessary include headers - Fix format - Make const functions (cherry picked from commit dc0fb99bab960026ba842210ec16fab4f4701e65) --- iocore/eventsystem/I_IOBuffer.h | 4 ++-- iocore/eventsystem/I_VIO.h | 28 +++++++++---------------- iocore/eventsystem/P_VIO.h | 36 ++++++++++----------------------- 3 files changed, 23 insertions(+), 45 deletions(-) diff --git a/iocore/eventsystem/I_IOBuffer.h b/iocore/eventsystem/I_IOBuffer.h index 404b41d029e..e74bb158b22 100644 --- a/iocore/eventsystem/I_IOBuffer.h +++ b/iocore/eventsystem/I_IOBuffer.h @@ -1298,13 +1298,13 @@ class MIOBuffer */ struct MIOBufferAccessor { IOBufferReader * - reader() + reader() const { return entry; } MIOBuffer * - writer() + writer() const { return mbuf; } diff --git a/iocore/eventsystem/I_VIO.h b/iocore/eventsystem/I_VIO.h index b80522035c8..d2b2b10568f 100644 --- a/iocore/eventsystem/I_VIO.h +++ b/iocore/eventsystem/I_VIO.h @@ -25,17 +25,12 @@ #pragma once #define I_VIO_h -#include "tscore/ink_platform.h" -#include "I_EventSystem.h" #if !defined(I_IOBuffer_h) #error "include I_IOBuffer.h" ----include I_IOBuffer.h #endif -#include "tscore/ink_apidefs.h" - class Continuation; + +class Continuation; class VConnection; -class IOVConnection; -class MIOBuffer; class ProxyMutex; /** @@ -73,9 +68,12 @@ class ProxyMutex; class VIO { public: + explicit VIO(int aop); + VIO(); ~VIO() {} + /** Interface for the VConnection that owns this handle. */ - Continuation *get_continuation(); + Continuation *get_continuation() const; void set_continuation(Continuation *cont); /** @@ -95,15 +93,15 @@ class VIO @return The number of bytes to be processed by the operation. */ - int64_t ntodo(); + int64_t ntodo() const; ///////////////////// // buffer settings // ///////////////////// void set_writer(MIOBuffer *writer); void set_reader(IOBufferReader *reader); - MIOBuffer *get_writer(); - IOBufferReader *get_reader(); + MIOBuffer *get_writer() const; + IOBufferReader *get_reader() const; /** Reenable the IO operation. @@ -140,10 +138,7 @@ class VIO inkcoreapi void reenable_re(); void disable(); - bool is_disabled(); - - explicit VIO(int aop); - VIO(); + bool is_disabled() const; enum { NONE = 0, @@ -160,7 +155,6 @@ class VIO STAT, }; -public: /** Continuation to callback. @@ -225,5 +219,3 @@ class VIO private: bool _disabled = false; }; - -#include "I_VConnection.h" diff --git a/iocore/eventsystem/P_VIO.h b/iocore/eventsystem/P_VIO.h index 4eebf0698ca..b934e910f77 100644 --- a/iocore/eventsystem/P_VIO.h +++ b/iocore/eventsystem/P_VIO.h @@ -27,44 +27,45 @@ TS_INLINE VIO::VIO(int aop) : op(aop), buffer(), mutex(nullptr) {} -///////////////////////////////////////////////////////////// -// -// VIO::VIO() -// -///////////////////////////////////////////////////////////// TS_INLINE VIO::VIO() : buffer(), mutex(nullptr) {} TS_INLINE Continuation * -VIO::get_continuation() +VIO::get_continuation() const { return cont; } + TS_INLINE void VIO::set_writer(MIOBuffer *writer) { buffer.writer_for(writer); } + TS_INLINE void VIO::set_reader(IOBufferReader *reader) { buffer.reader_for(reader); } + TS_INLINE MIOBuffer * -VIO::get_writer() +VIO::get_writer() const { return buffer.writer(); } + TS_INLINE IOBufferReader * -VIO::get_reader() +VIO::get_reader() const { return (buffer.reader()); } + TS_INLINE int64_t -VIO::ntodo() +VIO::ntodo() const { return nbytes - ndone; } + TS_INLINE void VIO::done() { @@ -75,11 +76,6 @@ VIO::done() } } -///////////////////////////////////////////////////////////// -// -// VIO::set_continuation() -// -///////////////////////////////////////////////////////////// TS_INLINE void VIO::set_continuation(Continuation *acont) { @@ -96,11 +92,6 @@ VIO::set_continuation(Continuation *acont) return; } -///////////////////////////////////////////////////////////// -// -// VIO::reenable() -// -///////////////////////////////////////////////////////////// TS_INLINE void VIO::reenable() { @@ -110,11 +101,6 @@ VIO::reenable() } } -///////////////////////////////////////////////////////////// -// -// VIO::reenable_re() -// -///////////////////////////////////////////////////////////// TS_INLINE void VIO::reenable_re() { @@ -131,7 +117,7 @@ VIO::disable() } TS_INLINE bool -VIO::is_disabled() +VIO::is_disabled() const { return this->_disabled; } From ab8996cade8df54e1450f2dd6285327aac3e7a66 Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Tue, 10 Sep 2019 14:03:29 +0900 Subject: [PATCH 016/718] Cleanup AuTest for HTTP/2 (cherry picked from commit 76cadf55ece2253c0ddf01a172c57c346f8cd89a) --- tests/gold_tests/h2/http2.test.py | 74 ++++++++++++++++--------------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/tests/gold_tests/h2/http2.test.py b/tests/gold_tests/h2/http2.test.py index 29f7a19ef75..54842726165 100644 --- a/tests/gold_tests/h2/http2.test.py +++ b/tests/gold_tests/h2/http2.test.py @@ -18,59 +18,61 @@ import os Test.Summary = ''' -Test a basic remap of a http connection +Test a basic remap of a http/2 connection ''' # need Curl Test.SkipUnless( Condition.HasCurlFeature('http2') ) Test.ContinueOnFail = True -# Define default ATS -ts = Test.MakeATSProcess("ts", select_ports=True, enable_tls=True) + +# ---- +# Setup Origin Server +# ---- server = Test.MakeOriginServer("server") -requestLocation = "test2" -reHost = "www.example.com" - -testName = "" -request_header = {"headers": "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""} -# desired response form the origin server -response_header = {"headers": "HTTP/1.1 200 OK\r\nServer: microserver\r\nConnection: close\r\n\r\n", - "timestamp": "1469733493.993", "body": ""} -request_header2 = { - "headers": "GET /{0} HTTP/1.1\r\nHost: {1}\r\n\r\n".format(requestLocation, reHost), "timestamp": "1469733493.993", "body": ""} -# desired response form the origin server -response_header2 = {"headers": "HTTP/1.1 200 OK\r\nServer: microserver\r\nTransfer-Encoding: chunked\r\nConnection: close\r\n\r\n", - "timestamp": "1469733493.993", "body": ""} -server.addResponse("sessionlog.json", request_header, response_header) +# For Test Case 1 & 5 - / +server.addResponse("sessionlog.json", + {"headers": "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""}, + {"headers": "HTTP/1.1 200 OK\r\nServer: microserver\r\nConnection: close\r\n\r\n", "timestamp": "1469733493.993", "body": ""}) +# For Test Case 2 - /bigfile # Add info for the large H2 download test server.addResponse("sessionlog.json", {"headers": "GET /bigfile HTTP/1.1\r\nHost: www.example.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""}, {"headers": "HTTP/1.1 200 OK\r\nServer: microserver\r\nConnection: close\r\nCache-Control: max-age=3600\r\nContent-Length: 191414\r\n\r\n", "timestamp": "1469733493.993", "body": ""}) +# For Test Case 3 - /test2 +server.addResponse("sessionlog.json", + {"headers": "GET /test2 HTTP/1.1\r\nHost: www.example.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""}, + {"headers": "HTTP/1.1 200 OK\r\nServer: microserver\r\nTransfer-Encoding: chunked\r\nConnection: close\r\n\r\n", "timestamp": "1469733493.993", "body": ""}) + +# For Test Case 6 - /postchunked post_body = "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" server.addResponse("sessionlog.jason", - {"headers": "POST /postchunked HTTP/1.1\r\nHost: www.example.com\r\n\r\n", - "timestamp": "1469733493.993", - "body": post_body}, + {"headers": "POST /postchunked HTTP/1.1\r\nHost: www.example.com\r\n\r\n", "timestamp": "1469733493.993", "body": post_body}, {"headers": "HTTP/1.1 200 OK\r\nServer: microserver\r\nConnection: close\r\nContent-Length: 10\r\n\r\n", "timestamp": "1469733493.993", "body": "0123456789"}) +# For Test Case 7 - /bigpostchunked # Make a post body that will be split across at least two frames big_post_body = "0123456789" * 131070 server.addResponse("sessionlog.jason", - {"headers": "POST /bigpostchunked HTTP/1.1\r\nHost: www.example.com\r\n\r\n", - "timestamp": "1469733493.993", - "body": big_post_body}, + {"headers": "POST /bigpostchunked HTTP/1.1\r\nHost: www.example.com\r\n\r\n", "timestamp": "1469733493.993", "body": big_post_body}, {"headers": "HTTP/1.1 200 OK\r\nServer: microserver\r\nConnection: close\r\nContent-Length: 10\r\n\r\n", "timestamp": "1469733493.993", "body": "0123456789"}) +big_post_body_file = open(os.path.join(Test.RunDirectory, "big_post_body"), "w") +big_post_body_file.write(big_post_body) +big_post_body_file.close() -server.addResponse("sessionlog.json", request_header2, response_header2) +# For Test Case 8 - /huge_resp_hdrs +server.addResponse("sessionlog.json", + {"headers": "GET /huge_resp_hdrs HTTP/1.1\r\nHost: www.example.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""}, + {"headers": "HTTP/1.1 200 OK\r\nServer: microserver\r\nConnection: close\r\nContent-Length: 6\r\n\r\n", "timestamp": "1469733493.993", "body": "200 OK"}) -# request/response for test case 8 -request_header = {"headers": "GET /huge_resp_hdrs HTTP/1.1\r\nHost: www.example.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""} -response_header = {"headers": "HTTP/1.1 200 OK\r\nServer: microserver\r\nConnection: close\r\nContent-Length: 6\r\n\r\n", "timestamp": "1469733493.993", "body": "200 OK"} -server.addResponse("sessionlog.json", request_header, response_header) +# ---- +# Setup ATS +# ---- +ts = Test.MakeATSProcess("ts", select_ports=True, enable_tls=True) # add ssl materials like key, certificates for the server ts.addSSLfile("ssl/server.pem") @@ -100,15 +102,15 @@ 'proxy.config.http2.max_concurrent_streams_in': 65535, }) -big_post_body_file = open(os.path.join(Test.RunDirectory, "big_post_body"), "w") -big_post_body_file.write(big_post_body) -big_post_body_file.close() - ts.Setup.CopyAs('h2client.py', Test.RunDirectory) ts.Setup.CopyAs('h2bigclient.py', Test.RunDirectory) ts.Setup.CopyAs('h2chunked.py', Test.RunDirectory) ts.Setup.CopyAs('h2active_timeout.py', Test.RunDirectory) +# ---- +# Test Cases +# ---- + # Test Case 1: basic H2 interaction tr = Test.AddTestRun() tr.Processes.Default.Command = 'python3 h2client.py -p {0}'.format(ts.Variables.ssl_port) @@ -128,7 +130,7 @@ # Test Case 3: Chunked content tr = Test.AddTestRun() -tr.Processes.Default.Command = 'python3 h2chunked.py -p {0} -u /{1}'.format(ts.Variables.ssl_port, requestLocation) +tr.Processes.Default.Command = 'python3 h2chunked.py -p {0} -u /test2'.format(ts.Variables.ssl_port) tr.Processes.Default.ReturnCode = 0 tr.Processes.Default.Streams.stdout = "gold/chunked.gold" tr.StillRunningAfter = server @@ -143,7 +145,7 @@ # tr.Processes.Default.Streams.stdout = "gold/replay.gold" # tr.StillRunningAfter = server -# Test Case 5:h2_active_timeout +# Test Case 5: h2_active_timeout tr = Test.AddTestRun() tr.Processes.Default.Command = 'python3 h2active_timeout.py -p {0}'.format(ts.Variables.ssl_port) tr.Processes.Default.ReturnCode = 0 @@ -154,7 +156,7 @@ # While HTTP/2 does not support Tranfer-encoding we pass that into curl to encourage it to not set the content length # on the post body tr = Test.AddTestRun() -tr.Processes.Default.Command = 'curl -s -k -H "Transfer-Encoding: chunked" -d "{0}" https://127.0.0.1:{1}/postchunked'.format( post_body, ts.Variables.ssl_port) +tr.Processes.Default.Command = 'curl -s -k -H "Transfer-Encoding: chunked" -d "{0}" https://127.0.0.1:{1}/postchunked'.format(post_body, ts.Variables.ssl_port) tr.Processes.Default.ReturnCode = 0 tr.Processes.Default.Streams.All = "gold/post_chunked.gold" tr.StillRunningAfter = server @@ -163,7 +165,7 @@ # While HTTP/2 does not support Tranfer-encoding we pass that into curl to encourage it to not set the content length # on the post body tr = Test.AddTestRun() -tr.Processes.Default.Command = 'curl -s -k -H "Transfer-Encoding: chunked" -d @big_post_body https://127.0.0.1:{0}/bigpostchunked'.format( ts.Variables.ssl_port) +tr.Processes.Default.Command = 'curl -s -k -H "Transfer-Encoding: chunked" -d @big_post_body https://127.0.0.1:{0}/bigpostchunked'.format(ts.Variables.ssl_port) tr.Processes.Default.ReturnCode = 0 tr.Processes.Default.Streams.All = "gold/post_chunked.gold" tr.StillRunningAfter = server From 4cf8ff44df137b9e3ebf3b373be9051553907fdf Mon Sep 17 00:00:00 2001 From: Masakazu Kitajo Date: Tue, 10 Sep 2019 16:49:01 +0900 Subject: [PATCH 017/718] Make code buildable with BoringSSL Checked with the latest code f7b830d8df9f5578c748aa0283d44c59ea7eeb25 (cherry picked from commit 6c0eb634b5082532b52272a8d3d7e7905f74d00c) --- .../c-api/client_context_dump/client_context_dump.cc | 2 +- iocore/net/P_SSLNetVConnection.h | 8 ++++++++ .../cert_reporting_tool/cert_reporting_tool.cc | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/example/plugins/c-api/client_context_dump/client_context_dump.cc b/example/plugins/c-api/client_context_dump/client_context_dump.cc index 36b20ddc4ce..034b556cec3 100644 --- a/example/plugins/c-api/client_context_dump/client_context_dump.cc +++ b/example/plugins/c-api/client_context_dump/client_context_dump.cc @@ -116,7 +116,7 @@ dump_context(const char *ca_path, const char *ck_path) // Serial number int64_t sn = 0; -#if OPENSSL_VERSION_NUMBER >= 0x010100000 +#if !defined(OPENSSL_IS_BORINGSSL) && (OPENSSL_VERSION_NUMBER >= 0x010100000) ASN1_INTEGER_get_int64(&sn, serial); #else sn = ASN1_INTEGER_get(serial); diff --git a/iocore/net/P_SSLNetVConnection.h b/iocore/net/P_SSLNetVConnection.h index 0240ee7e908..0dae517ff7b 100644 --- a/iocore/net/P_SSLNetVConnection.h +++ b/iocore/net/P_SSLNetVConnection.h @@ -309,12 +309,20 @@ class SSLNetVConnection : public UnixNetVConnection, public ALPNSupport return nullptr; } +#ifndef OPENSSL_IS_BORINGSSL int curve_nid = SSL_get_shared_curve(ssl, 0); if (curve_nid == NID_undef) { return nullptr; } return OBJ_nid2sn(curve_nid); +#else + if (uint16_t curve_id = SSL_get_curve_id(ssl); curve_id != 0) { + return SSL_get_curve_name(curve_id); + } else { + return nullptr; + } +#endif } bool diff --git a/plugins/experimental/cert_reporting_tool/cert_reporting_tool.cc b/plugins/experimental/cert_reporting_tool/cert_reporting_tool.cc index 0103418b2a7..fd6ab40b5d9 100644 --- a/plugins/experimental/cert_reporting_tool/cert_reporting_tool.cc +++ b/plugins/experimental/cert_reporting_tool/cert_reporting_tool.cc @@ -115,7 +115,7 @@ dump_context(const char *ca_path, const char *ck_path) // Serial number int64_t sn = 0; -#if OPENSSL_VERSION_NUMBER >= 0x010100000 +#if !defined(OPENSSL_IS_BORINGSSL) && (OPENSSL_VERSION_NUMBER >= 0x010100000) ASN1_INTEGER_get_int64(&sn, serial); #else sn = ASN1_INTEGER_get(serial); From 95a2ce7a36e5cd965d9e0e7b20adde31ee8da654 Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Wed, 11 Sep 2019 15:02:49 +0900 Subject: [PATCH 018/718] Fix AuTest for HTTP/2 using httpbin (cherry picked from commit 2e15c6541e973ad6e45e1daf92549f7b5c47eccb) --- tests/gold_tests/h2/httpbin.test.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/gold_tests/h2/httpbin.test.py b/tests/gold_tests/h2/httpbin.test.py index df2698063ff..d31247c5b09 100644 --- a/tests/gold_tests/h2/httpbin.test.py +++ b/tests/gold_tests/h2/httpbin.test.py @@ -64,18 +64,15 @@ }) ts.Disk.logging_yaml.AddLines( - ''' +''' logging: formats: - # Extended Log Format. - name: access - format: |- -[%] % % % % % % % + format: '[%] % % % % % % %' logs: - filename: access format: access - } '''.split("\n") ) @@ -87,7 +84,8 @@ # Test Case 0: Basic request and resposne test_run = Test.AddTestRun() -test_run.Processes.Default.Command = 'curl -vs -k --http2 https://127.0.0.1:{0}/get'.format(ts.Variables.ssl_port) +# TODO: when httpbin 0.8.0 or later is released, remove below json pretty print hack +test_run.Processes.Default.Command = "curl -vs -k --http2 https://127.0.0.1:{0}/get | python -c 'import sys,json; print(json.dumps(json.load(sys.stdin), indent=2))".format(ts.Variables.ssl_port) test_run.Processes.Default.ReturnCode = 0 test_run.Processes.Default.StartBefore(httpbin, ready=When.PortOpen(httpbin.Variables.Port)) test_run.Processes.Default.StartBefore(Test.Processes.ts) From ddba8b5895ec47bf217931e98f4930ccfb8dcbbb Mon Sep 17 00:00:00 2001 From: Valentin Gutierrez Date: Wed, 11 Sep 2019 13:43:55 +0000 Subject: [PATCH 019/718] Track SSL session cache evictions performed due to full bucket (cherry picked from commit a62e5f98763bd29bf68318cb55a2ddc1ec189a1b) --- iocore/net/SSLSessionCache.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/iocore/net/SSLSessionCache.cc b/iocore/net/SSLSessionCache.cc index 9ba73bc56fb..8c803892016 100644 --- a/iocore/net/SSLSessionCache.cc +++ b/iocore/net/SSLSessionCache.cc @@ -142,6 +142,9 @@ SSLSessionBucket::insertSession(const SSLSessionID &id, SSL_SESSION *sess) PRINT_BUCKET("insertSession before") if (queue.size >= static_cast(SSLConfigParams::session_cache_max_bucket_size)) { + if (ssl_rsb) { + SSL_INCREMENT_DYN_STAT(ssl_session_cache_eviction); + } removeOldestSession(); } From 1013eb3b1486447a93588fd876ae80fc6deadea8 Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Fri, 13 Sep 2019 09:16:33 +0900 Subject: [PATCH 020/718] Track scheduled events to (read|write)_vio.cont from Http2Stream (cherry picked from commit 9bd2fd6f0264bfe2176895531f8348fea20f84fa) --- proxy/http2/Http2Stream.cc | 30 ++++++++++++++++++++++++++---- proxy/http2/Http2Stream.h | 6 ++++-- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/proxy/http2/Http2Stream.cc b/proxy/http2/Http2Stream.cc index da681d3d3ae..8bdb1633d7c 100644 --- a/proxy/http2/Http2Stream.cc +++ b/proxy/http2/Http2Stream.cc @@ -78,14 +78,20 @@ Http2Stream::main_event_handler(int event, void *edata) if (lock.is_locked()) { read_vio.cont->handleEvent(event, &read_vio); } else { - this_ethread()->schedule_imm(read_vio.cont, event, &read_vio); + if (this->_read_vio_event) { + this->_read_vio_event->cancel(); + } + this->_read_vio_event = this_ethread()->schedule_imm(read_vio.cont, event, &read_vio); } } else if (current_reader && write_vio.ntodo() > 0) { MUTEX_TRY_LOCK(lock, write_vio.mutex, this_ethread()); if (lock.is_locked()) { write_vio.cont->handleEvent(event, &write_vio); } else { - this_ethread()->schedule_imm(write_vio.cont, event, &write_vio); + if (this->_write_vio_event) { + this->_write_vio_event->cancel(); + } + this->_write_vio_event = this_ethread()->schedule_imm(write_vio.cont, event, &write_vio); } } break; @@ -98,7 +104,10 @@ Http2Stream::main_event_handler(int event, void *edata) if (lock.is_locked()) { write_vio.cont->handleEvent(event, &write_vio); } else { - this_ethread()->schedule_imm(write_vio.cont, event, &write_vio); + if (this->_write_vio_event) { + this->_write_vio_event->cancel(); + } + this->_write_vio_event = this_ethread()->schedule_imm(write_vio.cont, event, &write_vio); } } } else { @@ -114,7 +123,10 @@ Http2Stream::main_event_handler(int event, void *edata) if (lock.is_locked()) { read_vio.cont->handleEvent(event, &read_vio); } else { - this_ethread()->schedule_imm(read_vio.cont, event, &read_vio); + if (this->_read_vio_event) { + this->_read_vio_event->cancel(); + } + this->_read_vio_event = this_ethread()->schedule_imm(read_vio.cont, event, &read_vio); } } } else { @@ -916,6 +928,16 @@ Http2Stream::clear_io_events() buffer_full_write_event->cancel(); buffer_full_write_event = nullptr; } + + if (this->_read_vio_event) { + this->_read_vio_event->cancel(); + this->_read_vio_event = nullptr; + } + + if (this->_write_vio_event) { + this->_write_vio_event->cancel(); + this->_write_vio_event = nullptr; + } } void diff --git a/proxy/http2/Http2Stream.h b/proxy/http2/Http2Stream.h index a005a624658..8b747bd560c 100644 --- a/proxy/http2/Http2Stream.h +++ b/proxy/http2/Http2Stream.h @@ -318,8 +318,10 @@ class Http2Stream : public ProxyTransaction ink_hrtime inactive_timeout_at = 0; Event *inactive_event = nullptr; - Event *read_event = nullptr; - Event *write_event = nullptr; + Event *read_event = nullptr; + Event *write_event = nullptr; + Event *_read_vio_event = nullptr; + Event *_write_vio_event = nullptr; }; extern ClassAllocator http2StreamAllocator; From 42f158f4ef6c8f1f328a4e00d4beae3cdace320a Mon Sep 17 00:00:00 2001 From: Valentin Gutierrez Date: Fri, 13 Sep 2019 10:15:17 +0000 Subject: [PATCH 021/718] Perform a SSL quiet shutdown when close-notify is not sent (cherry picked from commit acf2fb7519bb0ed3820d3f798178903341d0678f) --- iocore/net/SSLNetVConnection.cc | 5 + .../gold_tests/tls/tls_session_cache.test.py | 93 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 tests/gold_tests/tls/tls_session_cache.test.py diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc index 112cca4e43f..8a3fb9c05a1 100644 --- a/iocore/net/SSLNetVConnection.cc +++ b/iocore/net/SSLNetVConnection.cc @@ -874,6 +874,11 @@ SSLNetVConnection::do_io_close(int lerrno) // Send the close-notify int ret = SSL_shutdown(ssl); Debug("ssl-shutdown", "SSL_shutdown %s", (ret) ? "success" : "failed"); + } else { + // Request a quiet shutdown to OpenSSL + SSL_set_quiet_shutdown(ssl, 1); + SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN | SSL_SENT_SHUTDOWN); + Debug("ssl-shutdown", "Enable quiet shutdown"); } } } diff --git a/tests/gold_tests/tls/tls_session_cache.test.py b/tests/gold_tests/tls/tls_session_cache.test.py new file mode 100644 index 00000000000..08d9fd2d9e3 --- /dev/null +++ b/tests/gold_tests/tls/tls_session_cache.test.py @@ -0,0 +1,93 @@ +''' +''' +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import re +Test.Summary = ''' +Test tls session cache +''' + +# Define default ATS +ts = Test.MakeATSProcess("ts", select_ports=True, enable_tls=True) +server = Test.MakeOriginServer("server") + + +# Add info the origin server responses +request_header = {"headers": "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""} +response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", "timestamp": "1469733493.993", "body": ""} +server.addResponse("sessionlog.json", request_header, response_header) + +# add ssl materials like key, certificates for the server +ts.addSSLfile("ssl/server.pem") +ts.addSSLfile("ssl/server.key") + +ts.Disk.remap_config.AddLine( + 'map / http://127.0.0.1:{0}'.format(server.Variables.Port) +) + +ts.Disk.ssl_multicert_config.AddLine( + 'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key' +) + +ts.Disk.records_config.update({ + 'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir), + 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), + 'proxy.config.ssl.client.verify.server': 0, + 'proxy.config.ssl.server.cipher_suite': 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:RC4-MD5:AES128-SHA:AES256-SHA:DES-CBC3-SHA!SRP:!DSS:!PSK:!aNULL:!eNULL:!SSLv2', + 'proxy.config.exec_thread.autoconfig.scale': 1.0, + 'proxy.config.ssl.session_cache': 2, + 'proxy.config.ssl.session_cache.size': 4096, + 'proxy.config.ssl.session_cache.num_buckets': 256, + 'proxy.config.ssl.session_cache.skip_cache_on_bucket_contention': 0, + 'proxy.config.ssl.session_cache.timeout': 0, + 'proxy.config.ssl.session_cache.auto_clear': 1, + 'proxy.config.ssl.server.session_ticket.enable': 0, +}) + +# Check that Session-ID is the same on every connection +def checkSession(ev) : + retval = False + f = open(openssl_output, 'r') + err = "Session ids match" + if not f: + err = "Failed to open {0}".format(openssl_output) + return (retval, "Check that session ids match", err) + + content = f.read() + match = re.findall('Session-ID: ([0-9A-F]+)', content) + + if match: + if all(i == j for i, j in zip(match, match[1:])): + err = "{0} reused successfully {1} times".format(match[0], len(match)) + retval = True + else: + err = "Session is not being reused as expected" + else: + err = "Didn't find session id" + return (retval, "Check that session ids match", err) + + +tr = Test.AddTestRun("OpenSSL s_client -reconnect") +tr.Command = 'echo -e "GET / HTTP/1.0\r\n" | openssl s_client -tls1_2 -connect 127.0.0.1:{0} -reconnect'.format(ts.Variables.ssl_port) +tr.ReturnCode = 0 +# time delay as proxy.config.http.wait_for_cache could be broken +tr.Processes.Default.StartBefore(server) +tr.Processes.Default.StartBefore(Test.Processes.ts) +openssl_output = tr.Processes.Default.Streams.stdout.AbsPath +tr.Processes.Default.Streams.All.Content = Testers.Lambda(checkSession) +tr.StillRunningAfter = server From fcd64520dda8cbf80d3523036e87bdb786949512 Mon Sep 17 00:00:00 2001 From: Bryan Call Date: Mon, 16 Sep 2019 16:30:45 -0700 Subject: [PATCH 022/718] Remove hard coded filename in error message (cherry picked from commit b564fc4fc648365f47b3d711bbd9349cb5dc2998) --- iocore/net/YamlSNIConfig.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iocore/net/YamlSNIConfig.cc b/iocore/net/YamlSNIConfig.cc index 7f909ff03aa..4a7cefac65b 100644 --- a/iocore/net/YamlSNIConfig.cc +++ b/iocore/net/YamlSNIConfig.cc @@ -43,7 +43,7 @@ YamlSNIConfig::loader(const char *cfgFilename) } if (!config["sni"]) { - return ts::Errata::Message(1, 1, "malformed ssl_server_name.yaml file; expected a toplevel 'sni' node"); + return ts::Errata::Message(1, 1, "expected a toplevel 'sni' node"); } config = config["sni"]; From e5459ff2971fe838e119fd81d6f35bc4b2aacfc5 Mon Sep 17 00:00:00 2001 From: "Alan M. Carroll" Date: Tue, 24 Sep 2019 09:10:37 -0500 Subject: [PATCH 023/718] Fix debug output for global_user_agent_header. (cherry picked from commit 71fc9d3c016910f0361997e96d944ffa07734ab0) --- proxy/http/HttpTransactHeaders.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/proxy/http/HttpTransactHeaders.cc b/proxy/http/HttpTransactHeaders.cc index f3c9b5b90fe..ec5215a23b0 100644 --- a/proxy/http/HttpTransactHeaders.cc +++ b/proxy/http/HttpTransactHeaders.cc @@ -966,7 +966,8 @@ HttpTransactHeaders::add_global_user_agent_header_to_request(OverridableHttpConf if (http_txn_conf->global_user_agent_header) { MIMEField *ua_field; - Debug("http_trans", "Adding User-Agent: %s", http_txn_conf->global_user_agent_header); + Debug("http_trans", "Adding User-Agent: %.*s", static_cast(http_txn_conf->global_user_agent_header_size), + http_txn_conf->global_user_agent_header); if ((ua_field = header->field_find(MIME_FIELD_USER_AGENT, MIME_LEN_USER_AGENT)) == nullptr) { if (likely((ua_field = header->field_create(MIME_FIELD_USER_AGENT, MIME_LEN_USER_AGENT)) != nullptr)) { header->field_attach(ua_field); From 4629fd73c2a450005aef60d1b1a6ce3785acdfb0 Mon Sep 17 00:00:00 2001 From: Susan Hinrichs Date: Wed, 25 Sep 2019 14:17:24 +0000 Subject: [PATCH 024/718] Clear api set bit to avoid crash in following redirect. (cherry picked from commit b0820c3bfa852596a49092c13cb373651c95964c) --- proxy/http/HttpSM.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc index 346eab562f7..62cbb7513bc 100644 --- a/proxy/http/HttpSM.cc +++ b/proxy/http/HttpSM.cc @@ -7739,6 +7739,9 @@ HttpSM::redirect_request(const char *arg_redirect_url, const int arg_redirect_le t_state.server_info.clear(); t_state.parent_info.clear(); + // Must reset whether the InkAPI has set the destination address + t_state.api_server_addr_set = false; + if (t_state.txn_conf->cache_http) { t_state.cache_info.object_read = nullptr; } From a4c04885455477ae7220c0446ad35cb540cee420 Mon Sep 17 00:00:00 2001 From: Susan Hinrichs Date: Wed, 25 Sep 2019 20:48:48 +0000 Subject: [PATCH 025/718] Clarify docs on the change from redirect_enabled. (cherry picked from commit eebdabba5c02133fd3ff69cafca3e4790c890cd6) --- doc/admin-guide/files/records.config.en.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst index 6fec39e368f..9f3cb66f6ad 100644 --- a/doc/admin-guide/files/records.config.en.rst +++ b/doc/admin-guide/files/records.config.en.rst @@ -1332,6 +1332,8 @@ HTTP Redirection .. note:: When :ts:cv:`proxy.config.http.number_of_redirections` is set to a positive value and |TS| has previously cached a 3XX Redirect response, the cached response will continue to be refreshed and returned until the response is no longer in the cache. + .. note:: In previous versions proxy.config.http.redirection_enabled had to be set to 1 before this setting was evaluated. Now setting :ts:cv:`proxy.config.http.number_of_redirections` to a value greater than zero is sufficient to cause |TS| to follow redirects. + .. ts:cv:: CONFIG proxy.config.http.redirect_host_no_port INT 1 :reloadable: From 106d06abf5be083554a68cfdb4220197e2c33abf Mon Sep 17 00:00:00 2001 From: Bryan Call Date: Wed, 25 Sep 2019 15:12:56 -0700 Subject: [PATCH 026/718] Removed hardcoded sni.yaml configuration filename in logs (cherry picked from commit c4ce6357ef42a72a51cbea948c0ae515c2f2750d) --- iocore/net/SSLSNIConfig.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/iocore/net/SSLSNIConfig.cc b/iocore/net/SSLSNIConfig.cc index 32b88260664..aa3246a42e4 100644 --- a/iocore/net/SSLSNIConfig.cc +++ b/iocore/net/SSLSNIConfig.cc @@ -123,11 +123,11 @@ SNIConfigParams::Initialize() { sni_filename = ats_stringdup(RecConfigReadConfigPath("proxy.config.ssl.servername.filename")); - Note("sni.yaml loading ..."); + Note("%s loading ...", sni_filename); struct stat sbuf; if (stat(sni_filename, &sbuf) == -1 && errno == ENOENT) { - Note("sni.yaml failed to load"); + Note("%s failed to load", sni_filename); Warning("Loading SNI configuration - filename: %s doesn't exist", sni_filename); return 1; } @@ -136,12 +136,12 @@ SNIConfigParams::Initialize() if (!zret.isOK()) { std::stringstream errMsg; errMsg << zret; - Error("sni.yaml failed to load: %s", errMsg.str().c_str()); + Error("%s failed to load: %s", sni_filename, errMsg.str().c_str()); return 1; } loadSNIConfig(); - Note("sni.yaml finished loading"); + Note("%s finished loading", sni_filename); return 0; } From c9cafed86e98f532b53273d16d85b208735242a5 Mon Sep 17 00:00:00 2001 From: David Calavera Date: Fri, 13 Sep 2019 15:07:16 -0700 Subject: [PATCH 027/718] Add documentation for TSHttpTxnRedoCacheLookup Signed-off-by: David Calavera (cherry picked from commit 4a19b32446427b98be43fb357ca7ccffbb9d7a86) --- .../functions/TSHttpTxnRedoCacheLookup.en.rst | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 doc/developer-guide/api/functions/TSHttpTxnRedoCacheLookup.en.rst diff --git a/doc/developer-guide/api/functions/TSHttpTxnRedoCacheLookup.en.rst b/doc/developer-guide/api/functions/TSHttpTxnRedoCacheLookup.en.rst new file mode 100644 index 00000000000..01f174b274a --- /dev/null +++ b/doc/developer-guide/api/functions/TSHttpTxnRedoCacheLookup.en.rst @@ -0,0 +1,48 @@ +.. Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright + ownership. The ASF licenses this file to you under the Apache + License, Version 2.0 (the "License"); you may not use this file + except in compliance with the License. You may obtain a copy of + the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + +.. include:: ../../../common.defs + +.. default-domain:: c + +TSHttpTxnRedoCacheLookup +******************* + +Synopsis +======== + +`#include ` + +.. function:: TSReturnCode TSHttpTxnRedoCacheLookup(TSHttpTxn txnp, const char *url, int length) + +Description +=========== + +Perform a cache lookup with a different url. +This function rewinds the state machine to perform the new cache lookup. The cache_info for the new +url must have been initialized before calling this function. + +If the length argument is -1, this function will take the length from the url argument. + +Notes +===== + +This API may be changed in the future version since it is experimental. + +See Also +======== + +:manpage:`TSAPI(3ts)`, From 9769e17f2c7f6c69df49e74a9e5bff468d6d4eec Mon Sep 17 00:00:00 2001 From: Valentin Gutierrez Date: Tue, 16 Jul 2019 12:06:50 +0700 Subject: [PATCH 028/718] Expose client SSL stats via API & Lua (cherry picked from commit cd92e255380b319e3c3473f14a2209c5487cdbce) --- doc/admin-guide/plugins/lua.en.rst | 80 +++++++++++++++++ include/ts/ts.h | 31 +++++++ plugins/lua/ts_lua_client_request.c | 128 ++++++++++++++++++++++++++++ src/traffic_server/InkAPI.cc | 36 ++++++++ 4 files changed, 275 insertions(+) diff --git a/doc/admin-guide/plugins/lua.en.rst b/doc/admin-guide/plugins/lua.en.rst index 465ee4ca3f4..5686b289342 100644 --- a/doc/admin-guide/plugins/lua.en.rst +++ b/doc/admin-guide/plugins/lua.en.rst @@ -959,6 +959,86 @@ server request, and we should return TS_LUA_REMAP_DID_REMAP(_STOP) in do_remap. :ref:`TOP ` +ts.client_request.get_ssl_reused +----------------------------------------------- +**syntax:** *ts.client_request.get_ssl_reused()* + +**context:** do_remap/do_os_response or do_global_* or later + +**description**: This function can be used to know if the SSL session has been reused (1) or not (0) + +Here is an example: + +:: + + function do_global_read_request() + ssl_reused = ts.client_request.get_ssl_reused() + ts.debug(ssl_reused) -- 0 + end + + +`TOP <#lua-plugin>`_ + +ts.client_request.get_ssl_protocol +----------------------------------------------- +**syntax:** *ts.client_request.get_ssl_protocol()* + +**context:** do_remap/do_os_response or do_global_* or later + +**description**: This function can be used to get the SSL protocol used to communicate with the client + +Here is an example: + +:: + + function do_global_read_request() + ssl_protocol = ts.client_request.get_ssl_protocol() + ts.debug(ssl_protocol) -- TLSv1.2 + end + + +`TOP <#lua-plugin>`_ + +ts.client_request.get_ssl_cipher +----------------------------------------------- +**syntax:** *ts.client_request.get_ssl_cipher()* + +**context:** do_remap/do_os_response or do_global_* or later + +**description**: This function can be used to get the SSL cipher used to communicate with the client + +Here is an example: + +:: + + function do_global_read_request() + ssl_cipher = ts.client_request.get_ssl_cipher() + ts.debug(ssl_cipher) -- ECDHE-ECDSA-AES256-GCM-SHA384 + end + + +`TOP <#lua-plugin>`_ + +ts.client_request.get_ssl_curve +----------------------------------------------- +**syntax:** *ts.client_request.get_ssl_curve()* + +**context:** do_remap/do_os_response or do_global_* or later + +**description**: This function can be used to get the SSL Elliptic curve used to communicate with the client + +Here is an example: + +:: + + function do_global_read_request() + ssl_curve = ts.client_request.get_ssl_curve() + ts.debug(ssl_curve) -- X25519 + end + + +`TOP <#lua-plugin>`_ + ts.http.set_cache_url --------------------- **syntax:** *ts.http.set_cache_url(KEY_URL)* diff --git a/include/ts/ts.h b/include/ts/ts.h index 71a663eb5da..a59897deb73 100644 --- a/include/ts/ts.h +++ b/include/ts/ts.h @@ -2296,6 +2296,37 @@ tsapi int TSHttpTxnServerRespHdrBytesGet(TSHttpTxn txnp); tsapi int64_t TSHttpTxnServerRespBodyBytesGet(TSHttpTxn txnp); tsapi int TSHttpTxnClientRespHdrBytesGet(TSHttpTxn txnp); tsapi int64_t TSHttpTxnClientRespBodyBytesGet(TSHttpTxn txnp); +tsapi int TSVConnIsSslReused(TSVConn sslp); + +/** + Return the current (if set) SSL Cipher. This is still owned by the + core, and must not be free'd. + + @param sslp The connection pointer + + @return the SSL Cipher +*/ +tsapi const char *TSVConnSslCipherGet(TSVConn sslp); + +/** + Return the current (if set) SSL Protocol. This is still owned by the + core, and must not be free'd. + + @param sslp The connection pointer + + @return the SSL Protocol +*/ +tsapi const char *TSVConnSslProtocolGet(TSVConn sslp); + +/** + Return the current (if set) SSL Curve. This is still owned by the + core, and must not be free'd. + + @param txnp the transaction pointer + + @return the SSL Curve +*/ +tsapi const char *TSVConnSslCurveGet(TSVConn sslp); /* NetVC timeout APIs. */ tsapi void TSVConnInactivityTimeoutSet(TSVConn connp, TSHRTime timeout); diff --git a/plugins/lua/ts_lua_client_request.c b/plugins/lua/ts_lua_client_request.c index b851eb19d7e..e5c8c625210 100644 --- a/plugins/lua/ts_lua_client_request.c +++ b/plugins/lua/ts_lua_client_request.c @@ -66,6 +66,15 @@ static int ts_lua_client_request_client_addr_get_port(lua_State *L); static int ts_lua_client_request_client_addr_get_addr(lua_State *L); static int ts_lua_client_request_client_addr_get_incoming_port(lua_State *L); +static void ts_lua_inject_client_request_ssl_reused_api(lua_State *L); +static int ts_lua_client_request_get_ssl_reused(lua_State *L); +static void ts_lua_inject_client_request_ssl_cipher_api(lua_State *L); +static int ts_lua_client_request_get_ssl_cipher(lua_State *L); +static void ts_lua_inject_client_request_ssl_protocol_api(lua_State *L); +static int ts_lua_client_request_get_ssl_protocol(lua_State *L); +static void ts_lua_inject_client_request_ssl_curve_api(lua_State *L); +static int ts_lua_client_request_get_ssl_curve(lua_State *L); + void ts_lua_inject_client_request_api(lua_State *L) { @@ -82,6 +91,10 @@ ts_lua_inject_client_request_api(lua_State *L) ts_lua_inject_client_request_version_api(L); ts_lua_inject_client_request_body_size_api(L); ts_lua_inject_client_request_header_size_api(L); + ts_lua_inject_client_request_ssl_reused_api(L); + ts_lua_inject_client_request_ssl_cipher_api(L); + ts_lua_inject_client_request_ssl_protocol_api(L); + ts_lua_inject_client_request_ssl_curve_api(L); lua_setfield(L, -2, "client_request"); } @@ -924,3 +937,118 @@ ts_lua_client_request_get_header_size(lua_State *L) return 1; } + +static void +ts_lua_inject_client_request_ssl_reused_api(lua_State *L) +{ + lua_pushcfunction(L, ts_lua_client_request_get_ssl_reused); + lua_setfield(L, -2, "get_ssl_reused"); +} + +static int +ts_lua_client_request_get_ssl_reused(lua_State *L) +{ + int ssl_reused = 0; + ts_lua_http_ctx *http_ctx; + TSHttpSsn ssnp; + TSVConn client_conn; + + GET_HTTP_CONTEXT(http_ctx, L); + ssnp = TSHttpTxnSsnGet(http_ctx->txnp); + client_conn = TSHttpSsnClientVConnGet(ssnp); + + if (TSVConnIsSsl(client_conn)) { + ssl_reused = TSVConnIsSslReused(client_conn); + } + + lua_pushnumber(L, ssl_reused); + + return 1; +} + +static void +ts_lua_inject_client_request_ssl_cipher_api(lua_State *L) +{ + lua_pushcfunction(L, ts_lua_client_request_get_ssl_cipher); + lua_setfield(L, -2, "get_ssl_cipher"); +} + +static int +ts_lua_client_request_get_ssl_cipher(lua_State *L) +{ + const char *ssl_cipher = "-"; + ts_lua_http_ctx *http_ctx; + TSHttpSsn ssnp; + TSVConn client_conn; + + GET_HTTP_CONTEXT(http_ctx, L); + + ssnp = TSHttpTxnSsnGet(http_ctx->txnp); + client_conn = TSHttpSsnClientVConnGet(ssnp); + + if (TSVConnIsSsl(client_conn)) { + ssl_cipher = TSVConnSslCipherGet(client_conn); + } + + lua_pushstring(L, ssl_cipher); + + return 1; +} + +static void +ts_lua_inject_client_request_ssl_protocol_api(lua_State *L) +{ + lua_pushcfunction(L, ts_lua_client_request_get_ssl_protocol); + lua_setfield(L, -2, "get_ssl_protocol"); +} + +static int +ts_lua_client_request_get_ssl_protocol(lua_State *L) +{ + const char *ssl_protocol = "-"; + ts_lua_http_ctx *http_ctx; + TSHttpSsn ssnp; + TSVConn client_conn; + + GET_HTTP_CONTEXT(http_ctx, L); + + ssnp = TSHttpTxnSsnGet(http_ctx->txnp); + client_conn = TSHttpSsnClientVConnGet(ssnp); + + if (TSVConnIsSsl(client_conn)) { + ssl_protocol = TSVConnSslProtocolGet(client_conn); + } + + lua_pushstring(L, ssl_protocol); + + return 1; +} + +static void +ts_lua_inject_client_request_ssl_curve_api(lua_State *L) +{ + lua_pushcfunction(L, ts_lua_client_request_get_ssl_curve); + lua_setfield(L, -2, "get_ssl_curve"); +} + +static int +ts_lua_client_request_get_ssl_curve(lua_State *L) +{ + const char *ssl_curve = "-"; + ts_lua_http_ctx *http_ctx; + TSHttpSsn ssnp; + TSVConn client_conn; + + GET_HTTP_CONTEXT(http_ctx, L); + + ssnp = TSHttpTxnSsnGet(http_ctx->txnp); + client_conn = TSHttpSsnClientVConnGet(ssnp); + + if (TSVConnIsSsl(client_conn)) { + ssl_curve = TSVConnSslCurveGet(client_conn); + } + + lua_pushstring(L, ssl_curve); + + return 1; +} diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc index 7fa63d003c1..cd4059e1a59 100644 --- a/src/traffic_server/InkAPI.cc +++ b/src/traffic_server/InkAPI.cc @@ -6487,6 +6487,42 @@ TSHttpTxnClientRespBodyBytesGet(TSHttpTxn txnp) return sm->client_response_body_bytes; } +int +TSVConnIsSslReused(TSVConn sslp) +{ + NetVConnection *vc = reinterpret_cast(sslp); + SSLNetVConnection *ssl_vc = dynamic_cast(vc); + + return ssl_vc ? ssl_vc->getSSLSessionCacheHit() : 0; +} + +const char * +TSVConnSslCipherGet(TSVConn sslp) +{ + NetVConnection *vc = reinterpret_cast(sslp); + SSLNetVConnection *ssl_vc = dynamic_cast(vc); + + return ssl_vc ? ssl_vc->getSSLCipherSuite() : nullptr; +} + +const char * +TSVConnSslProtocolGet(TSVConn sslp) +{ + NetVConnection *vc = reinterpret_cast(sslp); + SSLNetVConnection *ssl_vc = dynamic_cast(vc); + + return ssl_vc ? ssl_vc->getSSLProtocol() : nullptr; +} + +const char * +TSVConnSslCurveGet(TSVConn sslp) +{ + NetVConnection *vc = reinterpret_cast(sslp); + SSLNetVConnection *ssl_vc = dynamic_cast(vc); + + return ssl_vc ? ssl_vc->getSSLCurve() : nullptr; +} + int TSHttpTxnPushedRespHdrBytesGet(TSHttpTxn txnp) { From 9bd3fad61ed2e7f096f63cefd952aee410cd5e18 Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Tue, 3 Sep 2019 09:05:56 +0900 Subject: [PATCH 029/718] Ran clang-format (cherry picked from commit aa58b6eb812319c7cde8be9e8d21ff939f9175f8) --- plugins/cachekey/configs.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/cachekey/configs.h b/plugins/cachekey/configs.h index 26cd9beb9f3..3ccf2a1b29c 100644 --- a/plugins/cachekey/configs.h +++ b/plugins/cachekey/configs.h @@ -226,10 +226,10 @@ class Configs */ bool loadClassifiers(const String &args, bool blacklist = true); - bool _prefixToBeRemoved = false; /**< @brief instructs the prefix (i.e. host:port) not to added to the cache key */ - bool _pathToBeRemoved = false; /**< @brief instructs the path not to added to the cache key */ - bool _canonicalPrefix = false; /**< @brief keep the URI scheme and authority element used as input to transforming into key */ - String _separator = "/"; /**< @brief a separator used to separate the cache key elements extracted from the URI */ - CacheKeyUriType _uriType = REMAP; /**< @brief shows which URI the cache key will be based on */ + bool _prefixToBeRemoved = false; /**< @brief instructs the prefix (i.e. host:port) not to added to the cache key */ + bool _pathToBeRemoved = false; /**< @brief instructs the path not to added to the cache key */ + bool _canonicalPrefix = false; /**< @brief keep the URI scheme and authority element used as input to transforming into key */ + String _separator = "/"; /**< @brief a separator used to separate the cache key elements extracted from the URI */ + CacheKeyUriType _uriType = REMAP; /**< @brief shows which URI the cache key will be based on */ CacheKeyKeyType _keyType = CACHE_KEY; /**< @brief target URI to be modified, cache key or paren selection */ }; From 56659933c36ac3e76fc80f8bcd43166be00330f6 Mon Sep 17 00:00:00 2001 From: Valentin Gutierrez Date: Thu, 29 Aug 2019 00:03:36 +0800 Subject: [PATCH 030/718] Provide stats for the recently introduced HTTP/2 rate limits Provide stats for the limits introduced by 9c09dbc11 (cherry picked from commit 5ec81125bd70d31f545cf959b65c4e929d26a192) --- .../statistics/core/http-connection.en.rst | 42 +++++++++++++++++++ proxy/http2/HTTP2.cc | 21 ++++++++++ proxy/http2/HTTP2.h | 6 +++ proxy/http2/Http2ConnectionState.cc | 6 +++ 4 files changed, 75 insertions(+) diff --git a/doc/admin-guide/monitoring/statistics/core/http-connection.en.rst b/doc/admin-guide/monitoring/statistics/core/http-connection.en.rst index 411881fa104..42c680e1f4e 100644 --- a/doc/admin-guide/monitoring/statistics/core/http-connection.en.rst +++ b/doc/admin-guide/monitoring/statistics/core/http-connection.en.rst @@ -204,3 +204,45 @@ HTTP/2 Represents the total number of closed HTTP/2 connections with high error rate which is configured by :ts:cv:`proxy.config.http2.stream_error_rate_threshold`. + +.. ts:stat:: global proxy.process.http2.max_settings_per_frame_exceeded integer + :type: counter + + Represents the total number of closed HTTP/2 connections for exceeding the + maximum allowed number of settings per frame limit which is configured by + :ts:cv:`proxy.config.http2.max_settings_per_frame`. + +.. ts:stat:: global proxy.process.http2.max_settings_per_minute_exceeded integer + :type: counter + + Represents the total number of closed HTTP/2 connections for exceeding the + maximum allowed number of settings per minute limit which is configured by + :ts:cv:`proxy.config.http2.max_settings_per_minute`. + +.. ts:stat:: global proxy.process.http2.max_settings_frames_per_minute_exceeded integer + :type: counter + + Represents the total number of closed HTTP/2 connections for exceeding the + maximum allowed number of settings frames per minute limit which is configured by + :ts:cv:`proxy.config.http2.max_settings_frames_per_minute`. + +.. ts:stat:: global proxy.process.http2.max_ping_frames_per_minute_exceeded integer + :type: counter + + Represents the total number of closed HTTP/2 connections for exceeding the + maximum allowed number of ping frames per minute limit which is configured by + :ts:cv:`proxy.config.http2.max_ping_frames_per_minute`. + +.. ts:stat:: global proxy.process.http2.max_priority_frames_per_minute_exceeded integer + :type: counter + + Represents the total number of closed HTTP/2 connections for exceeding the + maximum allowed number of priority frames per minute limit which is configured by + :ts:cv:`proxy.config.http2.max_priority_frames_per_minute`. + +.. ts:stat:: global proxy.process.http2.insufficient_avg_window_update integer + :type: counter + + Represents the total number of closed HTTP/2 connections for not reaching the + minimum average window increment limit which is configured by + :ts:cv:`proxy.config.http2.min_avg_window_update`. diff --git a/proxy/http2/HTTP2.cc b/proxy/http2/HTTP2.cc index 81f741d6459..6e427bbd188 100644 --- a/proxy/http2/HTTP2.cc +++ b/proxy/http2/HTTP2.cc @@ -62,6 +62,15 @@ static const char *const HTTP2_STAT_SESSION_DIE_INACTIVE_NAME = "pro static const char *const HTTP2_STAT_SESSION_DIE_EOS_NAME = "proxy.process.http2.session_die_eos"; static const char *const HTTP2_STAT_SESSION_DIE_ERROR_NAME = "proxy.process.http2.session_die_error"; static const char *const HTTP2_STAT_SESSION_DIE_HIGH_ERROR_RATE_NAME = "proxy.process.http2.session_die_high_error_rate"; +static const char *const HTTP2_STAT_MAX_SETTINGS_PER_FRAME_EXCEEDED_NAME = "proxy.process.http2.max_settings_per_frame_exceeded"; +static const char *const HTTP2_STAT_MAX_SETTINGS_PER_MINUTE_EXCEEDED_NAME = "proxy.process.http2.max_settings_per_minute_exceeded"; +static const char *const HTTP2_STAT_MAX_SETTINGS_FRAMES_PER_MINUTE_EXCEEDED_NAME = + "proxy.process.http2.max_settings_frames_per_minute_exceeded"; +static const char *const HTTP2_STAT_MAX_PING_FRAMES_PER_MINUTE_EXCEEDED_NAME = + "proxy.process.http2.max_ping_frames_per_minute_exceeded"; +static const char *const HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED_NAME = + "proxy.process.http2.max_priority_frames_per_minute_exceeded"; +static const char *const HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE_NAME = "proxy.process.http2.insufficient_avg_window_update"; union byte_pointer { byte_pointer(void *p) : ptr(p) {} @@ -820,6 +829,18 @@ Http2::init() static_cast(HTTP2_STAT_SESSION_DIE_ERROR), RecRawStatSyncSum); RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_SESSION_DIE_HIGH_ERROR_RATE_NAME, RECD_INT, RECP_PERSISTENT, static_cast(HTTP2_STAT_SESSION_DIE_HIGH_ERROR_RATE), RecRawStatSyncSum); + RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_MAX_SETTINGS_PER_FRAME_EXCEEDED_NAME, RECD_INT, RECP_PERSISTENT, + static_cast(HTTP2_STAT_MAX_SETTINGS_PER_FRAME_EXCEEDED), RecRawStatSyncSum); + RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_MAX_SETTINGS_PER_MINUTE_EXCEEDED_NAME, RECD_INT, RECP_PERSISTENT, + static_cast(HTTP2_STAT_MAX_SETTINGS_PER_MINUTE_EXCEEDED), RecRawStatSyncSum); + RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_MAX_SETTINGS_FRAMES_PER_MINUTE_EXCEEDED_NAME, RECD_INT, RECP_PERSISTENT, + static_cast(HTTP2_STAT_MAX_SETTINGS_FRAMES_PER_MINUTE_EXCEEDED), RecRawStatSyncSum); + RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_MAX_PING_FRAMES_PER_MINUTE_EXCEEDED_NAME, RECD_INT, RECP_PERSISTENT, + static_cast(HTTP2_STAT_MAX_PING_FRAMES_PER_MINUTE_EXCEEDED), RecRawStatSyncSum); + RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED_NAME, RECD_INT, RECP_PERSISTENT, + static_cast(HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED), RecRawStatSyncSum); + RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE_NAME, RECD_INT, RECP_PERSISTENT, + static_cast(HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE), RecRawStatSyncSum); } #if TS_HAS_TESTS diff --git a/proxy/http2/HTTP2.h b/proxy/http2/HTTP2.h index 85e2669bf0e..083eda44e88 100644 --- a/proxy/http2/HTTP2.h +++ b/proxy/http2/HTTP2.h @@ -84,6 +84,12 @@ enum { HTTP2_STAT_SESSION_DIE_EOS, HTTP2_STAT_SESSION_DIE_ERROR, HTTP2_STAT_SESSION_DIE_HIGH_ERROR_RATE, + HTTP2_STAT_MAX_SETTINGS_PER_FRAME_EXCEEDED, + HTTP2_STAT_MAX_SETTINGS_PER_MINUTE_EXCEEDED, + HTTP2_STAT_MAX_SETTINGS_FRAMES_PER_MINUTE_EXCEEDED, + HTTP2_STAT_MAX_PING_FRAMES_PER_MINUTE_EXCEEDED, + HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED, + HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE, HTTP2_N_STATS // Terminal counter, NOT A STAT INDEX. }; diff --git a/proxy/http2/Http2ConnectionState.cc b/proxy/http2/Http2ConnectionState.cc index d27f3818585..780291a76e3 100644 --- a/proxy/http2/Http2ConnectionState.cc +++ b/proxy/http2/Http2ConnectionState.cc @@ -421,6 +421,7 @@ rcv_priority_frame(Http2ConnectionState &cstate, const Http2Frame &frame) cstate.increment_received_priority_frame_count(); // Close this conection if its priority frame count received exceeds a limit if (cstate.get_received_priority_frame_count() > Http2::max_priority_frames_per_minute) { + HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED, this_ethread()); Http2StreamDebug(cstate.ua_session, stream_id, "Observed too frequent priority changes: %u priority changes within a last minute", cstate.get_received_priority_frame_count()); @@ -537,6 +538,7 @@ rcv_settings_frame(Http2ConnectionState &cstate, const Http2Frame &frame) cstate.increment_received_settings_frame_count(); // Close this conection if its SETTINGS frame count exceeds a limit if (cstate.get_received_settings_frame_count() > Http2::max_settings_frames_per_minute) { + HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_MAX_SETTINGS_FRAMES_PER_MINUTE_EXCEEDED, this_ethread()); Http2StreamDebug(cstate.ua_session, stream_id, "Observed too frequent SETTINGS frames: %u frames within a last minute", cstate.get_received_settings_frame_count()); return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM, @@ -575,6 +577,7 @@ rcv_settings_frame(Http2ConnectionState &cstate, const Http2Frame &frame) uint32_t n_settings = 0; while (nbytes < frame.header().length) { if (n_settings >= Http2::max_settings_per_frame) { + HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_MAX_SETTINGS_PER_FRAME_EXCEEDED, this_ethread()); Http2StreamDebug(cstate.ua_session, stream_id, "Observed too many settings in a frame"); return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM, "recv settings too many settings in a frame"); @@ -615,6 +618,7 @@ rcv_settings_frame(Http2ConnectionState &cstate, const Http2Frame &frame) cstate.increment_received_settings_count(n_settings); // Close this conection if its settings count received exceeds a limit if (cstate.get_received_settings_count() > Http2::max_settings_per_minute) { + HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_MAX_SETTINGS_PER_MINUTE_EXCEEDED, this_ethread()); Http2StreamDebug(cstate.ua_session, stream_id, "Observed too frequent setting changes: %u settings within a last minute", cstate.get_received_settings_count()); return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM, @@ -668,6 +672,7 @@ rcv_ping_frame(Http2ConnectionState &cstate, const Http2Frame &frame) cstate.increment_received_ping_frame_count(); // Close this conection if its ping count received exceeds a limit if (cstate.get_received_ping_frame_count() > Http2::max_ping_frames_per_minute) { + HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_MAX_PING_FRAMES_PER_MINUTE_EXCEEDED, this_ethread()); Http2StreamDebug(cstate.ua_session, stream_id, "Observed too frequent PING frames: %u PING frames within a last minute", cstate.get_received_ping_frame_count()); return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM, @@ -1998,6 +2003,7 @@ Http2ConnectionState::increment_client_rwnd(size_t amount) double sum = std::accumulate(this->_recent_rwnd_increment.begin(), this->_recent_rwnd_increment.end(), 0.0); double avg = sum / this->_recent_rwnd_increment.size(); if (avg < Http2::min_avg_window_update) { + HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE, this_ethread()); return Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM; } return Http2ErrorCode::HTTP2_ERROR_NO_ERROR; From f9e69ef10b94290a3ce1ed015fc505c68698d14f Mon Sep 17 00:00:00 2001 From: Valentin Gutierrez Date: Wed, 28 Aug 2019 13:16:33 +0800 Subject: [PATCH 031/718] Allow disabling HTTP/2 priority frames limit (cherry picked from commit f2ebbcee400c3c91aa789382d7f7243797ed733c) --- doc/admin-guide/files/records.config.en.rst | 4 +++- proxy/http2/Http2ConnectionState.cc | 11 ++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst index 9f3cb66f6ad..e4d94c6f72d 100644 --- a/doc/admin-guide/files/records.config.en.rst +++ b/doc/admin-guide/files/records.config.en.rst @@ -3660,7 +3660,9 @@ HTTP/2 Configuration Specifies how many number of PRIORITY frames |TS| receives for a minute at maximum. Clients exceeded this limit will be immediately disconnected with an error - code of ENHANCE_YOUR_CALM. + code of ENHANCE_YOUR_CALM. If this is set to 0, the limit logic is disabled. + This limit only will be enforced if :ts:cv:`proxy.config.http2.stream_priority_enabled` + is set to 1. .. ts:cv:: CONFIG proxy.config.http2.min_avg_window_update FLOAT 2560.0 :reloadable: diff --git a/proxy/http2/Http2ConnectionState.cc b/proxy/http2/Http2ConnectionState.cc index 780291a76e3..ddf39ed4750 100644 --- a/proxy/http2/Http2ConnectionState.cc +++ b/proxy/http2/Http2ConnectionState.cc @@ -417,10 +417,15 @@ rcv_priority_frame(Http2ConnectionState &cstate, const Http2Frame &frame) "PRIORITY frame depends on itself"); } + if (!Http2::stream_priority_enabled) { + return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE); + } + // Update PRIORITY frame count per minute cstate.increment_received_priority_frame_count(); // Close this conection if its priority frame count received exceeds a limit - if (cstate.get_received_priority_frame_count() > Http2::max_priority_frames_per_minute) { + if (Http2::max_priority_frames_per_minute != 0 && + cstate.get_received_priority_frame_count() > Http2::max_priority_frames_per_minute) { HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED, this_ethread()); Http2StreamDebug(cstate.ua_session, stream_id, "Observed too frequent priority changes: %u priority changes within a last minute", @@ -429,10 +434,6 @@ rcv_priority_frame(Http2ConnectionState &cstate, const Http2Frame &frame) "recv priority too frequent priority changes"); } - if (!Http2::stream_priority_enabled) { - return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE); - } - Http2StreamDebug(cstate.ua_session, stream_id, "PRIORITY - dep: %d, weight: %d, excl: %d, tree size: %d", priority.stream_dependency, priority.weight, priority.exclusive_flag, cstate.dependency_tree->size()); From a4090bfa6b32a075d573ab7e7ddfb967708621ca Mon Sep 17 00:00:00 2001 From: Sudheer Vinukonda Date: Tue, 3 Sep 2019 14:05:44 -0700 Subject: [PATCH 032/718] Update Server IP in Transaction when attaching a session from the pool IP may be mismatched when using Host based matching as the DNS IP is ignored which may cause txn logging (nhi) to be inaccurate Fix build (cherry picked from commit 9de4f2481556b3d7eca9c63813c5d4a8be23cbf1) --- proxy/http/HttpSM.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc index 62cbb7513bc..62775ce0c7a 100644 --- a/proxy/http/HttpSM.cc +++ b/proxy/http/HttpSM.cc @@ -5842,6 +5842,17 @@ HttpSM::attach_server_session(Http1ServerSession *s) hsm_release_assert(s->state == HSS_ACTIVE); server_session = s; server_transact_count = server_session->transact_count++; + + // update the dst_addr when using an existing session + // for e.g using Host based session pools may ignore the DNS IP + if (!ats_ip_addr_eq(&t_state.current.server->dst_addr, &server_session->get_server_ip())) { + ip_port_text_buffer ipb1, ipb2; + Debug("http_ss", "updating ip when attaching server session from %s to %s", + ats_ip_ntop(&t_state.current.server->dst_addr.sa, ipb1, sizeof(ipb1)), + ats_ip_ntop(&server_session->get_server_ip(), ipb2, sizeof(ipb2))); + ats_ip_copy(&t_state.current.server->dst_addr, &server_session->get_server_ip()); + } + // Propagate the per client IP debugging if (ua_txn) { s->get_netvc()->control_flags.set_flags(get_cont_flags().get_flags()); From 59b78e5c297899d3a203a448bf2ed81f1e0f2406 Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Tue, 20 Aug 2019 10:11:04 +0900 Subject: [PATCH 033/718] Convert check programs in iocore/eventsystem/ into Catch based unit tests (cherry picked from commit 39522703d7b9fdf4834b797e2d812f37f8970f71) --- .gitignore | 4 +- iocore/eventsystem/Makefile.am | 32 +++--- iocore/eventsystem/test_Buffer.cc | 64 ----------- iocore/eventsystem/test_Event.cc | 83 -------------- .../unit_tests/test_EventSystem.cc | 101 ++++++++++++++++++ .../eventsystem/unit_tests/test_IOBuffer.cc | 72 +++++++++++++ 6 files changed, 189 insertions(+), 167 deletions(-) delete mode 100644 iocore/eventsystem/test_Buffer.cc delete mode 100644 iocore/eventsystem/test_Event.cc create mode 100644 iocore/eventsystem/unit_tests/test_EventSystem.cc create mode 100644 iocore/eventsystem/unit_tests/test_IOBuffer.cc diff --git a/.gitignore b/.gitignore index c683ae3728b..23cdc5dd8b3 100644 --- a/.gitignore +++ b/.gitignore @@ -117,8 +117,8 @@ iocore/net/quic/test_QUICType iocore/net/quic/test_QUICTypeUtil iocore/net/quic/test_QUICVersionNegotiator iocore/aio/test_AIO -iocore/eventsystem/test_Buffer -iocore/eventsystem/test_Event +iocore/eventsystem/test_IOBuffer +iocore/eventsystem/test_EventSystem iocore/eventsystem/test_MIOBufferWriter iocore/hostdb/test_RefCountCache diff --git a/iocore/eventsystem/Makefile.am b/iocore/eventsystem/Makefile.am index 369bf55bb23..970d0ba7abe 100644 --- a/iocore/eventsystem/Makefile.am +++ b/iocore/eventsystem/Makefile.am @@ -69,7 +69,8 @@ libinkevent_a_SOURCES = \ UnixEvent.cc \ UnixEventProcessor.cc -check_PROGRAMS = test_Buffer test_Event \ +check_PROGRAMS = test_IOBuffer \ + test_EventSystem \ test_MIOBufferWriter test_LD_FLAGS = \ @@ -85,6 +86,7 @@ test_CPP_FLAGS = \ -I$(abs_top_srcdir)/proxy/logging \ -I$(abs_top_srcdir)/mgmt \ -I$(abs_top_srcdir)/mgmt/utils \ + -I$(abs_top_srcdir)/tests/include \ @OPENSSL_INCLUDES@ test_LD_ADD = \ @@ -92,29 +94,23 @@ test_LD_ADD = \ $(top_builddir)/lib/records/librecords_p.a \ $(top_builddir)/mgmt/libmgmt_p.la \ $(top_builddir)/iocore/eventsystem/libinkevent.a \ - $(top_builddir)/src/tscore/libtscore.la $(top_builddir)/src/tscpp/util/libtscpputil.la \ + $(top_builddir)/src/tscore/libtscore.la \ + $(top_builddir)/src/tscpp/util/libtscpputil.la \ $(top_builddir)/proxy/shared/libUglyLogStubs.a \ @HWLOC_LIBS@ -test_Buffer_SOURCES = \ - test_Buffer.cc - -test_Event_SOURCES = \ - test_Event.cc - -test_Buffer_CPPFLAGS = $(test_CPP_FLAGS) -test_Event_CPPFLAGS = $(test_CPP_FLAGS) - -test_Buffer_LDFLAGS = $(test_LD_FLAGS) -test_Event_LDFLAGS = $(test_LD_FLAGS) - -test_Buffer_LDADD = $(test_LD_ADD) -test_Event_LDADD = $(test_LD_ADD) +test_EventSystem_SOURCES = unit_tests/test_EventSystem.cc +test_EventSystem_CPPFLAGS = $(test_CPP_FLAGS) +test_EventSystem_LDFLAGS = $(test_LD_FLAGS) +test_EventSystem_LDADD = $(test_LD_ADD) +test_IOBuffer_SOURCES = unit_tests/test_IOBuffer.cc +test_IOBuffer_CPPFLAGS = $(test_CPP_FLAGS) +test_IOBuffer_LDFLAGS = $(test_LD_FLAGS) +test_IOBuffer_LDADD = $(test_LD_ADD) test_MIOBufferWriter_SOURCES = unit_tests/test_MIOBufferWriter.cc - -test_MIOBufferWriter_CPPFLAGS = $(test_CPP_FLAGS) -I$(abs_top_srcdir)/tests/include +test_MIOBufferWriter_CPPFLAGS = $(test_CPP_FLAGS) test_MIOBufferWriter_LDFLAGS = $(test_LD_FLAGS) test_MIOBufferWriter_LDADD = $(test_LD_ADD) diff --git a/iocore/eventsystem/test_Buffer.cc b/iocore/eventsystem/test_Buffer.cc deleted file mode 100644 index ccef1036864..00000000000 --- a/iocore/eventsystem/test_Buffer.cc +++ /dev/null @@ -1,64 +0,0 @@ -/** @file - - A brief file description - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "I_EventSystem.h" -#include "tscore/I_Layout.h" -#include "tscore/ink_string.h" - -#include "diags.i" - -#define TEST_TIME_SECOND 60 -#define TEST_THREADS 2 - -int -main(int /* argc ATS_UNUSED */, const char * /* argv ATS_UNUSED */ []) -{ - RecModeT mode_type = RECM_STAND_ALONE; - - Layout::create(); - init_diags("", nullptr); - RecProcessInit(mode_type); - - ink_event_system_init(EVENT_SYSTEM_MODULE_PUBLIC_VERSION); - eventProcessor.start(TEST_THREADS); - - Thread *main_thread = new EThread; - main_thread->set_specific(); - - for (unsigned i = 0; i < 100; ++i) { - MIOBuffer *b1 = new_MIOBuffer(default_large_iobuffer_size); - IOBufferReader *b1reader ATS_UNUSED = b1->alloc_reader(); - b1->fill(b1->write_avail()); - - MIOBuffer *b2 = new_MIOBuffer(default_large_iobuffer_size); - IOBufferReader *b2reader ATS_UNUSED = b2->alloc_reader(); - b2->fill(b2->write_avail()); - - // b1->write(b2reader, 2*1024); - - free_MIOBuffer(b2); - free_MIOBuffer(b1); - } - - exit(0); -} diff --git a/iocore/eventsystem/test_Event.cc b/iocore/eventsystem/test_Event.cc deleted file mode 100644 index 78c47bb3624..00000000000 --- a/iocore/eventsystem/test_Event.cc +++ /dev/null @@ -1,83 +0,0 @@ -/** @file - - A brief file description - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "I_EventSystem.h" -#include "tscore/I_Layout.h" -#include "tscore/TSSystemState.h" - -#include "diags.i" - -#define TEST_TIME_SECOND 60 -#define TEST_THREADS 2 - -static int count; - -struct alarm_printer : public Continuation { - alarm_printer(ProxyMutex *m) : Continuation(m) { SET_HANDLER(&alarm_printer::dummy_function); } - int - dummy_function(int /* event ATS_UNUSED */, Event * /* e ATS_UNUSED */) - { - ink_atomic_increment((int *)&count, 1); - printf("Count = %d\n", count); - return 0; - } -}; -struct process_killer : public Continuation { - process_killer(ProxyMutex *m) : Continuation(m) { SET_HANDLER(&process_killer::kill_function); } - int - kill_function(int /* event ATS_UNUSED */, Event * /* e ATS_UNUSED */) - { - printf("Count is %d \n", count); - if (count <= 0) { - exit(1); - } - if (count > TEST_TIME_SECOND * TEST_THREADS) { - exit(1); - } - exit(0); - return 0; - } -}; - -int -main(int /* argc ATS_UNUSED */, const char * /* argv ATS_UNUSED */ []) -{ - RecModeT mode_type = RECM_STAND_ALONE; - count = 0; - - Layout::create(); - init_diags("", nullptr); - RecProcessInit(mode_type); - - ink_event_system_init(EVENT_SYSTEM_MODULE_PUBLIC_VERSION); - eventProcessor.start(TEST_THREADS, 1048576); // Hardcoded stacksize at 1MB - - alarm_printer *alrm = new alarm_printer(new_ProxyMutex()); - process_killer *killer = new process_killer(new_ProxyMutex()); - eventProcessor.schedule_in(killer, HRTIME_SECONDS(10)); - eventProcessor.schedule_every(alrm, HRTIME_SECONDS(1)); - while (!TSSystemState::is_event_system_shut_down()) { - sleep(1); - } - return 0; -} diff --git a/iocore/eventsystem/unit_tests/test_EventSystem.cc b/iocore/eventsystem/unit_tests/test_EventSystem.cc new file mode 100644 index 00000000000..75faad2718d --- /dev/null +++ b/iocore/eventsystem/unit_tests/test_EventSystem.cc @@ -0,0 +1,101 @@ +/** @file + + Catch based unit tests for EventSystem + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#define CATCH_CONFIG_MAIN +#include "catch.hpp" + +#include "I_EventSystem.h" +#include "tscore/I_Layout.h" +#include "tscore/TSSystemState.h" + +#include "diags.i" + +#define TEST_TIME_SECOND 60 +#define TEST_THREADS 2 + +TEST_CASE("EventSystem", "[iocore]") +{ + static int count; + + struct alarm_printer : public Continuation { + alarm_printer(ProxyMutex *m) : Continuation(m) { SET_HANDLER(&alarm_printer::dummy_function); } + + int + dummy_function(int /* event ATS_UNUSED */, Event * /* e ATS_UNUSED */) + { + ink_atomic_increment((int *)&count, 1); + + EThread *e = this_ethread(); + printf("thread=%d (%p) count = %d\n", e->id, e, count); + + return 0; + } + }; + + struct process_killer : public Continuation { + process_killer(ProxyMutex *m) : Continuation(m) { SET_HANDLER(&process_killer::kill_function); } + + int + kill_function(int /* event ATS_UNUSED */, Event * /* e ATS_UNUSED */) + { + EThread *e = this_ethread(); + printf("thread=%d (%p) count is %d\n", e->id, e, count); + + REQUIRE(count > 0); + REQUIRE(count <= TEST_TIME_SECOND * TEST_THREADS); + + TSSystemState::shut_down_event_system(); + + return 0; + } + }; + + alarm_printer *alrm = new alarm_printer(new_ProxyMutex()); + process_killer *killer = new process_killer(new_ProxyMutex()); + eventProcessor.schedule_in(killer, HRTIME_SECONDS(10)); + eventProcessor.schedule_every(alrm, HRTIME_SECONDS(1)); + + while (!TSSystemState::is_event_system_shut_down()) { + sleep(1); + } +} + +struct EventProcessorListener : Catch::TestEventListenerBase { + using TestEventListenerBase::TestEventListenerBase; + + void + testRunStarting(Catch::TestRunInfo const &testRunInfo) override + { + Layout::create(); + init_diags("", nullptr); + RecProcessInit(RECM_STAND_ALONE); + + ink_event_system_init(EVENT_SYSTEM_MODULE_PUBLIC_VERSION); + eventProcessor.start(TEST_THREADS, 1048576); // Hardcoded stacksize at 1MB + + EThread *main_thread = new EThread; + main_thread->set_specific(); + } +}; + +CATCH_REGISTER_LISTENER(EventProcessorListener); diff --git a/iocore/eventsystem/unit_tests/test_IOBuffer.cc b/iocore/eventsystem/unit_tests/test_IOBuffer.cc new file mode 100644 index 00000000000..d3fd5d3ac9a --- /dev/null +++ b/iocore/eventsystem/unit_tests/test_IOBuffer.cc @@ -0,0 +1,72 @@ +/** @file + + Catch based unit tests for IOBuffer + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#define CATCH_CONFIG_MAIN +#include "catch.hpp" + +#include "I_EventSystem.h" +#include "tscore/I_Layout.h" + +#include "diags.i" + +#define TEST_THREADS 1 + +TEST_CASE("MIOBuffer", "[iocore]") +{ + for (unsigned i = 0; i < 100; ++i) { + MIOBuffer *b1 = new_MIOBuffer(default_small_iobuffer_size); + int64_t len1 = b1->write_avail(); + IOBufferReader *b1reader = b1->alloc_reader(); + b1->fill(len1); + CHECK(b1reader->read_avail() == len1); + + MIOBuffer *b2 = new_MIOBuffer(default_large_iobuffer_size); + int64_t len2 = b1->write_avail(); + IOBufferReader *b2reader = b2->alloc_reader(); + b2->fill(len2); + CHECK(b2reader->read_avail() == len2); + + free_MIOBuffer(b2); + free_MIOBuffer(b1); + } +} + +struct EventProcessorListener : Catch::TestEventListenerBase { + using TestEventListenerBase::TestEventListenerBase; + + void + testRunStarting(Catch::TestRunInfo const &testRunInfo) override + { + Layout::create(); + init_diags("", nullptr); + RecProcessInit(RECM_STAND_ALONE); + + ink_event_system_init(EVENT_SYSTEM_MODULE_PUBLIC_VERSION); + eventProcessor.start(TEST_THREADS); + + EThread *main_thread = new EThread; + main_thread->set_specific(); + } +}; + +CATCH_REGISTER_LISTENER(EventProcessorListener); From d6d35100b9eb5cc71db3a1b908395062986484cf Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Fri, 23 Aug 2019 15:06:03 +0900 Subject: [PATCH 034/718] Add unit tests for MIOBuffer:write() (cherry picked from commit 6751fd0d41f083d6481a1387b89bb55f0d4c7261) --- .../eventsystem/unit_tests/test_IOBuffer.cc | 159 ++++++++++++++++-- 1 file changed, 143 insertions(+), 16 deletions(-) diff --git a/iocore/eventsystem/unit_tests/test_IOBuffer.cc b/iocore/eventsystem/unit_tests/test_IOBuffer.cc index d3fd5d3ac9a..f380bf017bc 100644 --- a/iocore/eventsystem/unit_tests/test_IOBuffer.cc +++ b/iocore/eventsystem/unit_tests/test_IOBuffer.cc @@ -24,30 +24,154 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -#include "I_EventSystem.h" #include "tscore/I_Layout.h" +#include "I_EventSystem.h" +#include "RecordsConfig.h" + #include "diags.i" #define TEST_THREADS 1 TEST_CASE("MIOBuffer", "[iocore]") { - for (unsigned i = 0; i < 100; ++i) { - MIOBuffer *b1 = new_MIOBuffer(default_small_iobuffer_size); - int64_t len1 = b1->write_avail(); - IOBufferReader *b1reader = b1->alloc_reader(); - b1->fill(len1); - CHECK(b1reader->read_avail() == len1); - - MIOBuffer *b2 = new_MIOBuffer(default_large_iobuffer_size); - int64_t len2 = b1->write_avail(); - IOBufferReader *b2reader = b2->alloc_reader(); - b2->fill(len2); - CHECK(b2reader->read_avail() == len2); - - free_MIOBuffer(b2); - free_MIOBuffer(b1); + // These value could be tweaked by `ink_event_system_init()` using `proxy.config.io.max_buffer_size` + REQUIRE(default_small_iobuffer_size == DEFAULT_SMALL_BUFFER_SIZE); + REQUIRE(default_large_iobuffer_size == DEFAULT_LARGE_BUFFER_SIZE); + + REQUIRE(BUFFER_SIZE_FOR_INDEX(default_small_iobuffer_size) == 512); + REQUIRE(BUFFER_SIZE_FOR_INDEX(default_large_iobuffer_size) == 4096); + + SECTION("new_MIOBuffer 100 times") + { + int64_t read_avail_len1 = 0; + int64_t read_avail_len2 = 0; + + for (unsigned i = 0; i < 100; ++i) { + MIOBuffer *b1 = new_MIOBuffer(default_small_iobuffer_size); + int64_t len1 = b1->write_avail(); + IOBufferReader *b1reader = b1->alloc_reader(); + b1->fill(len1); + read_avail_len1 += b1reader->read_avail(); + + MIOBuffer *b2 = new_MIOBuffer(default_large_iobuffer_size); + int64_t len2 = b2->write_avail(); + IOBufferReader *b2reader = b2->alloc_reader(); + b2->fill(len2); + read_avail_len2 += b2reader->read_avail(); + + free_MIOBuffer(b2); + free_MIOBuffer(b1); + } + + CHECK(read_avail_len1 == 100 * BUFFER_SIZE_FOR_INDEX(default_small_iobuffer_size)); + CHECK(read_avail_len2 == 100 * BUFFER_SIZE_FOR_INDEX(default_large_iobuffer_size)); + } + + SECTION("write") + { + MIOBuffer *miob = new_MIOBuffer(); + IOBufferReader *miob_r = miob->alloc_reader(); + const IOBufferBlock *block = miob->first_write_block(); + + SECTION("initial state") + { + CHECK(miob->size_index == default_large_iobuffer_size); + CHECK(miob->water_mark == 0); + CHECK(miob->first_write_block() != nullptr); + CHECK(miob->block_size() == 4096); + CHECK(miob->block_write_avail() == 4096); + CHECK(miob->current_write_avail() == 4096); + CHECK(miob->write_avail() == 4096); + + CHECK(miob->max_read_avail() == 0); + CHECK(miob_r->read_avail() == 0); + } + + SECTION("write(const void *rbuf, int64_t nbytes)") + { + SECTION("1K") + { + uint8_t buf[1024]; + memset(buf, 0xAA, sizeof(buf)); + + int64_t written = miob->write(buf, sizeof(buf)); + + REQUIRE(written == sizeof(buf)); + + CHECK(miob->block_size() == 4096); + CHECK(miob->block_write_avail() == 3072); + CHECK(miob->current_write_avail() == 3072); + CHECK(miob->write_avail() == 3072); + + CHECK(miob->first_write_block() == block); + + CHECK(miob->max_read_avail() == sizeof(buf)); + CHECK(miob_r->read_avail() == sizeof(buf)); + } + + SECTION("4K") + { + uint8_t buf[4096]; + memset(buf, 0xAA, sizeof(buf)); + + int64_t written = miob->write(buf, sizeof(buf)); + + REQUIRE(written == sizeof(buf)); + + CHECK(miob->block_size() == 4096); + CHECK(miob->block_write_avail() == 0); + CHECK(miob->current_write_avail() == 0); + CHECK(miob->write_avail() == 0); + + CHECK(miob->first_write_block() == block); + + CHECK(miob->max_read_avail() == sizeof(buf)); + CHECK(miob_r->read_avail() == sizeof(buf)); + } + + SECTION("5K") + { + uint8_t buf[5120]; + memset(buf, 0xAA, sizeof(buf)); + + int64_t written = miob->write(buf, sizeof(buf)); + + REQUIRE(written == sizeof(buf)); + + CHECK(miob->block_size() == 4096); + CHECK(miob->block_write_avail() == 3072); + CHECK(miob->current_write_avail() == 3072); + CHECK(miob->write_avail() == 3072); + + CHECK(miob->first_write_block() != block); + + CHECK(miob->max_read_avail() == sizeof(buf)); + CHECK(miob_r->read_avail() == sizeof(buf)); + } + + SECTION("8K") + { + uint8_t buf[8192]; + memset(buf, 0xAA, sizeof(buf)); + + int64_t written = miob->write(buf, sizeof(buf)); + + REQUIRE(written == sizeof(buf)); + + CHECK(miob->block_size() == 4096); + CHECK(miob->block_write_avail() == 0); + CHECK(miob->current_write_avail() == 0); + CHECK(miob->write_avail() == 0); + + CHECK(miob->first_write_block() != block); + + CHECK(miob->max_read_avail() == sizeof(buf)); + CHECK(miob_r->read_avail() == sizeof(buf)); + } + } + + free_MIOBuffer(miob); } } @@ -61,6 +185,9 @@ struct EventProcessorListener : Catch::TestEventListenerBase { init_diags("", nullptr); RecProcessInit(RECM_STAND_ALONE); + // Initialize LibRecordsConfig for `proxy.config.io.max_buffer_size` (32K) + LibRecordsConfigInit(); + ink_event_system_init(EVENT_SYSTEM_MODULE_PUBLIC_VERSION); eventProcessor.start(TEST_THREADS); From 225a8c9fbb2a4cfbb80283f479eac21f1d519a0d Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Tue, 3 Sep 2019 16:23:00 +0900 Subject: [PATCH 035/718] Reduce unnecesary IOBufferBlock allocation - Add unit tests for MIOBuffer::write_avail() - Do nothing when the next block of the current writer exists (cherry picked from commit c40271ae7543a87bc90b4278954b79d304bb70b0) --- iocore/eventsystem/IOBuffer.cc | 13 +- iocore/eventsystem/I_IOBuffer.h | 5 +- iocore/eventsystem/P_IOBuffer.h | 4 +- .../eventsystem/unit_tests/test_IOBuffer.cc | 162 ++++++++++++++++++ 4 files changed, 179 insertions(+), 5 deletions(-) diff --git a/iocore/eventsystem/IOBuffer.cc b/iocore/eventsystem/IOBuffer.cc index e1a255a27d5..d2c130b832d 100644 --- a/iocore/eventsystem/IOBuffer.cc +++ b/iocore/eventsystem/IOBuffer.cc @@ -60,6 +60,9 @@ init_buffer_allocators(int iobuffer_advice) } } +// +// MIOBuffer +// int64_t MIOBuffer::remove_append(IOBufferReader *r) { @@ -173,6 +176,9 @@ MIOBuffer::puts(char *s, int64_t len) return 0; } +// +// IOBufferReader +// int64_t IOBufferReader::read(void *ab, int64_t len) { @@ -262,6 +268,9 @@ IOBufferReader::memcpy(void *ap, int64_t len, int64_t offset) return p; } +// +// IOBufferChain +// int64_t IOBufferChain::write(IOBufferBlock *blocks, int64_t length, int64_t offset) { @@ -349,7 +358,9 @@ IOBufferChain::consume(int64_t size) return zret; } -//-- MIOBufferWriter +// +// MIOBufferWriter +// MIOBufferWriter & MIOBufferWriter::write(const void *data_, size_t length) { diff --git a/iocore/eventsystem/I_IOBuffer.h b/iocore/eventsystem/I_IOBuffer.h index e74bb158b22..9a85c638dd5 100644 --- a/iocore/eventsystem/I_IOBuffer.h +++ b/iocore/eventsystem/I_IOBuffer.h @@ -950,9 +950,8 @@ class MIOBuffer void append_block(int64_t asize_index); /** - Adds new block to the end of block list using the block size for - the buffer specified when the buffer was allocated. - + Adds a new block to the end of the block list. Note that this does nothing when the next block of the current writer exists. + The block size is the same as specified size when the buffer was allocated. */ void add_block(); diff --git a/iocore/eventsystem/P_IOBuffer.h b/iocore/eventsystem/P_IOBuffer.h index c13202d0259..7252f4887d4 100644 --- a/iocore/eventsystem/P_IOBuffer.h +++ b/iocore/eventsystem/P_IOBuffer.h @@ -987,7 +987,9 @@ MIOBuffer::append_block(int64_t asize_index) TS_INLINE void MIOBuffer::add_block() { - append_block(size_index); + if (this->_writer == nullptr || this->_writer->next == nullptr) { + append_block(size_index); + } } TS_INLINE void diff --git a/iocore/eventsystem/unit_tests/test_IOBuffer.cc b/iocore/eventsystem/unit_tests/test_IOBuffer.cc index f380bf017bc..8128ffba039 100644 --- a/iocore/eventsystem/unit_tests/test_IOBuffer.cc +++ b/iocore/eventsystem/unit_tests/test_IOBuffer.cc @@ -173,6 +173,168 @@ TEST_CASE("MIOBuffer", "[iocore]") free_MIOBuffer(miob); } + + SECTION("write_avail") + { + MIOBuffer *miob = new_MIOBuffer(); + IOBufferReader *miob_r = miob->alloc_reader(); + uint8_t buf[8192]; + memset(buf, 0xAA, sizeof(buf)); + + // initial state + CHECK(miob->block_size() == 4096); + CHECK(miob->current_write_avail() == 4096); + CHECK(miob->write_avail() == 4096); + + SECTION("water_mark == 0 (default)") + { + REQUIRE(miob->water_mark == 0); + + // fill half of the current buffer + miob->write(buf, 2048); + CHECK(miob->max_read_avail() == 2048); + CHECK(miob->current_write_avail() == 2048); + CHECK(miob->high_water() == true); + CHECK(miob->current_low_water() == false); + CHECK(miob->write_avail() == 2048); ///< should have no side effect + + // fill all of the current buffer + miob->write(buf, 2048); + CHECK(miob->max_read_avail() == 4096); + CHECK(miob->current_write_avail() == 0); + CHECK(miob->high_water() == true); + CHECK(miob->current_low_water() == true); + CHECK(miob->write_avail() == 0); ///< should have no side effect + + // consume half of the data + miob_r->consume(2048); + CHECK(miob->max_read_avail() == 2048); + CHECK(miob->current_write_avail() == 0); + CHECK(miob->high_water() == true); + CHECK(miob->current_low_water() == true); + CHECK(miob->write_avail() == 0); ///< should have no side effect + + // consume all of the data + miob_r->consume(2048); + CHECK(miob->max_read_avail() == 0); + CHECK(miob->current_write_avail() == 0); + CHECK(miob->high_water() == false); + CHECK(miob->current_low_water() == true); + CHECK(miob->write_avail() == 4096); ///< should have a side effect: add a new block + + CHECK(miob->max_read_avail() == 0); + CHECK(miob->current_write_avail() == 4096); + CHECK(miob->high_water() == false); + CHECK(miob->current_low_water() == false); + CHECK(miob->write_avail() == 4096); ///< should have no side effect + } + + SECTION("water_mark == half of block size") + { + miob->water_mark = 2048; + REQUIRE(miob->water_mark * 2 == miob->block_size()); + + // fill half of the current buffer + miob->write(buf, 2048); + CHECK(miob->max_read_avail() == 2048); + CHECK(miob->current_write_avail() == 2048); + CHECK(miob->high_water() == false); + CHECK(miob->current_low_water() == true); + CHECK(miob->write_avail() == 6144); ///< should have a side effect: add a new block + + CHECK(miob->max_read_avail() == 2048); + CHECK(miob->current_write_avail() == 6144); + CHECK(miob->high_water() == false); + CHECK(miob->current_low_water() == false); + CHECK(miob->write_avail() == 6144); ///< should have no side effect + + // fill all of the current buffer + miob->write(buf, 6144); + CHECK(miob->max_read_avail() == 8192); + CHECK(miob->current_write_avail() == 0); + CHECK(miob->high_water() == true); + CHECK(miob->current_low_water() == true); + CHECK(miob->write_avail() == 0); ///< should have no side effect + + // consume half of the data + miob_r->consume(4096); + CHECK(miob->max_read_avail() == 4096); + CHECK(miob->current_write_avail() == 0); + CHECK(miob->high_water() == true); + CHECK(miob->current_low_water() == true); + CHECK(miob->write_avail() == 0); ///< should have no side effect + + // consume all of the data + miob_r->consume(4096); + CHECK(miob->max_read_avail() == 0); + CHECK(miob->current_write_avail() == 0); + CHECK(miob->high_water() == false); + CHECK(miob->current_low_water() == true); + CHECK(miob->write_avail() == 4096); ///< should have a side effect: add a new block + + CHECK(miob->max_read_avail() == 0); + CHECK(miob->current_write_avail() == 4096); + CHECK(miob->high_water() == false); + CHECK(miob->current_low_water() == false); + CHECK(miob->write_avail() == 4096); ///< should have no side effect + } + + SECTION("water_mark == block_size()") + { + miob->water_mark = 4096; + REQUIRE(miob->water_mark == miob->block_size()); + + // fill half of the current buffer + miob->write(buf, 2048); + CHECK(miob->max_read_avail() == 2048); + CHECK(miob->current_write_avail() == 2048); + CHECK(miob->high_water() == false); + CHECK(miob->current_low_water() == true); + CHECK(miob->write_avail() == 6144); ///< should have a side effect: add a new block + + CHECK(miob->max_read_avail() == 2048); + CHECK(miob->current_write_avail() == 6144); + CHECK(miob->high_water() == false); + CHECK(miob->current_low_water() == false); + CHECK(miob->write_avail() == 6144); ///< should have no side effect + + // fill all of the current buffer + miob->write(buf, 6144); + CHECK(miob->max_read_avail() == 8192); + CHECK(miob->current_write_avail() == 0); + CHECK(miob->high_water() == true); + CHECK(miob->current_low_water() == true); + CHECK(miob->write_avail() == 0); ///< should have no side effect + + // consume half of the data + miob_r->consume(4096); + CHECK(miob->max_read_avail() == 4096); + CHECK(miob->current_write_avail() == 0); + CHECK(miob->high_water() == false); + CHECK(miob->current_low_water() == true); + CHECK(miob->write_avail() == 4096); ///< should have a side effect: add a new block + IOBufferBlock *tail = miob->_writer->next.get(); + CHECK(tail != nullptr); + + CHECK(miob->max_read_avail() == 4096); + CHECK(miob->current_write_avail() == 4096); + CHECK(miob->high_water() == false); + CHECK(miob->current_low_water() == true); + CHECK(miob->write_avail() == 4096); ///< should have no side effect + CHECK(tail == miob->_writer->next.get()); ///< the tail block should not be changed + + // consume all of the data + miob_r->consume(4096); + CHECK(miob->max_read_avail() == 0); + CHECK(miob->current_write_avail() == 4096); + CHECK(miob->high_water() == false); + CHECK(miob->current_low_water() == true); + CHECK(miob->write_avail() == 4096); ///< should have no side effect + CHECK(tail == miob->_writer->next.get()); ///< the tail block should not be changed + } + + free_MIOBuffer(miob); + } } struct EventProcessorListener : Catch::TestEventListenerBase { From a91751d9153e490fd7da84a055fb693895e42141 Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Fri, 30 Aug 2019 09:52:22 +0900 Subject: [PATCH 036/718] Cleanup: Remove unused AllocType and unused functions (cherry picked from commit c65f0a1fbe4838cf56ba422f0a197895bf3c498e) --- iocore/eventsystem/I_IOBuffer.h | 42 ++++-------------------------- iocore/eventsystem/P_IOBuffer.h | 45 --------------------------------- 2 files changed, 5 insertions(+), 82 deletions(-) diff --git a/iocore/eventsystem/I_IOBuffer.h b/iocore/eventsystem/I_IOBuffer.h index 9a85c638dd5..4390bb1e256 100644 --- a/iocore/eventsystem/I_IOBuffer.h +++ b/iocore/eventsystem/I_IOBuffer.h @@ -62,11 +62,8 @@ extern int64_t default_large_iobuffer_size; // matched to size of OS buffers enum AllocType { NO_ALLOC, - FAST_ALLOCATED, - XMALLOCED, MEMALIGNED, DEFAULT_ALLOC, - CONSTANT, }; #define DEFAULT_BUFFER_NUMBER 128 @@ -143,14 +140,6 @@ void init_buffer_allocators(int iobuffer_advice); NO_ALLOC - - FAST_ALLOCATED - - - - XMALLOCED - - MEMALIGNED @@ -159,10 +148,6 @@ void init_buffer_allocators(int iobuffer_advice); DEFAULT_ALLOC - - CONSTANT - - */ @@ -465,8 +450,6 @@ class IOBufferBlock : public RefCountObj void realloc_set_internal(void *b, int64_t buf_size, int64_t asize_index); void realloc(void *b, int64_t buf_size); void realloc(int64_t i); - void realloc_xmalloc(void *b, int64_t buf_size); - void realloc_xmalloc(int64_t buf_size); /** Frees the IOBufferBlock object and its underlying memory. @@ -956,6 +939,10 @@ class MIOBuffer void add_block(); /** + Deprecated + + TODO: remove this function. Because ats_xmalloc() doesn't exist anymore. + Adds by reference len bytes of data pointed to by b to the end of the buffer. b MUST be a pointer to the beginning of block allocated from the ats_xmalloc() routine. The data will be deallocated @@ -1185,9 +1172,7 @@ class MIOBuffer void dealloc_all_readers(); void set(void *b, int64_t len); - void set_xmalloced(void *b, int64_t len); void alloc(int64_t i = default_large_iobuffer_size); - void alloc_xmalloc(int64_t buf_size); void append_block_internal(IOBufferBlock *b); int64_t write(IOBufferBlock const *b, int64_t len, int64_t offset); int64_t puts(char *buf, int64_t len); @@ -1254,16 +1239,6 @@ class MIOBuffer { _writer->realloc(b, buf_size); } - void - realloc_xmalloc(void *b, int64_t buf_size) - { - _writer->realloc_xmalloc(b, buf_size); - } - void - realloc_xmalloc(int64_t buf_size) - { - _writer->realloc_xmalloc(buf_size); - } int64_t size_index; @@ -1453,12 +1428,6 @@ extern IOBufferData *new_xmalloc_IOBufferData_internal( #endif void *b, int64_t size); -extern IOBufferData *new_constant_IOBufferData_internal( -#ifdef TRACK_BUFFER_USER - const char *locaction, -#endif - void *b, int64_t size); - #ifdef TRACK_BUFFER_USER class IOBufferData_tracker { @@ -1474,14 +1443,13 @@ class IOBufferData_tracker }; #endif +// TODO: remove new_xmalloc_IOBufferData. Because ats_xmalloc() doesn't exist anymore. #ifdef TRACK_BUFFER_USER #define new_IOBufferData IOBufferData_tracker(RES_PATH("memory/IOBuffer/")) #define new_xmalloc_IOBufferData(b, size) new_xmalloc_IOBufferData_internal(RES_PATH("memory/IOBuffer/"), (b), (size)) -#define new_constant_IOBufferData(b, size) new_constant_IOBufferData_internal(RES_PATH("memory/IOBuffer/"), (b), (size)) #else #define new_IOBufferData new_IOBufferData_internal #define new_xmalloc_IOBufferData new_xmalloc_IOBufferData_internal -#define new_constant_IOBufferData new_constant_IOBufferData_internal #endif extern int64_t iobuffer_size_to_index(int64_t size, int64_t max = max_iobuffer_size); diff --git a/iocore/eventsystem/P_IOBuffer.h b/iocore/eventsystem/P_IOBuffer.h index 7252f4887d4..49e65555d0c 100644 --- a/iocore/eventsystem/P_IOBuffer.h +++ b/iocore/eventsystem/P_IOBuffer.h @@ -216,20 +216,6 @@ new_IOBufferData_internal( return d; } -TS_INLINE IOBufferData * -new_constant_IOBufferData_internal( -#ifdef TRACK_BUFFER_USER - const char *loc, -#endif - void *b, int64_t size) -{ - return new_IOBufferData_internal( -#ifdef TRACK_BUFFER_USER - loc, -#endif - b, size, BUFFER_SIZE_INDEX_FOR_CONSTANT_SIZE(size)); -} - TS_INLINE IOBufferData * new_xmalloc_IOBufferData_internal( #ifdef TRACK_BUFFER_USER @@ -518,18 +504,6 @@ IOBufferBlock::realloc(void *b, int64_t buf_size) realloc_set_internal(b, buf_size, BUFFER_SIZE_NOT_ALLOCATED); } -TS_INLINE void -IOBufferBlock::realloc_xmalloc(void *b, int64_t buf_size) -{ - realloc_set_internal(b, buf_size, -buf_size); -} - -TS_INLINE void -IOBufferBlock::realloc_xmalloc(int64_t buf_size) -{ - realloc_set_internal(ats_malloc(buf_size), buf_size, -buf_size); -} - TS_INLINE void IOBufferBlock::realloc(int64_t i) { @@ -1106,18 +1080,6 @@ MIOBuffer::set(void *b, int64_t len) init_readers(); } -TS_INLINE void -MIOBuffer::set_xmalloced(void *b, int64_t len) -{ -#ifdef TRACK_BUFFER_USER - _writer = new_IOBufferBlock_internal(_location); -#else - _writer = new_IOBufferBlock_internal(); -#endif - _writer->set_internal(b, len, BUFFER_SIZE_INDEX_FOR_XMALLOC_SIZE(len)); - init_readers(); -} - TS_INLINE void MIOBuffer::append_xmalloced(void *b, int64_t len) { @@ -1155,13 +1117,6 @@ MIOBuffer::alloc(int64_t i) init_readers(); } -TS_INLINE void -MIOBuffer::alloc_xmalloc(int64_t buf_size) -{ - char *b = (char *)ats_malloc(buf_size); - set_xmalloced(b, buf_size); -} - TS_INLINE void MIOBuffer::dealloc_reader(IOBufferReader *e) { From 415644e9f472562d21333b3a6f25b1b8f7661f7f Mon Sep 17 00:00:00 2001 From: Susan Hinrichs Date: Fri, 9 Aug 2019 15:02:20 +0000 Subject: [PATCH 037/718] Address possibe use after free issue in HttpVCTable::remove_entry (cherry picked from commit 996d7dace90585a5f297f9c625795f301c8bf083) --- proxy/http/HttpSM.cc | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc index 62775ce0c7a..e36aed94a27 100644 --- a/proxy/http/HttpSM.cc +++ b/proxy/http/HttpSM.cc @@ -194,26 +194,10 @@ HttpVCTable::remove_entry(HttpVCTableEntry *e) free_MIOBuffer(e->write_buffer); e->write_buffer = nullptr; } - if (e->read_vio != nullptr && e->read_vio->cont == sm) { - // Cleanup dangling i/o - if (e == sm->get_ua_entry() && sm->get_ua_txn() != nullptr) { - e->read_vio = sm->get_ua_txn()->do_io_read(nullptr, 0, nullptr); - } else if (e == sm->get_server_entry() && sm->get_server_session()) { - e->read_vio = sm->get_server_session()->do_io_read(nullptr, 0, nullptr); - } else { - ink_release_assert(false); - } - } - if (e->write_vio != nullptr && e->write_vio->cont == sm) { - // Cleanup dangling i/o - if (e == sm->get_ua_entry() && sm->get_ua_txn()) { - e->write_vio = sm->get_ua_txn()->do_io_write(nullptr, 0, nullptr); - } else if (e == sm->get_server_entry() && sm->get_server_session()) { - e->write_vio = sm->get_server_session()->do_io_write(nullptr, 0, nullptr); - } else { - ink_release_assert(false); - } - } + // Cannot reach in to checkout the netvc + // for remaining I/O operations because the netvc + // may have been deleted at this point and the pointer + // could be stale. e->read_vio = nullptr; e->write_vio = nullptr; e->vc_handler = nullptr; From 472e61f92c07827a34e1a11c87fcc2058871901f Mon Sep 17 00:00:00 2001 From: Walter Karas Date: Tue, 1 Oct 2019 16:24:25 -0500 Subject: [PATCH 038/718] YAML config: output erroneous keyword and line number in YAML file it appears on in diags.log. (cherry picked from commit 823baa89bd37bcdc7916550208bc3f9272db4334) --- iocore/net/YamlSNIConfig.cc | 6 +++--- proxy/logging/YamlLogConfig.cc | 2 +- proxy/logging/YamlLogConfigDecoders.cc | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/iocore/net/YamlSNIConfig.cc b/iocore/net/YamlSNIConfig.cc index 4a7cefac65b..a9abe8effe3 100644 --- a/iocore/net/YamlSNIConfig.cc +++ b/iocore/net/YamlSNIConfig.cc @@ -117,10 +117,10 @@ template <> struct convert { static bool decode(const Node &node, YamlSNIConfig::Item &item) { - for (auto &&item : node) { + for (const auto &elem : node) { if (std::none_of(valid_sni_config_keys.begin(), valid_sni_config_keys.end(), - [&item](const std::string &s) { return s == item.first.as(); })) { - throw YAML::ParserException(item.Mark(), "unsupported key " + item.first.as()); + [&elem](const std::string &s) { return s == elem.first.as(); })) { + throw YAML::ParserException(elem.first.Mark(), "unsupported key " + elem.first.as()); } } diff --git a/proxy/logging/YamlLogConfig.cc b/proxy/logging/YamlLogConfig.cc index 398bfcbbc80..985f0aa0f61 100644 --- a/proxy/logging/YamlLogConfig.cc +++ b/proxy/logging/YamlLogConfig.cc @@ -119,7 +119,7 @@ YamlLogConfig::decodeLogObject(const YAML::Node &node) for (auto const &item : node) { if (std::none_of(valid_log_object_keys.begin(), valid_log_object_keys.end(), [&item](const std::string &s) { return s == item.first.as(); })) { - throw YAML::ParserException(item.Mark(), "log: unsupported key '" + item.first.as() + "'"); + throw YAML::ParserException(item.first.Mark(), "log: unsupported key '" + item.first.as() + "'"); } } diff --git a/proxy/logging/YamlLogConfigDecoders.cc b/proxy/logging/YamlLogConfigDecoders.cc index 57264458614..fca2817f578 100644 --- a/proxy/logging/YamlLogConfigDecoders.cc +++ b/proxy/logging/YamlLogConfigDecoders.cc @@ -36,10 +36,10 @@ namespace YAML bool convert>::decode(const Node &node, std::unique_ptr &logFormat) { - for (auto &&item : node) { + for (const auto &item : node) { if (std::none_of(valid_log_format_keys.begin(), valid_log_format_keys.end(), [&item](const std::string &s) { return s == item.first.as(); })) { - throw YAML::ParserException(node.Mark(), "format: unsupported key '" + item.first.as() + "'"); + throw YAML::ParserException(item.first.Mark(), "format: unsupported key '" + item.first.as() + "'"); } } From e83a34297b58e03c9f9e4036ed948e67f0de18da Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Thu, 3 Oct 2019 11:40:21 -0600 Subject: [PATCH 039/718] Updated ChangeLog --- CHANGELOG-9.0.0 | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-9.0.0 b/CHANGELOG-9.0.0 index 1b0e8a2cf8d..05d78000efc 100644 --- a/CHANGELOG-9.0.0 +++ b/CHANGELOG-9.0.0 @@ -186,6 +186,7 @@ Changes with Apache Traffic Server 9.0.0 #4603 - Add cdniip and cdnistd claims to uri signing #4604 - Repurpose sub claim and add cdniuc support for URI signing #4606 - TLS Bridge: Fix remap for UA connection, tweak docs for remap support. + #4607 - adding TSHttpTxnRedoCacheLookup #4609 - BWF: Change timestamp global name to be consistent with logging timestamps #4613 - Runroot: Update verify command and refactor #4616 - [WEBP] Transform images when a client accepts image/webp. @@ -458,7 +459,6 @@ Changes with Apache Traffic Server 9.0.0 #5297 - Doc: fix proxy.config.cache.ram_cache.algorithm description #5301 - Slice Plugin: add options for disabling or pacing detailed block stitch error logging. #5302 - Correct config name for proxy.config.dns.connection_mode - #5305 - Throttling results in tight loop if there are no new connections #5306 - Removes priorities for AIOs, thanks oknet #5307 - correctly handle return value 0 from recv() #5308 - cppcheck: Changed from C casting to C++ casting @@ -702,6 +702,7 @@ Changes with Apache Traffic Server 9.0.0 #5722 - In test_hooks Au test case, add work-around for flakeyness of VCONN start/close events. #5723 - Update docs to document wipe_field_action that we use in production #5724 - Enable logging of the Elliptic Curve used to communicate with the client + #5726 - Expose client request SSL stats via API & Lua plugin #5728 - Remove header_rewrite conditions deprecated in previous versions #5730 - Cleanup and link references to sni.yaml #5731 - Use un-deprecated records for SSL server verification @@ -743,6 +744,8 @@ Changes with Apache Traffic Server 9.0.0 #5803 - Make TS_NULL_MLOC a valid C compile-time constant. #5806 - More doc spelling fixes #5808 - Remove unused assignment to satisfy clang-analyzer + #5809 - Address possible use after free issue in HttpVCTable::remove_entry + #5811 - Fix no_activity timeout for server session reuse. #5813 - Fixes broken links to documentation #5815 - Updates links to trafficserver.apache.org to https #5817 - Fixes various issues found in docs @@ -762,4 +765,34 @@ Changes with Apache Traffic Server 9.0.0 #5841 - Cleanup: unifdef WRITE_AND_TRANSFER #5844 - Explain how SRV origin selection works #5847 - Cleanup: Remove unused empty files + #5848 - Convert check programs in iocore/eventsystem/ into Catch based unit tests + #5853 - correct the size of DNS buffers #5856 - Fixes 'traffic_ctl server restart' to restart + #5865 - cachekey: added --canonical-prefix parameter + #5867 - PR#5867: Explain how to use open_con(). + #5868 - Update HttpTransact.cc + #5870 - Fix bad limit in poll loop. jtest -c1 now works again. + #5872 - cachekey: added --key-type to allow parent selection URL to be modified + #5883 - Add unit tests for MIOBuffer:write() + #5885 - Add the ability to static link ASAN, TSAN and LSAN + #5887 - Fixed const issue with magick plugin + #5888 - Allow disabling HTTP/2 priority frames limit + #5889 - Provide stats for the recently introduced HTTP/2 rate limits + #5893 - Cleanup: Remove unused AllocType and unused functions + #5902 - Ran clang-format + #5903 - Reduce unnecesary IOBufferBlock allocation + #5905 - Update Server IP in Transaction when attaching a session from the pool + #5915 - Update documentation for connect_attempts_timeout. + #5920 - Cleanup: VIO + #5921 - Cleanup AuTest for HTTP/2 + #5922 - Make code buildable with BoringSSL + #5926 - Fix AuTest for HTTP/2 using httpbin + #5930 - Track SSL session cache evictions performed due to full bucket + #5934 - Track scheduled events to (read|write)_vio.cont from Http2Stream + #5935 - Perform a SSL quiet shutdown when close-notify is not sent + #5939 - Remove hard coded filename in error message + #5955 - Fix debug output for global_user_agent_header. + #5959 - Clear api set bit to avoid crash in following redirect. + #5961 - Clarify docs on the change from redirect_enabled. + #5962 - Removed hardcoded sni.yaml configuration filename in logs + #5977 - YAML config: output erroneous keyword and line number From 6d5c488576e73de808ae24f77ae6240dd0c02d2b Mon Sep 17 00:00:00 2001 From: Fei Deng Date: Wed, 21 Aug 2019 14:19:25 -0500 Subject: [PATCH 040/718] check for nullptr when locking (cherry picked from commit d75af6f2eb6c63aa216111bd7f477f1f4c775580) --- iocore/eventsystem/I_Lock.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/iocore/eventsystem/I_Lock.h b/iocore/eventsystem/I_Lock.h index b5bef2c40e0..d599be26b06 100644 --- a/iocore/eventsystem/I_Lock.h +++ b/iocore/eventsystem/I_Lock.h @@ -353,17 +353,19 @@ class MutexLock Ptr &am, EThread *t) : m(am), locked_p(true) { - Mutex_lock( + if (am) { + Mutex_lock( #ifdef DEBUG - location, ahandler, + location, ahandler, #endif // DEBUG - m, t); + m, t); + } } void release() { - if (locked_p) { + if (locked_p && m) { Mutex_unlock(m, m->thread_holding); } locked_p = false; From 55e3ca68ba23bc690499feb832e43ca04a90aa78 Mon Sep 17 00:00:00 2001 From: Fei Deng Date: Thu, 5 Sep 2019 15:05:15 -0500 Subject: [PATCH 041/718] weak mutex macros (cherry picked from commit f0d82b7d55a25c7a74f379eac9d2852f7f08ced2) --- iocore/eventsystem/I_Lock.h | 137 ++++++++++++++++++++++++--- iocore/hostdb/HostDB.cc | 2 +- iocore/net/SSLNetVConnection.cc | 1 + proxy/ProxySession.cc | 2 +- proxy/http/HttpSM.cc | 2 +- src/traffic_server/InkAPI.cc | 4 +- src/traffic_server/traffic_server.cc | 4 +- 7 files changed, 131 insertions(+), 21 deletions(-) diff --git a/iocore/eventsystem/I_Lock.h b/iocore/eventsystem/I_Lock.h index d599be26b06..4850199251d 100644 --- a/iocore/eventsystem/I_Lock.h +++ b/iocore/eventsystem/I_Lock.h @@ -48,13 +48,20 @@ @param _t The current EThread executing your code. */ + +// A weak version of the SCOPED_MUTEX_LOCK macro, allows the mutex to be a nullptr. #ifdef DEBUG -#define SCOPED_MUTEX_LOCK(_l, _m, _t) MutexLock _l(MakeSourceLocation(), nullptr, _m, _t) -#else -#define SCOPED_MUTEX_LOCK(_l, _m, _t) MutexLock _l(_m, _t) +#define WEAK_SCOPED_MUTEX_LOCK(_l, _m, _t) WeakMutexLock _l(MakeSourceLocation(), (char *)nullptr, _m, _t); +#else // DEBUG +#define WEAK_SCOPED_MUTEX_LOCK(_l, _m, _t) WeakMutexLock _l(_m, _t); #endif // DEBUG #ifdef DEBUG +#define SCOPED_MUTEX_LOCK(_l, _m, _t) MutexLock _l(MakeSourceLocation(), (char *)nullptr, _m, _t) +#else // DEBUG +#define SCOPED_MUTEX_LOCK(_l, _m, _t) MutexLock _l(_m, _t) +#endif // DEBUG + /** Attempts to acquire the lock to the ProxyMutex. @@ -68,8 +75,15 @@ @param _t The current EThread executing your code. */ -#define MUTEX_TRY_LOCK(_l, _m, _t) MutexTryLock _l(MakeSourceLocation(), (char *)nullptr, _m, _t) +#ifdef DEBUG +#define WEAK_MUTEX_TRY_LOCK(_l, _m, _t) WeakMutexTryLock _l(MakeSourceLocation(), (char *)nullptr, _m, _t); +#else // DEBUG +#define WEAK_MUTEX_TRY_LOCK(_l, _m, _t) WeakMutexTryLock _l(_m, _t); +#endif // DEBUG + +#ifdef DEBUG +#define MUTEX_TRY_LOCK(_l, _m, _t) MutexTryLock _l(MakeSourceLocation(), (char *)nullptr, _m, _t) #else // DEBUG #define MUTEX_TRY_LOCK(_l, _m, _t) MutexTryLock _l(_m, _t) #endif // DEBUG @@ -337,23 +351,21 @@ Mutex_unlock(Ptr &m, EThread *t) } } -/** Scoped lock class for ProxyMutex - */ -class MutexLock +class WeakMutexLock { private: Ptr m; bool locked_p; public: - MutexLock( + WeakMutexLock( #ifdef DEBUG const SourceLocation &location, const char *ahandler, #endif // DEBUG Ptr &am, EThread *t) : m(am), locked_p(true) { - if (am) { + if (m.get()) { Mutex_lock( #ifdef DEBUG location, ahandler, @@ -365,7 +377,42 @@ class MutexLock void release() { - if (locked_p && m) { + if (locked_p && m.get()) { + Mutex_unlock(m, m->thread_holding); + } + locked_p = false; + } + + ~WeakMutexLock() { this->release(); } +}; + +/** Scoped lock class for ProxyMutex + */ +class MutexLock +{ +private: + Ptr m; + bool locked_p; + +public: + MutexLock( +#ifdef DEBUG + const SourceLocation &location, const char *ahandler, +#endif // DEBUG + Ptr &am, EThread *t) + : m(am), locked_p(true) + { + Mutex_lock( +#ifdef DEBUG + location, ahandler, +#endif // DEBUG + m, t); + } + + void + release() + { + if (locked_p) { Mutex_unlock(m, m->thread_holding); } locked_p = false; @@ -376,21 +423,21 @@ class MutexLock /** Scoped try lock class for ProxyMutex */ -class MutexTryLock +class WeakMutexTryLock { private: Ptr m; bool lock_acquired; public: - MutexTryLock( + WeakMutexTryLock( #ifdef DEBUG const SourceLocation &location, const char *ahandler, #endif // DEBUG Ptr &am, EThread *t) : m(am) { - if (am) { + if (m.get()) { lock_acquired = Mutex_trylock( #ifdef DEBUG location, ahandler, @@ -401,11 +448,12 @@ class MutexTryLock } } - ~MutexTryLock() + ~WeakMutexTryLock() { if (lock_acquired && m.get()) { Mutex_unlock(m, m->thread_holding); } + lock_acquired = false; } /** Spin till lock is acquired @@ -441,6 +489,67 @@ class MutexTryLock } }; +/** Scoped try lock class for ProxyMutex + */ +class MutexTryLock +{ +private: + Ptr m; + bool lock_acquired; + +public: + MutexTryLock( +#ifdef DEBUG + const SourceLocation &location, const char *ahandler, +#endif // DEBUG + Ptr &am, EThread *t) + : m(am) + { + lock_acquired = Mutex_trylock( +#ifdef DEBUG + location, ahandler, +#endif // DEBUG + m, t); + } + + ~MutexTryLock() + { + if (lock_acquired) { + Mutex_unlock(m, m->thread_holding); + } + } + + /** Spin till lock is acquired + */ + void + acquire(EThread *t) + { + MUTEX_TAKE_LOCK(m, t); + lock_acquired = true; + } + + void + release() + { + if (lock_acquired) { + Mutex_unlock(m, m->thread_holding); + } + lock_acquired = false; + } + + bool + is_locked() const + { + return lock_acquired; + } + + const ProxyMutex * + get_mutex() const + { + return m.get(); + } +}; + inline void ProxyMutex::free() { diff --git a/iocore/hostdb/HostDB.cc b/iocore/hostdb/HostDB.cc index 27a5b1c98fd..991071c1395 100644 --- a/iocore/hostdb/HostDB.cc +++ b/iocore/hostdb/HostDB.cc @@ -994,7 +994,7 @@ HostDBContinuation::removeEvent(int /* event ATS_UNUSED */, Event *e) if (cont) { proxy_mutex = cont->mutex; } - MUTEX_TRY_LOCK(lock, proxy_mutex, e->ethread); + WEAK_MUTEX_TRY_LOCK(lock, proxy_mutex, e->ethread); if (!lock.is_locked()) { e->schedule_in(HOST_DB_RETRY_PERIOD); return EVENT_CONT; diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc index 8a3fb9c05a1..aacfb05649b 100644 --- a/iocore/net/SSLNetVConnection.cc +++ b/iocore/net/SSLNetVConnection.cc @@ -1752,6 +1752,7 @@ SSLNetVConnection::callHooks(TSEvent eventId) } if (curHook != nullptr) { + WEAK_SCOPED_MUTEX_LOCK(lock, curHook->m_cont->mutex, this_ethread()); curHook->invoke(eventId, this); reenabled = (this->sslHandshakeHookState != HANDSHAKE_HOOKS_CERT_INVOKE && this->sslHandshakeHookState != HANDSHAKE_HOOKS_PRE_INVOKE && diff --git a/proxy/ProxySession.cc b/proxy/ProxySession.cc index 7063b9f3bea..3d037bc960e 100644 --- a/proxy/ProxySession.cc +++ b/proxy/ProxySession.cc @@ -108,7 +108,7 @@ ProxySession::state_api_callout(int event, void *data) if (nullptr != cur_hook) { APIHook const *hook = cur_hook; - MUTEX_TRY_LOCK(lock, hook->m_cont->mutex, mutex->thread_holding); + WEAK_MUTEX_TRY_LOCK(lock, hook->m_cont->mutex, mutex->thread_holding); // Have a mutex but didn't get the lock, reschedule if (!lock.is_locked()) { diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc index e36aed94a27..ec068e52ad5 100644 --- a/proxy/http/HttpSM.cc +++ b/proxy/http/HttpSM.cc @@ -1393,7 +1393,7 @@ plugins required to work with sni_routing. callout_state = HTTP_API_IN_CALLOUT; } - MUTEX_TRY_LOCK(lock, cur_hook->m_cont->mutex, mutex->thread_holding); + WEAK_MUTEX_TRY_LOCK(lock, cur_hook->m_cont->mutex, mutex->thread_holding); // Have a mutex but didn't get the lock, reschedule if (!lock.is_locked()) { diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc index cd4059e1a59..29f9b0d293c 100644 --- a/src/traffic_server/InkAPI.cc +++ b/src/traffic_server/InkAPI.cc @@ -1330,7 +1330,7 @@ APIHook::invoke(int event, void *edata) const ink_assert(!"not reached"); } } - MUTEX_TRY_LOCK(lock, m_cont->mutex, this_ethread()); + WEAK_MUTEX_TRY_LOCK(lock, m_cont->mutex, this_ethread()); if (!lock.is_locked()) { // If we cannot get the lock, the caller needs to restructure to handle rescheduling ink_release_assert(0); @@ -4785,7 +4785,7 @@ int TSContCall(TSCont contp, TSEvent event, void *edata) { Continuation *c = (Continuation *)contp; - MUTEX_TRY_LOCK(lock, c->mutex, this_ethread()); + WEAK_MUTEX_TRY_LOCK(lock, c->mutex, this_ethread()); if (!lock.is_locked()) { // If we cannot get the lock, the caller needs to restructure to handle rescheduling ink_release_assert(0); diff --git a/src/traffic_server/traffic_server.cc b/src/traffic_server/traffic_server.cc index 591ce0b0c49..d6095ab4d42 100644 --- a/src/traffic_server/traffic_server.cc +++ b/src/traffic_server/traffic_server.cc @@ -230,7 +230,7 @@ struct AutoStopCont : public Continuation { APIHook *hook = lifecycle_hooks->get(TS_LIFECYCLE_SHUTDOWN_HOOK); while (hook) { - SCOPED_MUTEX_LOCK(lock, hook->m_cont->mutex, this_ethread()); + WEAK_SCOPED_MUTEX_LOCK(lock, hook->m_cont->mutex, this_ethread()); hook->invoke(TS_EVENT_LIFECYCLE_SHUTDOWN, nullptr); hook = hook->next(); } @@ -2113,7 +2113,7 @@ task_threads_started_callback() { APIHook *hook = lifecycle_hooks->get(TS_LIFECYCLE_TASK_THREADS_READY_HOOK); while (hook) { - SCOPED_MUTEX_LOCK(lock, hook->m_cont->mutex, this_ethread()); + WEAK_SCOPED_MUTEX_LOCK(lock, hook->m_cont->mutex, this_ethread()); hook->invoke(TS_EVENT_LIFECYCLE_TASK_THREADS_READY, nullptr); hook = hook->next(); } From a9a5b4bcffcca51f01c5883ba9f35e928dd38129 Mon Sep 17 00:00:00 2001 From: Bryan Call Date: Thu, 3 Oct 2019 17:55:05 -0700 Subject: [PATCH 042/718] Updated ChangeLog --- CHANGELOG-9.0.0 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG-9.0.0 b/CHANGELOG-9.0.0 index 05d78000efc..748314d9392 100644 --- a/CHANGELOG-9.0.0 +++ b/CHANGELOG-9.0.0 @@ -768,11 +768,13 @@ Changes with Apache Traffic Server 9.0.0 #5848 - Convert check programs in iocore/eventsystem/ into Catch based unit tests #5853 - correct the size of DNS buffers #5856 - Fixes 'traffic_ctl server restart' to restart + #5857 - Check for nullptr when locking #5865 - cachekey: added --canonical-prefix parameter #5867 - PR#5867: Explain how to use open_con(). #5868 - Update HttpTransact.cc #5870 - Fix bad limit in poll loop. jtest -c1 now works again. #5872 - cachekey: added --key-type to allow parent selection URL to be modified + #5879 - Weak mutex locking macros #5883 - Add unit tests for MIOBuffer:write() #5885 - Add the ability to static link ASAN, TSAN and LSAN #5887 - Fixed const issue with magick plugin From 5fe0b79170de26f1887e2edd4fde370208c836ec Mon Sep 17 00:00:00 2001 From: Vijay Mamidi Date: Sat, 5 Oct 2019 00:23:06 -0700 Subject: [PATCH 043/718] Concurrent SRV request failures (cherry picked from commit bf0140612866699d174355c6f95f886463090c33) --- iocore/hostdb/HostDB.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iocore/hostdb/HostDB.cc b/iocore/hostdb/HostDB.cc index 991071c1395..512781f620a 100644 --- a/iocore/hostdb/HostDB.cc +++ b/iocore/hostdb/HostDB.cc @@ -1556,7 +1556,7 @@ HostDBContinuation::probeEvent(int /* event ATS_UNUSED */, Event *e) } if (action.continuation && r) { - reply_to_cont(action.continuation, r.get()); + reply_to_cont(action.continuation, r.get(), is_srv()); } // If it succeeds or it was a remote probe, we are done From 2d142efd025d7e48d6a6ac0c7b7eb3792ceb2440 Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Tue, 24 Sep 2019 11:30:38 -0600 Subject: [PATCH 044/718] Turn on certificate verification, in permissive mode for now (cherry picked from commit 04982180df1de9996e9df207bae37ba200882096) --- configs/records.config.default.in | 2 +- doc/admin-guide/files/records.config.en.rst | 2 +- mgmt/RecordsConfig.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configs/records.config.default.in b/configs/records.config.default.in index 61028b0501a..df417bc4a49 100644 --- a/configs/records.config.default.in +++ b/configs/records.config.default.in @@ -163,7 +163,7 @@ CONFIG proxy.config.reverse_proxy.enabled INT 1 # https://docs.trafficserver.apache.org/records.config#client-related-configuration # https://docs.trafficserver.apache.org/en/latest/admin-guide/files/ssl_multicert.config.en.html ############################################################################## -CONFIG proxy.config.ssl.client.verify.server.policy STRING DISABLED +CONFIG proxy.config.ssl.client.verify.server.policy STRING PERMISSIVE CONFIG proxy.config.ssl.client.verify.server.properties STRING ALL CONFIG proxy.config.ssl.client.CA.cert.filename STRING NULL CONFIG proxy.config.ssl.server.cipher_suite STRING ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst index e4d94c6f72d..c8284d54445 100644 --- a/doc/admin-guide/files/records.config.en.rst +++ b/doc/admin-guide/files/records.config.en.rst @@ -3349,7 +3349,7 @@ SSL Termination Client-Related Configuration ---------------------------- -.. ts:cv:: CONFIG proxy.config.ssl.client.verify.server.policy STRING DISABLED +.. ts:cv:: CONFIG proxy.config.ssl.client.verify.server.policy STRING PERMISSIVE :reloadable: :overridable: diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc index 71214fb5b5a..92adf0f48e9 100644 --- a/mgmt/RecordsConfig.cc +++ b/mgmt/RecordsConfig.cc @@ -1098,7 +1098,7 @@ static const RecordElement RecordsConfig[] = , {RECT_CONFIG, "proxy.config.ssl.client.verify.server", RECD_INT, "0", RECU_DYNAMIC, RR_NULL, RECC_INT, "[0-2]", RECA_NULL} , - {RECT_CONFIG, "proxy.config.ssl.client.verify.server.policy", RECD_STRING, "DISABLED", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} + {RECT_CONFIG, "proxy.config.ssl.client.verify.server.policy", RECD_STRING, "PERMISSIVE", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , {RECT_CONFIG, "proxy.config.ssl.client.verify.server.properties", RECD_STRING, "ALL", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , From b58aaa9de8da43e55a8e94811dae4398f3fbdfde Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Sat, 5 Oct 2019 15:22:21 -0600 Subject: [PATCH 045/718] Updated ChangeLog --- CHANGELOG-9.0.0 | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG-9.0.0 b/CHANGELOG-9.0.0 index 748314d9392..79959cd01a2 100644 --- a/CHANGELOG-9.0.0 +++ b/CHANGELOG-9.0.0 @@ -794,6 +794,7 @@ Changes with Apache Traffic Server 9.0.0 #5935 - Perform a SSL quiet shutdown when close-notify is not sent #5939 - Remove hard coded filename in error message #5955 - Fix debug output for global_user_agent_header. + #5956 - Turn on certificate verification, in permissive mode for now #5959 - Clear api set bit to avoid crash in following redirect. #5961 - Clarify docs on the change from redirect_enabled. #5962 - Removed hardcoded sni.yaml configuration filename in logs From 43097fb638db6a92a5674c5d2182febb1e9137e3 Mon Sep 17 00:00:00 2001 From: Vijay Mamidi Date: Thu, 10 Oct 2019 23:04:06 -0700 Subject: [PATCH 046/718] Mark host as partial when subdmains are more than default table depth (cherry picked from commit 9ca5abc19a89ca518049921dd9cd827268cb22a0) --- src/tscore/HostLookup.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tscore/HostLookup.cc b/src/tscore/HostLookup.cc index 72759d988cc..22ee6648424 100644 --- a/src/tscore/HostLookup.cc +++ b/src/tscore/HostLookup.cc @@ -785,15 +785,15 @@ HostLookup::TableInsert(string_view match_data, int index, bool domain_record) // leaf node to make sure we have a match if (domain_record == false) { if (match.empty()) { - leaf_array[index].type = HostLeaf::HOST_PARTIAL; - } else { leaf_array[index].type = HostLeaf::HOST_COMPLETE; + } else { + leaf_array[index].type = HostLeaf::HOST_PARTIAL; } } else { if (match.empty()) { - leaf_array[index].type = HostLeaf::DOMAIN_PARTIAL; - } else { leaf_array[index].type = HostLeaf::DOMAIN_COMPLETE; + } else { + leaf_array[index].type = HostLeaf::DOMAIN_PARTIAL; } } From 75dafb0d9ae6d6043f911cc57ffd37433494d306 Mon Sep 17 00:00:00 2001 From: Fei Deng Date: Thu, 10 Oct 2019 15:33:00 -0500 Subject: [PATCH 047/718] do not reload configs periodically (cherry picked from commit cd1485435bd5c5e52110149881d8bb07a8dad988) --- mgmt/ConfigManager.cc | 13 +++++++------ mgmt/ConfigManager.h | 7 ++++++- mgmt/FileManager.cc | 4 ++-- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/mgmt/ConfigManager.cc b/mgmt/ConfigManager.cc index e5ffa732349..1eb94aaeeac 100644 --- a/mgmt/ConfigManager.cc +++ b/mgmt/ConfigManager.cc @@ -95,12 +95,12 @@ ConfigManager::statFile(struct stat *buf) return statResult; } -// bool ConfigManager::checkForUserUpdate() +// bool ConfigManager::checkForUserUpdate(RollBackCheckType how) // // Called to check if the file has been changed by the user. // Timestamps are compared to see if a change occurred bool -ConfigManager::checkForUserUpdate() +ConfigManager::checkForUserUpdate(RollBackCheckType how) { struct stat fileInfo; bool result; @@ -113,10 +113,11 @@ ConfigManager::checkForUserUpdate() } if (fileLastModified < TS_ARCHIVE_STAT_MTIME(fileInfo)) { - fileLastModified = TS_ARCHIVE_STAT_MTIME(fileInfo); - configFiles->fileChanged(fileName, configName); - mgmt_log("User has changed config file %s\n", fileName); - + if (how == ROLLBACK_CHECK_AND_UPDATE) { + fileLastModified = TS_ARCHIVE_STAT_MTIME(fileInfo); + configFiles->fileChanged(fileName, configName); + mgmt_log("User has changed config file %s\n", fileName); + } result = true; } else { result = false; diff --git a/mgmt/ConfigManager.h b/mgmt/ConfigManager.h index d27aed10a5a..f32cb2a8401 100644 --- a/mgmt/ConfigManager.h +++ b/mgmt/ConfigManager.h @@ -31,6 +31,11 @@ class TextBuffer; class ExpandingArray; +enum RollBackCheckType { + ROLLBACK_CHECK_AND_UPDATE, + ROLLBACK_CHECK_ONLY, +}; + // // class ConfigManager // @@ -66,7 +71,7 @@ class ConfigManager }; // Check if a file has changed, automatically holds the lock. Used by FileManager. - bool checkForUserUpdate(); + bool checkForUserUpdate(RollBackCheckType); // These are getters, for FileManager to get info about a particular configuration. const char * diff --git a/mgmt/FileManager.cc b/mgmt/FileManager.cc index e5737e9458d..c23f17f4e73 100644 --- a/mgmt/FileManager.cc +++ b/mgmt/FileManager.cc @@ -177,7 +177,7 @@ FileManager::rereadConfig() rb = it.second; // ToDo: rb->isVersions() was always true before, because numberBackups was always >= 1. So ROLLBACK_CHECK_ONLY could not // happen at all... - if (rb->checkForUserUpdate()) { + if (rb->checkForUserUpdate(ROLLBACK_CHECK_AND_UPDATE)) { changedFiles.push_back(rb); if (rb->isChildManaged()) { if (std::find(parentFileNeedChange.begin(), parentFileNeedChange.end(), rb->getParentConfig()) == @@ -237,7 +237,7 @@ FileManager::isConfigStale() ink_mutex_acquire(&accessLock); for (auto &&it : bindings) { rb = it.second; - if (rb->checkForUserUpdate()) { + if (rb->checkForUserUpdate(ROLLBACK_CHECK_ONLY)) { stale = true; break; } From 6fa482bf0d9504dd5168af7107aca9c66a894729 Mon Sep 17 00:00:00 2001 From: Susan Hinrichs Date: Wed, 2 Oct 2019 14:19:47 +0000 Subject: [PATCH 048/718] Revert "Optimize: If failed on migrateToCurrentThread, put the server session back to global server session pool" This reverts commit c776c6677b0c005dd511945ae023a14f8f6b0bc3. Conflicts: iocore/net/UnixNetVConnection.cc (cherry picked from commit 26a51a0fb22095e0befc461c53691d3d0dd2d948) --- iocore/net/UnixNetVConnection.cc | 74 ++++++++++---------------------- proxy/http/HttpSessionManager.cc | 24 ++++++----- 2 files changed, 37 insertions(+), 61 deletions(-) diff --git a/iocore/net/UnixNetVConnection.cc b/iocore/net/UnixNetVConnection.cc index e4e8cf67d70..448ae426f14 100644 --- a/iocore/net/UnixNetVConnection.cc +++ b/iocore/net/UnixNetVConnection.cc @@ -1176,7 +1176,6 @@ UnixNetVConnection::populate(Connection &con_in, Continuation *c, void *arg) } if (h->startIO(this) < 0) { - con_in.move(this->con); Debug("iocore_net", "populate : Failed to add to epoll list"); return EVENT_ERROR; } @@ -1370,71 +1369,44 @@ UnixNetVConnection::migrateToCurrentThread(Continuation *cont, EThread *t) return this; } - // Lock the NetHandler first in order to put the new NetVC into NetHandler and InactivityCop. - // It is safe and no performance issue to get the mutex lock for a NetHandler of current ethread. - SCOPED_MUTEX_LOCK(lock, client_nh->mutex, t); - - // Try to get the mutex lock for NetHandler of this NetVC - MUTEX_TRY_LOCK(lock_src, this->nh->mutex, t); - if (lock_src.is_locked()) { - // Detach this NetVC from original NetHandler & InactivityCop. - this->nh->stopCop(this); - this->nh->stopIO(this); - // Put this NetVC into current NetHandler & InactivityCop. - this->thread = t; - client_nh->startIO(this); - client_nh->startCop(this); - // Move this NetVC to current EThread Successfully. - return this; - } - - // Failed to get the mutex lock for original NetHandler. - // Try to migrate it by create a new NetVC and then move con.fd and ssl ctx. + Connection hold_con; + hold_con.move(this->con); SSLNetVConnection *sslvc = dynamic_cast(this); - SSL *save_ssl = (sslvc) ? sslvc->ssl : nullptr; - UnixNetVConnection *ret_vc = nullptr; + SSL *save_ssl = (sslvc) ? sslvc->ssl : nullptr; + if (save_ssl) { + SSLNetVCDetach(sslvc->ssl); + sslvc->ssl = nullptr; + } + + // Do_io_close will signal the VC to be freed on the original thread + // Since we moved the con context, the fd will not be closed + // Go ahead and remove the fd from the original thread's epoll structure, so it is not + // processed on two threads simultaneously + this->ep.stop(); + this->do_io_close(); // Create new VC: if (save_ssl) { SSLNetVConnection *sslvc = static_cast(sslNetProcessor.allocate_vc(t)); - if (sslvc->populate(this->con, cont, save_ssl) != EVENT_DONE) { - sslvc->free(t); - sslvc = nullptr; - ret_vc = this; + if (sslvc->populate(hold_con, cont, save_ssl) != EVENT_DONE) { + sslvc->do_io_close(); + sslvc = nullptr; } else { sslvc->set_context(get_context()); - ret_vc = dynamic_cast(sslvc); } + return sslvc; + // Update the SSL fields } else { UnixNetVConnection *netvc = static_cast(netProcessor.allocate_vc(t)); - if (netvc->populate(this->con, cont, save_ssl) != EVENT_DONE) { - netvc->free(t); - netvc = nullptr; - ret_vc = this; + if (netvc->populate(hold_con, cont, save_ssl) != EVENT_DONE) { + netvc->do_io_close(); + netvc = nullptr; } else { netvc->set_context(get_context()); - ret_vc = netvc; } + return netvc; } - - // clear con.fd and ssl ctx from this NetVC since a new NetVC is created. - if (ret_vc != this) { - if (save_ssl) { - SSLNetVCDetach(sslvc->ssl); - sslvc->ssl = nullptr; - } - ink_assert(this->con.fd == NO_FD); - - // Do_io_close will signal the VC to be freed on the original thread - // Since we moved the con context, the fd will not be closed - // Go ahead and remove the fd from the original thread's epoll structure, so it is not - // processed on two threads simultaneously - this->ep.stop(); - this->do_io_close(); - } - - return ret_vc; } void diff --git a/proxy/http/HttpSessionManager.cc b/proxy/http/HttpSessionManager.cc index 4215ca8a9c4..b50e854d101 100644 --- a/proxy/http/HttpSessionManager.cc +++ b/proxy/http/HttpSessionManager.cc @@ -340,17 +340,21 @@ HttpSessionManager::acquire_session(Continuation * /* cont ATS_UNUSED */, sockad UnixNetVConnection *server_vc = dynamic_cast(to_return->get_netvc()); if (server_vc) { UnixNetVConnection *new_vc = server_vc->migrateToCurrentThread(sm, ethread); - if (new_vc->thread != ethread) { - // Failed to migrate, put it back to global session pool - m_g_pool->releaseSession(to_return); - to_return = nullptr; - retval = HSM_NOT_FOUND; - } else if (new_vc != server_vc) { - // The VC migrated, keep things from timing out on us - new_vc->set_inactivity_timeout(new_vc->get_inactivity_timeout()); - to_return->set_netvc(new_vc); + // The VC moved, free up the original one + if (new_vc != server_vc) { + ink_assert(new_vc == nullptr || new_vc->nh != nullptr); + if (!new_vc) { + // Close out to_return, we were't able to get a connection + to_return->do_io_close(); + to_return = nullptr; + retval = HSM_NOT_FOUND; + } else { + // Keep things from timing out on us + new_vc->set_inactivity_timeout(new_vc->get_inactivity_timeout()); + to_return->set_netvc(new_vc); + } } else { - // The VC moved, keep things from timing out on us + // Keep things from timing out on us server_vc->set_inactivity_timeout(server_vc->get_inactivity_timeout()); } } From e2302526a698e6be0c0aa5a70346c7e3b6971b6f Mon Sep 17 00:00:00 2001 From: Gancho Tenev Date: Tue, 17 Sep 2019 10:06:50 -0700 Subject: [PATCH 049/718] cachekey: allow multiple values for `--key-type` Allow multiple target types to be specified for `--key-type` so the operator can apply the same modifications to both cache key and parent selection url at the same time without chaining cachekey plugin instances. Instead of: @plugin=cachekey.so \ @pparam=--key-type=parent_selection_url \ @pparam=--remove-all-params=true @plugin=cachekey.so \ @pparam=--key-type=cache_key \ @pparam=--remove-all-params=true to write: @plugin=cachekey.so \ @pparam=--key-type=parent_selection_url,cache_key \ @pparam=--remove-all-params=true (cherry picked from commit db8cd14acede7460a5996864c52e1b206695e405) --- doc/admin-guide/plugins/cachekey.en.rst | 25 ++++++++++--- plugins/cachekey/configs.cc | 29 +++++++++------ plugins/cachekey/configs.h | 6 ++-- plugins/cachekey/plugin.cc | 48 +++++++++++++------------ 4 files changed, 70 insertions(+), 38 deletions(-) diff --git a/doc/admin-guide/plugins/cachekey.en.rst b/doc/admin-guide/plugins/cachekey.en.rst index 3ee09484da2..5b6ba4cdd18 100644 --- a/doc/admin-guide/plugins/cachekey.en.rst +++ b/doc/admin-guide/plugins/cachekey.en.rst @@ -53,11 +53,11 @@ Key type The plugin manipulates the `cache key` by default. If `parent selection URL` manipulation is needed the following option can be used: -* ``--key-type=[cache_key|parent_selection_url]`` (default: ``cache_key``) +* ``--key-type=`` (default: ``cache_key``) - list of ``cache_key`` or ``parent_selection_url``, if multiple ``--key-type`` options are specified then all values are combined together. + +An instance of this plugin can be used for applying manipulations to `cache key`, `parent selection URL` or both depending on the need. See `simultaneous cache key and parent selection URL manipulation`_ +for examples of how to apply the **same** set of manupulations to both targets with a single plugin instance or applying **diferent** sets of manipulations to each target using separate plugin instances. -One instance of this plugin can used either for `cache key` or `parent selection URL` manupulation but never both. -If `simultaneous cache key and parent selection URL manipulation`_ is needed two separate instances of the plugin -have to be loaded for each key type. Cache key structure and related plugin parameters ================================================= @@ -664,3 +664,20 @@ For this purpose two separate instances are loaded for that remap rule: In the example above the first instance of the plugin sets the prefix to the parent selection URI and the second instance of the plugin sets the prefix to the cache key. + +The **same** string manipulations can be applied to both cache key and parent selection url more concisely without chaining cachekey plugin instances by specifying multiple target types `--key-type`. + +Instead of:: + + @plugin=cachekey.so \ + @pparam=--key-type=parent_selection_url \ + @pparam=--remove-all-params=true + @plugin=cachekey.so \ + @pparam=--key-type=cache_key \ + @pparam=--remove-all-params=true + +one could write:: + + @plugin=cachekey.so \ + @pparam=--key-type=parent_selection_url,cache_key \ + @pparam=--remove-all-params=true diff --git a/plugins/cachekey/configs.cc b/plugins/cachekey/configs.cc index 335bb2d5a06..938ae1d5cad 100644 --- a/plugins/cachekey/configs.cc +++ b/plugins/cachekey/configs.cc @@ -529,6 +529,10 @@ Configs::init(int argc, const char *argv[], bool perRemapConfig) bool Configs::finalize() { + if (_keyTypes.empty()) { + CacheKeyDebug("setting cache key"); + _keyTypes = {CACHE_KEY}; + } return _query.finalize() && _headers.finalize() && _cookies.finalize(); } @@ -586,14 +590,19 @@ void Configs::setKeyType(const char *arg) { if (nullptr != arg) { - if (9 == strlen(arg) && 0 == strncasecmp(arg, "cache_key", 9)) { - _keyType = CacheKeyKeyType::CACHE_KEY; - CacheKeyDebug("setting cache key"); - } else if (20 == strlen(arg) && 0 == strncasecmp(arg, "parent_selection_url", 20)) { - _keyType = CacheKeyKeyType::PARENT_SELECTION_URL; - CacheKeyDebug("setting parent selection URL"); - } else { - CacheKeyError("unrecognized key type '%s', using default 'cache_key'", arg); + StringVector types; + ::commaSeparateString(types, arg); + + for (auto type : types) { + if (9 == type.length() && 0 == strncasecmp(type.c_str(), "cache_key", 9)) { + _keyTypes.insert(CacheKeyKeyType::CACHE_KEY); + CacheKeyDebug("setting cache key"); + } else if (20 == type.length() && 0 == strncasecmp(type.c_str(), "parent_selection_url", 20)) { + _keyTypes.insert(CacheKeyKeyType::PARENT_SELECTION_URL); + CacheKeyDebug("setting parent selection URL"); + } else { + CacheKeyError("unrecognized key type '%s', using default 'cache_key'", arg); + } } } else { CacheKeyError("found an empty key type, using default 'cache_key'"); @@ -606,10 +615,10 @@ Configs::getUriType() return _uriType; } -CacheKeyKeyType +CacheKeyKeyTypeSet & Configs::getKeyType() { - return _keyType; + return _keyTypes; } const char * diff --git a/plugins/cachekey/configs.h b/plugins/cachekey/configs.h index 3ccf2a1b29c..e8712f18342 100644 --- a/plugins/cachekey/configs.h +++ b/plugins/cachekey/configs.h @@ -41,6 +41,8 @@ enum CacheKeyKeyType { const char *getCacheKeyUriTypeName(CacheKeyUriType type); const char *getCacheKeyKeyTypeName(CacheKeyKeyType type); +typedef std::set CacheKeyKeyTypeSet; + /** * @brief Plug-in configuration elements (query / headers / cookies). * @@ -203,7 +205,7 @@ class Configs /** * @brief get target URI type. */ - CacheKeyKeyType getKeyType(); + CacheKeyKeyTypeSet &getKeyType(); /* Make the following members public to avoid unnecessary accessors */ ConfigQuery _query; /**< @brief query parameter related configuration */ @@ -231,5 +233,5 @@ class Configs bool _canonicalPrefix = false; /**< @brief keep the URI scheme and authority element used as input to transforming into key */ String _separator = "/"; /**< @brief a separator used to separate the cache key elements extracted from the URI */ CacheKeyUriType _uriType = REMAP; /**< @brief shows which URI the cache key will be based on */ - CacheKeyKeyType _keyType = CACHE_KEY; /**< @brief target URI to be modified, cache key or paren selection */ + CacheKeyKeyTypeSet _keyTypes; /**< @brief target URI to be modified, cache key or paren selection */ }; diff --git a/plugins/cachekey/plugin.cc b/plugins/cachekey/plugin.cc index aff94f96736..d92c079271a 100644 --- a/plugins/cachekey/plugin.cc +++ b/plugins/cachekey/plugin.cc @@ -38,34 +38,38 @@ Configs *globalConfig = nullptr; static void setCacheKey(TSHttpTxn txn, Configs *config, TSRemapRequestInfo *rri = nullptr) { - /* Initial cache key facility from the requested URL. */ - CacheKey cachekey(txn, config->getSeparator(), config->getUriType(), config->getKeyType(), rri); + const CacheKeyKeyTypeSet &keyTypes = config->getKeyType(); - /* Append custom prefix or the host:port */ - if (!config->prefixToBeRemoved()) { - cachekey.appendPrefix(config->_prefix, config->_prefixCapture, config->_prefixCaptureUri, config->canonicalPrefix()); - } - /* Classify User-Agent and append the class name to the cache key if matched. */ - cachekey.appendUaClass(config->_classifier); + for (auto type : keyTypes) { + /* Initial cache key facility from the requested URL. */ + CacheKey cachekey(txn, config->getSeparator(), config->getUriType(), type, rri); - /* Capture from User-Agent header. */ - cachekey.appendUaCaptures(config->_uaCapture); + /* Append custom prefix or the host:port */ + if (!config->prefixToBeRemoved()) { + cachekey.appendPrefix(config->_prefix, config->_prefixCapture, config->_prefixCaptureUri, config->canonicalPrefix()); + } + /* Classify User-Agent and append the class name to the cache key if matched. */ + cachekey.appendUaClass(config->_classifier); - /* Append headers to the cache key. */ - cachekey.appendHeaders(config->_headers); + /* Capture from User-Agent header. */ + cachekey.appendUaCaptures(config->_uaCapture); - /* Append cookies to the cache key. */ - cachekey.appendCookies(config->_cookies); + /* Append headers to the cache key. */ + cachekey.appendHeaders(config->_headers); - /* Append the path to the cache key. */ - if (!config->pathToBeRemoved()) { - cachekey.appendPath(config->_pathCapture, config->_pathCaptureUri); - } - /* Append query parameters to the cache key. */ - cachekey.appendQuery(config->_query); + /* Append cookies to the cache key. */ + cachekey.appendCookies(config->_cookies); - /* Set the cache key */ - cachekey.finalize(); + /* Append the path to the cache key. */ + if (!config->pathToBeRemoved()) { + cachekey.appendPath(config->_pathCapture, config->_pathCaptureUri); + } + /* Append query parameters to the cache key. */ + cachekey.appendQuery(config->_query); + + /* Set the cache key */ + cachekey.finalize(); + } } static int From 4c9bdef9f311c1c2da65019928429f8f05897a7c Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Tue, 3 Sep 2019 11:24:05 +0900 Subject: [PATCH 050/718] Cleanup: unifdef TRACK_BUFFER_USER (cherry picked from commit 64595af3d0fb7882993016d67e43e7c5ca3af914) --- iocore/eventsystem/I_IOBuffer.h | 69 ++------------- iocore/eventsystem/P_IOBuffer.h | 144 +++++--------------------------- 2 files changed, 29 insertions(+), 184 deletions(-) diff --git a/iocore/eventsystem/I_IOBuffer.h b/iocore/eventsystem/I_IOBuffer.h index 4390bb1e256..f83bc3205a4 100644 --- a/iocore/eventsystem/I_IOBuffer.h +++ b/iocore/eventsystem/I_IOBuffer.h @@ -56,10 +56,6 @@ inkcoreapi extern int64_t max_iobuffer_size; extern int64_t default_small_iobuffer_size; extern int64_t default_large_iobuffer_size; // matched to size of OS buffers -#if !defined(TRACK_BUFFER_USER) -#define TRACK_BUFFER_USER 1 -#endif - enum AllocType { NO_ALLOC, MEMALIGNED, @@ -231,9 +227,7 @@ class IOBufferData : public RefCountObj */ char *_data = nullptr; -#ifdef TRACK_BUFFER_USER const char *_location = nullptr; -#endif /** Constructor. Initializes state for a IOBufferData object. Do not use @@ -464,9 +458,7 @@ class IOBufferBlock : public RefCountObj char *_end = nullptr; char *_buf_end = nullptr; -#ifdef TRACK_BUFFER_USER const char *_location = nullptr; -#endif /** The underlying reference to the allocated memory. A reference to a @@ -1255,9 +1247,7 @@ class MIOBuffer Ptr _writer; IOBufferReader readers[MAX_MIOBUFFER_READERS]; -#ifdef TRACK_BUFFER_USER const char *_location = nullptr; -#endif MIOBuffer(void *b, int64_t bufsize, int64_t aWater_mark); // cppcheck-suppress noExplicitConstructor; allow implicit conversion @@ -1323,13 +1313,8 @@ struct MIOBufferAccessor { IOBufferReader *entry = nullptr; }; -extern MIOBuffer *new_MIOBuffer_internal( -#ifdef TRACK_BUFFER_USER - const char *loc, -#endif - int64_t size_index = default_large_iobuffer_size); +extern MIOBuffer *new_MIOBuffer_internal(const char *loc, int64_t size_index = default_large_iobuffer_size); -#ifdef TRACK_BUFFER_USER class MIOBuffer_tracker { const char *loc; @@ -1342,15 +1327,9 @@ class MIOBuffer_tracker return new_MIOBuffer_internal(loc, size_index); } }; -#endif -extern MIOBuffer *new_empty_MIOBuffer_internal( -#ifdef TRACK_BUFFER_USER - const char *loc, -#endif - int64_t size_index = default_large_iobuffer_size); +extern MIOBuffer *new_empty_MIOBuffer_internal(const char *loc, int64_t size_index = default_large_iobuffer_size); -#ifdef TRACK_BUFFER_USER class Empty_MIOBuffer_tracker { const char *loc; @@ -1363,32 +1342,17 @@ class Empty_MIOBuffer_tracker return new_empty_MIOBuffer_internal(loc, size_index); } }; -#endif /// MIOBuffer allocator/deallocator -#ifdef TRACK_BUFFER_USER #define new_MIOBuffer MIOBuffer_tracker(RES_PATH("memory/IOBuffer/")) #define new_empty_MIOBuffer Empty_MIOBuffer_tracker(RES_PATH("memory/IOBuffer/")) -#else -#define new_MIOBuffer new_MIOBuffer_internal -#define new_empty_MIOBuffer new_empty_MIOBuffer_internal -#endif extern void free_MIOBuffer(MIOBuffer *mio); ////////////////////////////////////////////////////////////////////// -extern IOBufferBlock *new_IOBufferBlock_internal( -#ifdef TRACK_BUFFER_USER - const char *loc -#endif -); +extern IOBufferBlock *new_IOBufferBlock_internal(const char *loc); -extern IOBufferBlock *new_IOBufferBlock_internal( -#ifdef TRACK_BUFFER_USER - const char *loc, -#endif - IOBufferData *d, int64_t len = 0, int64_t offset = 0); +extern IOBufferBlock *new_IOBufferBlock_internal(const char *loc, IOBufferData *d, int64_t len = 0, int64_t offset = 0); -#ifdef TRACK_BUFFER_USER class IOBufferBlock_tracker { const char *loc; @@ -1406,29 +1370,16 @@ class IOBufferBlock_tracker return new_IOBufferBlock_internal(loc, d.get(), len, offset); } }; -#endif /// IOBufferBlock allocator -#ifdef TRACK_BUFFER_USER #define new_IOBufferBlock IOBufferBlock_tracker(RES_PATH("memory/IOBuffer/")) -#else -#define new_IOBufferBlock new_IOBufferBlock_internal -#endif //////////////////////////////////////////////////////////// -extern IOBufferData *new_IOBufferData_internal( -#ifdef TRACK_BUFFER_USER - const char *location, -#endif - int64_t size_index = default_large_iobuffer_size, AllocType type = DEFAULT_ALLOC); +extern IOBufferData *new_IOBufferData_internal(const char *location, int64_t size_index = default_large_iobuffer_size, + AllocType type = DEFAULT_ALLOC); -extern IOBufferData *new_xmalloc_IOBufferData_internal( -#ifdef TRACK_BUFFER_USER - const char *location, -#endif - void *b, int64_t size); +extern IOBufferData *new_xmalloc_IOBufferData_internal(const char *location, void *b, int64_t size); -#ifdef TRACK_BUFFER_USER class IOBufferData_tracker { const char *loc; @@ -1441,16 +1392,10 @@ class IOBufferData_tracker return new_IOBufferData_internal(loc, size_index, type); } }; -#endif // TODO: remove new_xmalloc_IOBufferData. Because ats_xmalloc() doesn't exist anymore. -#ifdef TRACK_BUFFER_USER #define new_IOBufferData IOBufferData_tracker(RES_PATH("memory/IOBuffer/")) #define new_xmalloc_IOBufferData(b, size) new_xmalloc_IOBufferData_internal(RES_PATH("memory/IOBuffer/"), (b), (size)) -#else -#define new_IOBufferData new_IOBufferData_internal -#define new_xmalloc_IOBufferData new_xmalloc_IOBufferData_internal -#endif extern int64_t iobuffer_size_to_index(int64_t size, int64_t max = max_iobuffer_size); extern int64_t index_to_buffer_size(int64_t idx); diff --git a/iocore/eventsystem/P_IOBuffer.h b/iocore/eventsystem/P_IOBuffer.h index 49e65555d0c..8814614200d 100644 --- a/iocore/eventsystem/P_IOBuffer.h +++ b/iocore/eventsystem/P_IOBuffer.h @@ -146,7 +146,6 @@ iobufferblock_skip(IOBufferBlock *b, int64_t *poffset, int64_t *plen, int64_t wr return b; } -#ifdef TRACK_BUFFER_USER TS_INLINE void iobuffer_mem_inc(const char *_loc, int64_t _size_index) { @@ -179,7 +178,6 @@ iobuffer_mem_dec(const char *_loc, int64_t _size_index) } ResourceTracker::increment(_loc, -index_to_buffer_size(_size_index)); } -#endif ////////////////////////////////////////////////////////////////// // @@ -199,62 +197,34 @@ IOBufferData::block_size() } TS_INLINE IOBufferData * -new_IOBufferData_internal( -#ifdef TRACK_BUFFER_USER - const char *location, -#endif - void *b, int64_t size, int64_t asize_index) +new_IOBufferData_internal(const char *location, void *b, int64_t size, int64_t asize_index) { (void)size; IOBufferData *d = THREAD_ALLOC(ioDataAllocator, this_thread()); d->_size_index = asize_index; ink_assert(BUFFER_SIZE_INDEX_IS_CONSTANT(asize_index) || size <= d->block_size()); -#ifdef TRACK_BUFFER_USER d->_location = location; -#endif - d->_data = (char *)b; + d->_data = (char *)b; return d; } TS_INLINE IOBufferData * -new_xmalloc_IOBufferData_internal( -#ifdef TRACK_BUFFER_USER - const char *location, -#endif - void *b, int64_t size) +new_xmalloc_IOBufferData_internal(const char *location, void *b, int64_t size) { - return new_IOBufferData_internal( -#ifdef TRACK_BUFFER_USER - location, -#endif - b, size, BUFFER_SIZE_INDEX_FOR_XMALLOC_SIZE(size)); + return new_IOBufferData_internal(location, b, size, BUFFER_SIZE_INDEX_FOR_XMALLOC_SIZE(size)); } TS_INLINE IOBufferData * -new_IOBufferData_internal( -#ifdef TRACK_BUFFER_USER - const char *location, -#endif - void *b, int64_t size) +new_IOBufferData_internal(const char *location, void *b, int64_t size) { - return new_IOBufferData_internal( -#ifdef TRACK_BUFFER_USER - location, -#endif - b, size, iobuffer_size_to_index(size)); + return new_IOBufferData_internal(location, b, size, iobuffer_size_to_index(size)); } TS_INLINE IOBufferData * -new_IOBufferData_internal( -#ifdef TRACK_BUFFER_USER - const char *loc, -#endif - int64_t size_index, AllocType type) +new_IOBufferData_internal(const char *loc, int64_t size_index, AllocType type) { IOBufferData *d = THREAD_ALLOC(ioDataAllocator, this_thread()); -#ifdef TRACK_BUFFER_USER - d->_location = loc; -#endif + d->_location = loc; d->alloc(size_index, type); return d; } @@ -271,9 +241,7 @@ IOBufferData::alloc(int64_t size_index, AllocType type) } _size_index = size_index; _mem_type = type; -#ifdef TRACK_BUFFER_USER iobuffer_mem_inc(_location, size_index); -#endif switch (type) { case MEMALIGNED: if (BUFFER_SIZE_INDEX_IS_FAST_ALLOCATED(size_index)) { @@ -299,9 +267,7 @@ IOBufferData::alloc(int64_t size_index, AllocType type) TS_INLINE void IOBufferData::dealloc() { -#ifdef TRACK_BUFFER_USER iobuffer_mem_dec(_location, _size_index); -#endif switch (_mem_type) { case MEMALIGNED: if (BUFFER_SIZE_INDEX_IS_FAST_ALLOCATED(_size_index)) { @@ -338,30 +304,18 @@ IOBufferData::free() // ////////////////////////////////////////////////////////////////// TS_INLINE IOBufferBlock * -new_IOBufferBlock_internal( -#ifdef TRACK_BUFFER_USER - const char *location -#endif -) +new_IOBufferBlock_internal(const char *location) { IOBufferBlock *b = THREAD_ALLOC(ioBlockAllocator, this_thread()); -#ifdef TRACK_BUFFER_USER - b->_location = location; -#endif + b->_location = location; return b; } TS_INLINE IOBufferBlock * -new_IOBufferBlock_internal( -#ifdef TRACK_BUFFER_USER - const char *location, -#endif - IOBufferData *d, int64_t len, int64_t offset) +new_IOBufferBlock_internal(const char *location, IOBufferData *d, int64_t len, int64_t offset) { IOBufferBlock *b = THREAD_ALLOC(ioBlockAllocator, this_thread()); -#ifdef TRACK_BUFFER_USER - b->_location = location; -#endif + b->_location = location; b->set(d, len, offset); return b; } @@ -397,11 +351,7 @@ TS_INLINE void IOBufferBlock::alloc(int64_t i) { ink_assert(BUFFER_SIZE_ALLOCATED(i)); -#ifdef TRACK_BUFFER_USER data = new_IOBufferData_internal(_location, i); -#else - data = new_IOBufferData_internal(i); -#endif reset(); } @@ -434,18 +384,12 @@ IOBufferBlock::clear() TS_INLINE IOBufferBlock * IOBufferBlock::clone() const { -#ifdef TRACK_BUFFER_USER IOBufferBlock *b = new_IOBufferBlock_internal(_location); -#else - IOBufferBlock *b = new_IOBufferBlock_internal(); -#endif - b->data = data; - b->_start = _start; - b->_end = _end; - b->_buf_end = _end; -#ifdef TRACK_BUFFER_USER - b->_location = _location; -#endif + b->data = data; + b->_start = _start; + b->_end = _end; + b->_buf_end = _end; + b->_location = _location; return b; } @@ -465,15 +409,9 @@ IOBufferBlock::free() TS_INLINE void IOBufferBlock::set_internal(void *b, int64_t len, int64_t asize_index) { -#ifdef TRACK_BUFFER_USER - data = new_IOBufferData_internal(_location, BUFFER_SIZE_NOT_ALLOCATED); -#else - data = new_IOBufferData_internal(BUFFER_SIZE_NOT_ALLOCATED); -#endif + data = new_IOBufferData_internal(_location, BUFFER_SIZE_NOT_ALLOCATED); data->_data = (char *)b; -#ifdef TRACK_BUFFER_USER iobuffer_mem_inc(_location, asize_index); -#endif data->_size_index = asize_index; reset(); _end = _start + len; @@ -728,9 +666,7 @@ inkcoreapi extern ClassAllocator ioAllocator; TS_INLINE MIOBuffer::MIOBuffer(void *b, int64_t bufsize, int64_t aWater_mark) { -#ifdef TRACK_BUFFER_USER _location = nullptr; -#endif set(b, bufsize); water_mark = aWater_mark; size_index = BUFFER_SIZE_NOT_ALLOCATED; @@ -742,9 +678,7 @@ MIOBuffer::MIOBuffer(int64_t default_size_index) { clear(); size_index = default_size_index; -#ifdef TRACK_BUFFER_USER - _location = nullptr; -#endif + _location = nullptr; return; } @@ -752,9 +686,7 @@ TS_INLINE MIOBuffer::MIOBuffer() { clear(); -#ifdef TRACK_BUFFER_USER _location = nullptr; -#endif return; } @@ -766,16 +698,10 @@ MIOBuffer::~MIOBuffer() } TS_INLINE MIOBuffer * -new_MIOBuffer_internal( -#ifdef TRACK_BUFFER_USER - const char *location, -#endif - int64_t size_index) +new_MIOBuffer_internal(const char *location, int64_t size_index) { MIOBuffer *b = THREAD_ALLOC(ioAllocator, this_thread()); -#ifdef TRACK_BUFFER_USER b->_location = location; -#endif b->alloc(size_index); b->water_mark = 0; return b; @@ -790,18 +716,12 @@ free_MIOBuffer(MIOBuffer *mio) } TS_INLINE MIOBuffer * -new_empty_MIOBuffer_internal( -#ifdef TRACK_BUFFER_USER - const char *location, -#endif - int64_t size_index) +new_empty_MIOBuffer_internal(const char *location, int64_t size_index) { MIOBuffer *b = THREAD_ALLOC(ioAllocator, this_thread()); b->size_index = size_index; b->water_mark = 0; -#ifdef TRACK_BUFFER_USER - b->_location = location; -#endif + b->_location = location; return b; } @@ -948,11 +868,7 @@ TS_INLINE void MIOBuffer::append_block(int64_t asize_index) { ink_assert(BUFFER_SIZE_ALLOCATED(asize_index)); -#ifdef TRACK_BUFFER_USER IOBufferBlock *b = new_IOBufferBlock_internal(_location); -#else - IOBufferBlock *b = new_IOBufferBlock_internal(); -#endif b->alloc(asize_index); append_block_internal(b); return; @@ -1071,11 +987,7 @@ MIOBuffer::max_read_avail() TS_INLINE void MIOBuffer::set(void *b, int64_t len) { -#ifdef TRACK_BUFFER_USER _writer = new_IOBufferBlock_internal(_location); -#else - _writer = new_IOBufferBlock_internal(); -#endif _writer->set_internal(b, len, BUFFER_SIZE_INDEX_FOR_CONSTANT_SIZE(len)); init_readers(); } @@ -1083,11 +995,7 @@ MIOBuffer::set(void *b, int64_t len) TS_INLINE void MIOBuffer::append_xmalloced(void *b, int64_t len) { -#ifdef TRACK_BUFFER_USER IOBufferBlock *x = new_IOBufferBlock_internal(_location); -#else - IOBufferBlock *x = new_IOBufferBlock_internal(); -#endif x->set_internal(b, len, BUFFER_SIZE_INDEX_FOR_XMALLOC_SIZE(len)); append_block_internal(x); } @@ -1095,11 +1003,7 @@ MIOBuffer::append_xmalloced(void *b, int64_t len) TS_INLINE void MIOBuffer::append_fast_allocated(void *b, int64_t len, int64_t fast_size_index) { -#ifdef TRACK_BUFFER_USER IOBufferBlock *x = new_IOBufferBlock_internal(_location); -#else - IOBufferBlock *x = new_IOBufferBlock_internal(); -#endif x->set_internal(b, len, fast_size_index); append_block_internal(x); } @@ -1107,11 +1011,7 @@ MIOBuffer::append_fast_allocated(void *b, int64_t len, int64_t fast_size_index) TS_INLINE void MIOBuffer::alloc(int64_t i) { -#ifdef TRACK_BUFFER_USER _writer = new_IOBufferBlock_internal(_location); -#else - _writer = new_IOBufferBlock_internal(); -#endif _writer->alloc(i); size_index = i; init_readers(); From 28e1d6d47b4aab5635677a56e6926829345ae15c Mon Sep 17 00:00:00 2001 From: "Alan M. Carroll" Date: Fri, 16 Aug 2019 18:55:48 -0500 Subject: [PATCH 051/718] Doc: Guide to remap plugin API. (cherry picked from commit 5cb4b316ad93fd4c78f44effc4c1dfbe4949543c) --- .../api/functions/TSRemap.en.rst | 16 +- .../api/functions/TSTypes.en.rst | 40 +++++ doc/developer-guide/plugins/index.en.rst | 1 + .../plugins/remap-plugins.en.rst | 148 ++++++++++++++++++ 4 files changed, 198 insertions(+), 7 deletions(-) create mode 100644 doc/developer-guide/plugins/remap-plugins.en.rst diff --git a/doc/developer-guide/api/functions/TSRemap.en.rst b/doc/developer-guide/api/functions/TSRemap.en.rst index 38d06d871eb..ddd99178a71 100644 --- a/doc/developer-guide/api/functions/TSRemap.en.rst +++ b/doc/developer-guide/api/functions/TSRemap.en.rst @@ -29,11 +29,11 @@ Synopsis `#include ` `#include ` -.. function:: TSReturnCode TSRemapInit(TSRemapInterface * api_info, char * errbuf, int errbuf_size) +.. function:: TSReturnCode TSRemapInit(TSRemapInterface * api_info, char * errbuff, int errbuff_size) .. function:: void TSRemapConfigReload(void) .. function:: void TSRemapDone(void) .. function:: TSRemapStatus TSRemapDoRemap(void * ih, TSHttpTxn rh, TSRemapRequestInfo * rri) -.. function:: TSReturnCode TSRemapNewInstance(int argc, char * argv[], void ** ih, char * errbuf, int errbuf_size) +.. function:: TSReturnCode TSRemapNewInstance(int argc, char * argv[], void ** ih, char * errbuff, int errbuff_size) .. function:: void TSRemapDeleteInstance(void * ) .. function:: void TSRemapOSResponse(void * ih, TSHttpTxn rh, int os_response_type) @@ -50,8 +50,8 @@ route the transaction through your plugin. Multiple remap plugins can be specified for a single remap rule, resulting in a remap plugin chain where each plugin is given an opportunity to examine the HTTP transaction. -:func:`TSRemapInit` is a required entry point. This function will be called -once when Traffic Server loads the plugin. If the optional :func:`TSRemapDone` +:func:`TSRemapInit` is a required entry point. This function will be called once when Traffic Server +loads the plugin. If the optional :func:`TSRemapDone` entry point is available, Traffic Server will call then when unloading the remap plugin. @@ -65,15 +65,17 @@ any data or continuations associated with that instance. entry point. In this function, the remap plugin may examine and modify the HTTP transaction. -:func:`TSRemapConfigReload` is called once for every remap plugin just before the -remap configuration file (:file:`remap.config`) is reloaded. This is an optional -entry point, which takes no arguments and has no return value. +:func:`TSRemapConfigReload` is called once for every remap plugin immediately after a new +configuration is successfully loaded and immediately before the new remap configuration becomes +active. This is an optional entry point, which takes no arguments and has no return value. Generally speaking, calls to these functions are mutually exclusive. The exception is for functions which take an HTTP transaction as a parameter. Calls to these transaction-specific functions for different transactions are not necessarily mutually exclusive of each other. +For further information, see :ref:`developer-plugins-remap`. + Types ===== diff --git a/doc/developer-guide/api/functions/TSTypes.en.rst b/doc/developer-guide/api/functions/TSTypes.en.rst index 9ffc3185ad5..20bed4490ad 100644 --- a/doc/developer-guide/api/functions/TSTypes.en.rst +++ b/doc/developer-guide/api/functions/TSTypes.en.rst @@ -143,8 +143,48 @@ more widely. Those are described on this page. .. type:: TSRemapInterface + Data passed to a remap plugin via :func:`TSRemapInit`. + + .. member:: unsigned long size + + The size of the structure in bytes, including this member. + + .. member:: unsigned long tsremap_version + + The API version of the C API. The lower 16 bits are the minor version, and the upper bits + the major version. + .. type:: TSRemapRequestInfo + Data passed to a remap plugin during the invocation of a remap rule. + + .. member:: TSMBuffer requestBufp + + The client request. All of the other :type:`TSMLoc` values use this as the base buffer. + + .. member:: TSMLoc requestHdrp + + The client request. + + .. member:: TSMLoc mapFromUrl + + The match URL in the remap rule. + + .. member:: TSMLoc mapToUrl + + The target URL in the remap rule. + + .. member:: TSMLoc requestUrl + + The current request URL. The remap rule and plugins listed earlier in the remap rule can modify this + from the client request URL. Remap plugins are expected to modify this value to perform the + remapping of the request. Note this is the same :code:`TSMLoc` as would be obtained by + calling :func:`TSHttpTxnClientReqGet`. + + .. member:: int redirect + + Flag for using the remapped URL as an explicit redirection. This can be set by the remap plugin. + .. type:: TSSslX509 This type represents the :code:`X509` object created from an SSL certificate. diff --git a/doc/developer-guide/plugins/index.en.rst b/doc/developer-guide/plugins/index.en.rst index 35ba0ff2626..4f528436110 100644 --- a/doc/developer-guide/plugins/index.en.rst +++ b/doc/developer-guide/plugins/index.en.rst @@ -37,6 +37,7 @@ Plugin Development io/index.en http-headers/index.en http-transformations/index.en + remap-plugins.en new-protocol-plugins.en plugin-interfaces.en adding-statistics.en diff --git a/doc/developer-guide/plugins/remap-plugins.en.rst b/doc/developer-guide/plugins/remap-plugins.en.rst new file mode 100644 index 00000000000..7b691c6e77a --- /dev/null +++ b/doc/developer-guide/plugins/remap-plugins.en.rst @@ -0,0 +1,148 @@ +.. Licensed to the Apache Software Foundation (ASF) under one or more contributor license + agreements. See the NOTICE file distributed with this work for additional information regarding + copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the License. You may obtain + a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the License + is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + or implied. See the License for the specific language governing permissions and limitations + under the License. + +.. include:: ../../common.defs +.. default-domain:: c +.. _developer-plugins-remap: + +Remap Plugins +************* + +Remap plugins are called during remap (URL rewriting). The particular plugins and the order is +determined by the remap rule. The :file:`remap.config` file can contain explicit references to +remap plugins in a rule and the presence of such a reference in a rule causes the plugin to be +invoked when the rule is matched. For example, a rule such as + +.. code-block:: text + + map http://example.one/ http://example.two/ @plugin=example.so @pparam=first_arg @pparm=second_arg + +will, if matched, cause the plugin "example.so" to be called with parameters "first_arg" and "second_arg". + +A key difference between global and remap plugins is reconfiguration and reloading. If +:file:`remap.config` is reloaded, then all remap plugins are reconfigured based on the new version +of the file. Global plugins need to handle their own configuration reloading, if any. + +In addition, as of |TS| 9.0, remap plugins can be reloaded during runtime. During a +:file:`remap.config` reload, if the plugin image file has changed, a new one is loaded and used. + +All of the externally invoked functions must be declared as :code:`extern "C"` in order to be +correctly located by the Traffic Server core. This is already done if :ts:git:`include/ts/remap.h` +is included, otherwise it must be done explicitly. + +Initialization +============== + +If any rule uses a plugin, the remap configuration loading will load the dynamic library and then +call :func:`TSRemapInit`. The plugin must return :macro:`TS_SUCCESS` or the configuration loading +will fail. If there is an error during the invocation of this function a C string style message +should be placed in :arg:`errbuff`, taking note of the maximum size of the buffer passed in +:arg:`errbuff_size`. The message is checked if the function returns a value other than +:macro:`TS_SUCCESS`. + +This function should perform any plugin global initialization, such as setting up static data +tables. It only be called immediately after the dynamic library is loaded from disk. + +Configuration +============= + +For each plugin invocation in a remap rule, :func:`TSRemapNewInstance` is called. + +The parameters :arg:`argc`, :arg:`argv` specify an array of arguments to the invocation instance in +the standard way. :arg:`argc` is the number of arguments present and :arg:`argv` is an array of +pointers, each of which points to a plugin parameter. The number of valid elements is :arg:`argc`. +Note these pointers are valid only for the duration of the function call. If any part of them need +persistent storage, that must be provided by the plugin. + +:arg:`ih` is for invocation instance storage data. This initially points at a :code:`nullptr`. If +that pointer is updated the new value will be preserved and passed back to the plugin in later +callbacks. This enables it to serve to identify which particular rule was matched and provide +context data. The standard use is to allocate a class instance, store rule relevant context data in +that instance, and update :arg:`ih` to point at the instance. The most common data is that derived +from the invocation arguments passed in :arg:`argc`, :arg:`argv`. + +:arg:`errbuff` and :arg:`errbuff_size` specify a writeable buffer used to report errors. Error +messages must be C strings and must fit in the buffer, including the terminating null. + +In essence, :func:`TSRemapNewInstance` is called to create an invocation instance for the plugin to +store rule local data. If the plugin is invoked multiples time on a rule, this will be called +multiple times for the rule, once for each invocation. Only the value store in :arg:`ih` will be +available when the rule is actually matched. In particular the plugin arguments will not be +available. + +Calls to :func:`TSRemapNewInstance` are serialized. + +If there is an error then the callback should return :macro:`TS_ERROR` and fill in the +:arg:`errbuff` with a C-string describing the error. Otherwise the function must return +:macro:`TS_SUCCESS`. + +Runtime +======= + +At runtime, if a remap rule is matched, the plugin is invoked by calling :func:`TSRemapDoRemap`. +This function is responsible for performing the plugin operation for the transaction. + +:arg:`ih` is the same value set in :func:`TSRemapNewInstance` for the invocation instance. This is +not examined or checked by the core. :arg:`rh` is the transaction for which the rule matched. +:arg:`rri` is information about the rule and the transaction. + +The callback is required to return a :type:`TSRemapStatus` indicating whether it performed a remap. +This is used for verifying a request was remapped if remapping is required. This can also be used +to prevent further remapping, although this should be used with caution. + +Calls to :func:`TSRemapDoRemap` are not serialized, they can be concurrent, even for the same +invocation instance. However, the callbacks for a single rule for a single transaction are +serialized in the order the plugins are invoked in the rule. + +All calls to :func:`TSRemapNewInstance` for a given configuration will be called and completed +before any calls to :func:`TSRemapDoRemap`. + +Cleanup +======= + +When a new :file:`remap.config` is loaded successfully, the prior configuration is cleaned up. For +each call to :func:`TSRemapNewInstance` a corresponding call to :func:`TSRemapDeleteInstance` is +called. The only argument is the invocation instance handle, originally provided by the plugin to +:func:`TSRemapNewInstance`. This is expected to suffice for the plugin to clean up any rule specific +data. + +As part of the old configuration cleanup :func:`TSRemapConfigReload` is called on the plugins in the +old configuration before any calls to :func:`TSRemapDeleteInstance`. This is an optional entry +point. + +.. note:: + + This is called per *plugin*, not per invocation of the plugin in :file:`remap.config`, and only + called if the plugin was called at least once with :func:`TSRemapNewInstance` for that + configuration. + +.. note:: + + There is no explicit indication or connection between the call to :func:`TSRemapConfigReload` and + the "old" (existing) configuration. It is guaranteeed that :func:`TSRemapConfigReload` will be + called on all the plugins before any :func:`TSRemapDeleteInstance` and these calls will be + serial. Similarly, :func:`TSRemapConfigReload` will be called serially after all calls to + :func:`TSRemapNewInstance` for a given configuration. + +.. note:: + + The old configuration, if any, is still active during the call to :func:`TSRemapConfigReload` and + therefore calls to :func:`TSRemapDoRemap` may occur concurrently with that function. + +The intention of :func:`TSRemapConfigReload` is to provide for temporary data structures used only +during configuration loading. These can be created as needed when an invocation instance is loaded +and used in subsequent invocation instance loading, then cleaned up in :func:`TSRemapConfigReload`. + +If no rule uses a plugin, it may be unloaded. In that case :func:`TSRemapDone` is called. This is +an optional entry point, a plugin is not required to provide it. It is called once per plugin, not +per plugin invocation. From a8bcd1c58cdf70e1fb810738a3ea76850e79baa0 Mon Sep 17 00:00:00 2001 From: Gancho Tenev Date: Tue, 3 Sep 2019 13:19:40 -0700 Subject: [PATCH 052/718] Rearrange config reload notifications Renamed `TSRemapConfigReload` to `TSRemapPreConfigReload` to notify all already loaded plugins that a configuration (re)load is about to start. Added new `TSRemapPostConfigReload(TSReturnCode)` to notify the plugins that the configuration (re)load is done and provide status of its success or failure. (cherry picked from commit 70de21d9c72997564ee9ae549cac5407e0f48a98) --- build/plugins.mk | 2 +- .../api/functions/TSRemap.en.rst | 14 ++- .../plugins/remap-plugins.en.rst | 79 +++++++----- include/ts/remap.h | 22 +++- proxy/ReverseProxy.cc | 2 +- proxy/http/remap/Makefile.am | 2 +- proxy/http/remap/PluginDso.h | 10 +- proxy/http/remap/PluginFactory.cc | 75 +++++++---- proxy/http/remap/PluginFactory.h | 6 +- proxy/http/remap/RemapConfig.cc | 15 ++- proxy/http/remap/RemapPluginInfo.cc | 37 ++++-- proxy/http/remap/RemapPluginInfo.h | 27 ++-- .../remap/unit-tests/plugin_testing_calls.cc | 11 +- .../remap/unit-tests/plugin_testing_common.h | 28 +++-- proxy/http/remap/unit-tests/test_PluginDso.cc | 6 +- .../remap/unit-tests/test_PluginFactory.cc | 119 ++++++++++++++---- .../http/remap/unit-tests/test_RemapPlugin.cc | 9 +- 17 files changed, 320 insertions(+), 144 deletions(-) diff --git a/build/plugins.mk b/build/plugins.mk index 86d0a66a681..4556fc22e2d 100644 --- a/build/plugins.mk +++ b/build/plugins.mk @@ -22,7 +22,7 @@ TS_PLUGIN_LD_FLAGS = \ -module \ -shared \ -avoid-version \ - -export-symbols-regex '^(TSRemapInit|TSRemapDone|TSRemapDoRemap|TSRemapNewInstance|TSRemapDeleteInstance|TSRemapOSResponse|TSPluginInit)$$' + -export-symbols-regex '^(TSRemapInit|TSRemapDone|TSRemapDoRemap|TSRemapNewInstance|TSRemapDeleteInstance|TSRemapOSResponse|TSPluginInit|TSRemapPreConfigReload|TSRemapPostConfigReload)$$' TS_PLUGIN_CPPFLAGS = \ -I$(abs_top_builddir)/proxy/api \ diff --git a/doc/developer-guide/api/functions/TSRemap.en.rst b/doc/developer-guide/api/functions/TSRemap.en.rst index ddd99178a71..bbfc2203a0a 100644 --- a/doc/developer-guide/api/functions/TSRemap.en.rst +++ b/doc/developer-guide/api/functions/TSRemap.en.rst @@ -30,7 +30,8 @@ Synopsis `#include ` .. function:: TSReturnCode TSRemapInit(TSRemapInterface * api_info, char * errbuff, int errbuff_size) -.. function:: void TSRemapConfigReload(void) +.. function:: void TSRemapPreConfigReload(void) +.. function:: void TSRemapPostConfigReload(TSReturnCode reloadStatus) .. function:: void TSRemapDone(void) .. function:: TSRemapStatus TSRemapDoRemap(void * ih, TSHttpTxn rh, TSRemapRequestInfo * rri) .. function:: TSReturnCode TSRemapNewInstance(int argc, char * argv[], void ** ih, char * errbuff, int errbuff_size) @@ -65,9 +66,14 @@ any data or continuations associated with that instance. entry point. In this function, the remap plugin may examine and modify the HTTP transaction. -:func:`TSRemapConfigReload` is called once for every remap plugin immediately after a new -configuration is successfully loaded and immediately before the new remap configuration becomes -active. This is an optional entry point, which takes no arguments and has no return value. +:func:`TSRemapPreConfigReload` is called *before* the parsing of a new remap configuration starts +to notify plugins of the coming configuration reload. It is called on all already loaded plugins, +invoked by current and all previous still used configurations. This is an optional entry point. + +:func:`TSRemapPostConfigReload` is called to indicate the end of the the new remap configuration +load. It is called on the newly and previously loaded plugins, invoked by the new, current and +previous still used configurations. It also indicates if the configuration reload was successful +by passing :macro:`TS_SUCCESS` or :macro:`TS_ERROR`. This is an optional entry point. Generally speaking, calls to these functions are mutually exclusive. The exception is for functions which take an HTTP transaction as a parameter. Calls to these diff --git a/doc/developer-guide/plugins/remap-plugins.en.rst b/doc/developer-guide/plugins/remap-plugins.en.rst index 7b691c6e77a..ead70b21724 100644 --- a/doc/developer-guide/plugins/remap-plugins.en.rst +++ b/doc/developer-guide/plugins/remap-plugins.en.rst @@ -80,12 +80,46 @@ multiple times for the rule, once for each invocation. Only the value store in : available when the rule is actually matched. In particular the plugin arguments will not be available. -Calls to :func:`TSRemapNewInstance` are serialized. +Calls to :func:`TSRemapNewInstance` are serialized. All calls to :func:`TSRemapNewInstance` +for a given configuration will be called and completed before any calls to :func:`TSRemapDoRemap`. If there is an error then the callback should return :macro:`TS_ERROR` and fill in the :arg:`errbuff` with a C-string describing the error. Otherwise the function must return :macro:`TS_SUCCESS`. + +Configuration reload notifications +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:func:`TSRemapPreConfigReload` is called *before* the parsing of a new remap configuration starts +to notify plugins of the coming configuration reload. It is called on all already loaded plugins, +invoked by current and all previous still used configurations. This is an optional entry point. + +:func:`TSRemapPostConfigReload` is called to indicate the end of the the new remap configuration +load. It is called on the newly and previously loaded plugins, invoked by the new, current and +previous still used configurations. It also indicates if the configuration reload was successful +by passing :macro:`TS_SUCCESS` or :macro:`TS_ERROR`. This is an optional entry point. + +These calls are called per *plugin*, not per invocation of the plugin in :file:`remap.config` +and only will be called if the plugin was called at least once with :func:`TSRemapNewInstance` +for any configuration and at least one configuration using it is still loaded. + +:func:`TSRemapPreConfigReload` will be called serially for all loaded plugins +before any call to :func:`TSRemapNewInstance` during parsing of the new configuration. + +:func:`TSRemapPostConfigReload` will be called serially for all plugins after +all calls to :func:`TSRemapNewInstance` during parsing of the new configuration. + +The intention of these callbacks can be demonstrated with the following use-case. +A plugin could use :func:`TSRemapPreConfigReload` as a signal to drop (or allocate) temporary +per plugin data structures. These structures can be created (or updated) as needed +when a plugin invocation instance is loaded (:func:`TSRemapNewInstance` is called). +Then it could be used in subsequent invocation instances loading. After the configuration +reload is done :func:`TSRemapPostConfigReload` could be used to confirm +the data structures update if :macro:`TS_SUCCESS` is passed or recover / clean-up +after a failed reload attempt if :macro:`TS_ERROR` is passed. + + Runtime ======= @@ -104,8 +138,13 @@ Calls to :func:`TSRemapDoRemap` are not serialized, they can be concurrent, even invocation instance. However, the callbacks for a single rule for a single transaction are serialized in the order the plugins are invoked in the rule. -All calls to :func:`TSRemapNewInstance` for a given configuration will be called and completed -before any calls to :func:`TSRemapDoRemap`. +No calls to :func:`TSRemapDoRemap` will occur before :func:`TSRemapPostConfigReload` for +all plugin instances invoked by the new configuration. + +The old configurations, if any, are still active during the calls to :func:`TSRemapPreConfigReload` +and :func:`TSRemapPreConfigReload` and therefore calls to :func:`TSRemapDoRemap` may occur +concurrently with those functions. + Cleanup ======= @@ -114,35 +153,9 @@ When a new :file:`remap.config` is loaded successfully, the prior configuration each call to :func:`TSRemapNewInstance` a corresponding call to :func:`TSRemapDeleteInstance` is called. The only argument is the invocation instance handle, originally provided by the plugin to :func:`TSRemapNewInstance`. This is expected to suffice for the plugin to clean up any rule specific -data. - -As part of the old configuration cleanup :func:`TSRemapConfigReload` is called on the plugins in the -old configuration before any calls to :func:`TSRemapDeleteInstance`. This is an optional entry -point. - -.. note:: - - This is called per *plugin*, not per invocation of the plugin in :file:`remap.config`, and only - called if the plugin was called at least once with :func:`TSRemapNewInstance` for that - configuration. - -.. note:: - - There is no explicit indication or connection between the call to :func:`TSRemapConfigReload` and - the "old" (existing) configuration. It is guaranteeed that :func:`TSRemapConfigReload` will be - called on all the plugins before any :func:`TSRemapDeleteInstance` and these calls will be - serial. Similarly, :func:`TSRemapConfigReload` will be called serially after all calls to - :func:`TSRemapNewInstance` for a given configuration. - -.. note:: - - The old configuration, if any, is still active during the call to :func:`TSRemapConfigReload` and - therefore calls to :func:`TSRemapDoRemap` may occur concurrently with that function. - -The intention of :func:`TSRemapConfigReload` is to provide for temporary data structures used only -during configuration loading. These can be created as needed when an invocation instance is loaded -and used in subsequent invocation instance loading, then cleaned up in :func:`TSRemapConfigReload`. +data. Calls to :func:`TSRemapDeleteInstance` will be serial for all plugin invocations in a +remap configuration. If no rule uses a plugin, it may be unloaded. In that case :func:`TSRemapDone` is called. This is -an optional entry point, a plugin is not required to provide it. It is called once per plugin, not -per plugin invocation. +an optional entry point, a plugin is not required to provide it. It corresponds to :func:`TSRemapInit`. +It is called once per plugin, not per plugin invocation. diff --git a/include/ts/remap.h b/include/ts/remap.h index cc263fdd4ea..dd7be385c9d 100644 --- a/include/ts/remap.h +++ b/include/ts/remap.h @@ -88,13 +88,27 @@ typedef enum { */ tsapi TSReturnCode TSRemapInit(TSRemapInterface *api_info, char *errbuf, int errbuf_size); -/* This gets called every time remap.config is reloaded. This is complementary - to TSRemapInit() which gets called when the plugin is first loaded. You can - not fail, or cause reload to stop here, it's merely a notification. +/* This gets called every time before remap.config is reloaded. This is complementary + to TSRemapInit() which gets called when the plugin is first loaded. + It is guaranteed to be called before TSRemapInit() and TSRemapNewInstance(). + It cannot fail, or cause reload to stop here, it's merely a notification. Optional function. + Params: none Return: none */ -tsapi void TSRemapConfigReload(void); +tsapi void TSRemapPreConfigReload(void); + +/* This gets called every time afterremap.config is reloaded. This is complementary + to TSRemapInit() which gets called when the plugin is first loaded. + It is guaranteed to be called after TSRemapInit() and TSRemapNewInstance(). + It cannot fail, or cause reload to stop here, it's merely a notification that + the (re)load is done and provide a status of its success or failure.. + Optional function. + Params: reloadStatus - TS_SUCCESS - (re)load was successful, + TS_ERROR - (re)load failed. + Return: none +*/ +tsapi void TSRemapPostConfigReload(TSReturnCode reloadStatus); /* Remap new request Mandatory interface function. diff --git a/proxy/ReverseProxy.cc b/proxy/ReverseProxy.cc index d7d3ae09e45..2f5de1a917b 100644 --- a/proxy/ReverseProxy.cc +++ b/proxy/ReverseProxy.cc @@ -151,7 +151,7 @@ reloadUrlRewrite() ink_assert(oldTable != nullptr); // Release the old one - oldTable->pluginFactory.indicateReload(); + oldTable->pluginFactory.deactivate(); oldTable->release(); Debug("url_rewrite", "%s", msg); diff --git a/proxy/http/remap/Makefile.am b/proxy/http/remap/Makefile.am index ad705d3d26c..8973d1b7710 100644 --- a/proxy/http/remap/Makefile.am +++ b/proxy/http/remap/Makefile.am @@ -103,7 +103,7 @@ DSO_LDFLAGS = \ -module \ -shared \ -avoid-version \ - -export-symbols-regex '^(TSRemapInit|TSRemapDone|TSRemapDoRemap|TSRemapNewInstance|TSRemapDeleteInstance|TSRemapOSResponse|TSRemapConfigReload|TSPluginInit|pluginDsoVersionTest|getPluginDebugObjectTest)$$' + -export-symbols-regex '^(TSRemapInit|TSRemapDone|TSRemapDoRemap|TSRemapNewInstance|TSRemapDeleteInstance|TSRemapOSResponse|TSRemapPreConfigReload|TSRemapPostConfigReload|TSPluginInit|pluginDsoVersionTest|getPluginDebugObjectTest)$$' # Build plugins for unit testing the plugin (re)load. pkglib_LTLIBRARIES = \ diff --git a/proxy/http/remap/PluginDso.h b/proxy/http/remap/PluginDso.h index 4554c6b8756..23a84b5b9a2 100644 --- a/proxy/http/remap/PluginDso.h +++ b/proxy/http/remap/PluginDso.h @@ -33,6 +33,7 @@ #include #include +#include "ts/apidefs.h" #include "tscore/ts_file.h" namespace fs = ts::file; @@ -73,10 +74,11 @@ class PluginDso : public PluginThreadContext using Linkage = ts::IntrusiveLinkage; using PluginList = ts::IntrusiveDList; - /* Methods to be called when processing a list of plugins, to overloaded by the remap or the global plugins correspondingly */ - virtual void indicateReload() = 0; - virtual bool init(std::string &error) = 0; - virtual void done() = 0; + /* Methods to be called when processing a list of plugins, to be overloaded by the remap or the global plugins correspondingly */ + virtual void indicatePreReload() = 0; + virtual void indicatePostReload(TSReturnCode reloadStatus) = 0; + virtual bool init(std::string &error) = 0; + virtual void done() = 0; void acquire(); void release(); diff --git a/proxy/http/remap/PluginFactory.cc b/proxy/http/remap/PluginFactory.cc index c6b1c8a7f31..8b045cc12b3 100644 --- a/proxy/http/remap/PluginFactory.cc +++ b/proxy/http/remap/PluginFactory.cc @@ -35,28 +35,34 @@ RemapPluginInst::RemapPluginInst(RemapPluginInfo &plugin) : _plugin(plugin) { _plugin.acquire(); - _plugin.incInstanceCount(); } RemapPluginInst::~RemapPluginInst() { - _plugin.decInstanceCount(); _plugin.release(); } -bool -RemapPluginInst::init(int argc, char **argv, std::string &error) +RemapPluginInst * +RemapPluginInst::init(RemapPluginInfo *plugin, int argc, char **argv, std::string &error) { - bool result = false; - result = _plugin.initInstance(argc, argv, &_instance, error); - - return result; + RemapPluginInst *inst = new RemapPluginInst(*plugin); + if (plugin->initInstance(argc, argv, &(inst->_instance), error)) { + plugin->incInstanceCount(); + return inst; + } + delete inst; + return nullptr; } void RemapPluginInst::done() { + _plugin.decInstanceCount(); _plugin.doneInstance(_instance); + + if (0 == _plugin.instanceCount()) { + _plugin.done(); + } } TSRemapStatus @@ -163,9 +169,10 @@ PluginFactory::getRemapPlugin(const fs::path &configPath, int argc, char **argv, _list.append(plugin); if (plugin->init(error)) { - inst = new RemapPluginInst(*plugin); - inst->init(argc, argv, error); - _instList.append(inst); + inst = RemapPluginInst::init(plugin, argc, argv, error); + if (nullptr != inst) { + _instList.append(inst); + } } if (_preventiveCleaning) { @@ -177,9 +184,10 @@ PluginFactory::getRemapPlugin(const fs::path &configPath, int argc, char **argv, } } else { Debug(_tag, "plugin '%s' has already been loaded", configPath.c_str()); - inst = new RemapPluginInst(*plugin); - inst->init(argc, argv, error); - _instList.append(inst); + inst = RemapPluginInst::init(plugin, argc, argv, error); + if (nullptr != inst) { + _instList.append(inst); + } } return inst; @@ -236,25 +244,44 @@ PluginFactory::findByEffectivePath(const fs::path &path) } /** - * @brief Tell all plugins (that so wish) that remap.config is being reloaded + * @brief Tell all plugins instantiated by this factory that the configuration + * they are using is no longer the active one. * * This method would be useful only in case configs are reloaded independently from * factory/plugins instantiation and initialization. */ void -PluginFactory::indicateReload() +PluginFactory::deactivate() { - Debug(_tag, "indicated config reload to factory '%s'", getUuid()); + Debug(_tag, "deactivate configuration used by factory '%s'", getUuid()); _instList.apply([](RemapPluginInst &pluginInst) -> void { pluginInst.done(); }); +} - _list.apply([](PluginDso &plugin) -> void { - if (1 == plugin.instanceCount()) { - plugin.done(); - } else { - plugin.indicateReload(); - } - }); +/** + * @brief Tell all plugins (that so wish) that remap.config is going to be reloaded + */ +void +PluginFactory::indicatePreReload() +{ + Debug(_tag, "indicated config is going to be reloaded by factory '%s' to %zu plugin%s", getUuid(), _list.count(), + _list.count() != 1 ? "s" : ""); + + _list.apply([](PluginDso &plugin) -> void { plugin.indicatePreReload(); }); +} + +/** + * @brief Tell all plugins (that so wish) that remap.config is done reloading + */ +void +PluginFactory::indicatePostReload(TSReturnCode reloadStatus) +{ + Debug(_tag, "indicated config is done reloading by factory '%s' to %zu plugin%s", getUuid(), _list.count(), + _list.count() != 1 ? "s" : ""); + + for (auto it = _list.begin(); _list.end() != it; it++) { + it->indicatePostReload(reloadStatus); + } } void diff --git a/proxy/http/remap/PluginFactory.h b/proxy/http/remap/PluginFactory.h index 1cb0661903e..db722bd6372 100644 --- a/proxy/http/remap/PluginFactory.h +++ b/proxy/http/remap/PluginFactory.h @@ -47,7 +47,7 @@ class RemapPluginInst ~RemapPluginInst(); /* Used by the PluginFactory */ - bool init(int argc, char **argv, std::string &error); + static RemapPluginInst *init(RemapPluginInfo *plugin, int argc, char **argv, std::string &error); void done(); /* Used by the traffic server core while processing requests */ @@ -100,7 +100,9 @@ class PluginFactory virtual const char *getUuid(); void clean(std::string &error); - void indicateReload(); + void deactivate(); + void indicatePreReload(); + void indicatePostReload(TSReturnCode reloadStatus); protected: PluginDso *findByEffectivePath(const fs::path &path); diff --git a/proxy/http/remap/RemapConfig.cc b/proxy/http/remap/RemapConfig.cc index e231c098b40..5774b18c6c4 100644 --- a/proxy/http/remap/RemapConfig.cc +++ b/proxy/http/remap/RemapConfig.cc @@ -1320,9 +1320,16 @@ remap_parse_config(const char *path, UrlRewrite *rewrite) { BUILD_TABLE_INFO bti; - // If this happens to be a config reload, the list of loaded remap plugins is non-empty, and we - // can signal all these plugins that a reload has begun. - rewrite->pluginFactory.indicateReload(); + /* If this happens to be a config reload, the list of loaded remap plugins is non-empty, and we + * can signal all these plugins that a reload has begun. */ + rewrite->pluginFactory.indicatePreReload(); + bti.rewrite = rewrite; - return remap_parse_config_bti(path, &bti); + bool status = remap_parse_config_bti(path, &bti); + + /* Now after we parsed the configuration and (re)loaded plugins and plugin instances + * accordingly notify all plugins that we are done */ + rewrite->pluginFactory.indicatePostReload(status ? TS_SUCCESS : TS_ERROR); + + return status; } diff --git a/proxy/http/remap/RemapPluginInfo.cc b/proxy/http/remap/RemapPluginInfo.cc index 8a1c00ed134..a98c3eeb29e 100644 --- a/proxy/http/remap/RemapPluginInfo.cc +++ b/proxy/http/remap/RemapPluginInfo.cc @@ -52,7 +52,9 @@ RemapPluginInfo::getFunctionSymbol(const char *symbol) { std::string error; /* ignore the error, return nullptr if symbol not defined */ void *address = nullptr; - getSymbol(symbol, address, error); + if (getSymbol(symbol, address, error)) { + Debug(_tag, "plugin '%s' found symbol '%s'", _configPath.c_str(), symbol); + } return reinterpret_cast(address); } @@ -81,13 +83,14 @@ RemapPluginInfo::load(std::string &error) return false; } - init_cb = getFunctionSymbol(TSREMAP_FUNCNAME_INIT); - config_reload_cb = getFunctionSymbol(TSREMAP_FUNCNAME_CONFIG_RELOAD); - done_cb = getFunctionSymbol(TSREMAP_FUNCNAME_DONE); - new_instance_cb = getFunctionSymbol(TSREMAP_FUNCNAME_NEW_INSTANCE); - delete_instance_cb = getFunctionSymbol(TSREMAP_FUNCNAME_DELETE_INSTANCE); - do_remap_cb = getFunctionSymbol(TSREMAP_FUNCNAME_DO_REMAP); - os_response_cb = getFunctionSymbol(TSREMAP_FUNCNAME_OS_RESPONSE); + init_cb = getFunctionSymbol(TSREMAP_FUNCNAME_INIT); + pre_config_reload_cb = getFunctionSymbol(TSREMAP_FUNCNAME_PRE_CONFIG_RELOAD); + post_config_reload_cb = getFunctionSymbol(TSREMAP_FUNCNAME_POST_CONFIG_RELOAD); + done_cb = getFunctionSymbol(TSREMAP_FUNCNAME_DONE); + new_instance_cb = getFunctionSymbol(TSREMAP_FUNCNAME_NEW_INSTANCE); + delete_instance_cb = getFunctionSymbol(TSREMAP_FUNCNAME_DELETE_INSTANCE); + do_remap_cb = getFunctionSymbol(TSREMAP_FUNCNAME_DO_REMAP); + os_response_cb = getFunctionSymbol(TSREMAP_FUNCNAME_OS_RESPONSE); /* Validate if the callback TSREMAP functions are specified correctly in the plugin. */ bool valid = true; @@ -243,12 +246,24 @@ RemapPluginInfo::osResponse(void *ih, TSHttpTxn rh, int os_response_type) RemapPluginInfo::~RemapPluginInfo() {} void -RemapPluginInfo::indicateReload() +RemapPluginInfo::indicatePreReload() +{ + setPluginContext(); + + if (pre_config_reload_cb) { + pre_config_reload_cb(); + } + + resetPluginContext(); +} + +void +RemapPluginInfo::indicatePostReload(TSReturnCode reloadStatus) { setPluginContext(); - if (config_reload_cb) { - config_reload_cb(); + if (post_config_reload_cb) { + post_config_reload_cb(reloadStatus); } resetPluginContext(); diff --git a/proxy/http/remap/RemapPluginInfo.h b/proxy/http/remap/RemapPluginInfo.h index cc5941db64a..731196a26de 100644 --- a/proxy/http/remap/RemapPluginInfo.h +++ b/proxy/http/remap/RemapPluginInfo.h @@ -36,13 +36,14 @@ class url_mapping; extern thread_local PluginThreadContext *pluginThreadContext; -static constexpr const char *const TSREMAP_FUNCNAME_INIT = "TSRemapInit"; -static constexpr const char *const TSREMAP_FUNCNAME_CONFIG_RELOAD = "TSRemapConfigReload"; -static constexpr const char *const TSREMAP_FUNCNAME_DONE = "TSRemapDone"; -static constexpr const char *const TSREMAP_FUNCNAME_NEW_INSTANCE = "TSRemapNewInstance"; -static constexpr const char *const TSREMAP_FUNCNAME_DELETE_INSTANCE = "TSRemapDeleteInstance"; -static constexpr const char *const TSREMAP_FUNCNAME_DO_REMAP = "TSRemapDoRemap"; -static constexpr const char *const TSREMAP_FUNCNAME_OS_RESPONSE = "TSRemapOSResponse"; +static constexpr const char *const TSREMAP_FUNCNAME_INIT = "TSRemapInit"; +static constexpr const char *const TSREMAP_FUNCNAME_PRE_CONFIG_RELOAD = "TSRemapPreConfigReload"; +static constexpr const char *const TSREMAP_FUNCNAME_POST_CONFIG_RELOAD = "TSRemapPostConfigReload"; +static constexpr const char *const TSREMAP_FUNCNAME_DONE = "TSRemapDone"; +static constexpr const char *const TSREMAP_FUNCNAME_NEW_INSTANCE = "TSRemapNewInstance"; +static constexpr const char *const TSREMAP_FUNCNAME_DELETE_INSTANCE = "TSRemapDeleteInstance"; +static constexpr const char *const TSREMAP_FUNCNAME_DO_REMAP = "TSRemapDoRemap"; +static constexpr const char *const TSREMAP_FUNCNAME_OS_RESPONSE = "TSRemapOSResponse"; /** * Holds information for a remap plugin, remap specific callback entry points for plugin init/done and instance init/done, do_remap, @@ -53,8 +54,10 @@ class RemapPluginInfo : public PluginDso public: /// Initialization function, called on library load. using Init_F = TSReturnCode(TSRemapInterface *api_info, char *errbuf, int errbuf_size); - /// Reload function, called to inform the plugin of a configuration reload. - using Reload_F = void(); + /// Reload function, called to inform the plugin that configuration is going to be reloaded. + using PreReload_F = void(); + /// Reload function, called to inform the plugin that configuration is done reloading. + using PostReload_F = void(TSReturnCode); /// Called when remapping for a transaction has finished. using Done_F = void(); /// Create an rule instance. @@ -68,7 +71,8 @@ class RemapPluginInfo : public PluginDso void *dl_handle = nullptr; /* "handle" for the dynamic library */ Init_F *init_cb = nullptr; - Reload_F *config_reload_cb = nullptr; + PreReload_F *pre_config_reload_cb = nullptr; + PostReload_F *post_config_reload_cb = nullptr; Done_F *done_cb = nullptr; New_Instance_F *new_instance_cb = nullptr; Delete_Instance_F *delete_instance_cb = nullptr; @@ -94,7 +98,8 @@ class RemapPluginInfo : public PluginDso void osResponse(void *ih, TSHttpTxn rh, int os_response_type); /* Used by traffic server core to indicate configuration reload */ - virtual void indicateReload(); + virtual void indicatePreReload(); + virtual void indicatePostReload(TSReturnCode reloadStatus); protected: /* Utility to be used only with unit testing */ diff --git a/proxy/http/remap/unit-tests/plugin_testing_calls.cc b/proxy/http/remap/unit-tests/plugin_testing_calls.cc index 89c8df2c749..1d57da3426b 100644 --- a/proxy/http/remap/unit-tests/plugin_testing_calls.cc +++ b/proxy/http/remap/unit-tests/plugin_testing_calls.cc @@ -103,9 +103,16 @@ TSRemapOSResponse(void *ih, TSHttpTxn rh, int os_response_type) } void -TSRemapConfigReload(void) +TSRemapPreConfigReload(void) { - debugObject.reloadConfigCalled++; + debugObject.preReloadConfigCalled++; +} + +void +TSRemapPostConfigReload(TSReturnCode reloadStatus) +{ + debugObject.postReloadConfigCalled++; + debugObject.postReloadConfigSuccess = (TS_SUCCESS == reloadStatus); } /* The folowing functions are meant for unit testing */ diff --git a/proxy/http/remap/unit-tests/plugin_testing_common.h b/proxy/http/remap/unit-tests/plugin_testing_common.h index 66a8dd686ee..3662d0c5ec6 100644 --- a/proxy/http/remap/unit-tests/plugin_testing_common.h +++ b/proxy/http/remap/unit-tests/plugin_testing_common.h @@ -51,17 +51,19 @@ class PluginDebugObject void clear() { - contextInit = nullptr; - contextInitInstance = nullptr; - doRemapCalled = 0; - initCalled = 0; - doneCalled = 0; - initInstanceCalled = 0; - deleteInstanceCalled = 0; - reloadConfigCalled = 0; - ih = nullptr; - argc = 0; - argv = nullptr; + contextInit = nullptr; + contextInitInstance = nullptr; + doRemapCalled = 0; + initCalled = 0; + doneCalled = 0; + initInstanceCalled = 0; + deleteInstanceCalled = 0; + preReloadConfigCalled = 0; + postReloadConfigCalled = 0; + postReloadConfigSuccess = 0; + ih = nullptr; + argc = 0; + argv = nullptr; } /* Input fields used to set the test behavior of the plugin call-backs */ @@ -76,7 +78,9 @@ class PluginDebugObject int doneCalled = 0; /* mark if done was called */ int initInstanceCalled = 0; /* mark if instance init was called */ int deleteInstanceCalled = 0; /* mark if delete instance was called */ - int reloadConfigCalled = 0; /* mark if reload config was called */ + int preReloadConfigCalled = 0; /* mark if pre-reload config was called */ + int postReloadConfigCalled = 0; /* mark if post-reload config was called */ + bool postReloadConfigSuccess = 0; /* mark if plugin reload status is passed correctly */ void *ih = nullptr; /* instance handler */ int argc = 0; /* number of plugin instance parameters received by the plugin */ char **argv = nullptr; /* plugin instance parameters received by the plugin */ diff --git a/proxy/http/remap/unit-tests/test_PluginDso.cc b/proxy/http/remap/unit-tests/test_PluginDso.cc index 092261b76fd..1635a65493f 100644 --- a/proxy/http/remap/unit-tests/test_PluginDso.cc +++ b/proxy/http/remap/unit-tests/test_PluginDso.cc @@ -69,7 +69,11 @@ class PluginDsoUnitTest : public PluginDso } virtual void - indicateReload() + indicatePreReload() + { + } + virtual void + indicatePostReload(TSReturnCode reloadStatus) { } virtual bool diff --git a/proxy/http/remap/unit-tests/test_PluginFactory.cc b/proxy/http/remap/unit-tests/test_PluginFactory.cc index 9c2d81942f2..1c75bbe37e7 100644 --- a/proxy/http/remap/unit-tests/test_PluginFactory.cc +++ b/proxy/http/remap/unit-tests/test_PluginFactory.cc @@ -554,7 +554,7 @@ SCENARIO("notifying plugins of config reload", "[plugin][core]") GIVEN("simple configuration with 1 plugin and 1 factory") { - WHEN("indicating config reload") + WHEN("(1) signal pre-new-config-load, (2) signal post-new-config-load, (3) old-config deactivate") { /* Simulate configuration without plugins - an unused factory */ setupConfigPathTest(configName1, buildPath, uuid_t1, effectivePath1, runtimePath1, 1556825556); @@ -566,17 +566,43 @@ SCENARIO("notifying plugins of config reload", "[plugin][core]") /* Prapare the debug object */ PluginDebugObject *debugObject = getDebugObject(plugin1->_plugin); - debugObject->clear(); - THEN("expect 'done' methods to be called for plugin and the instance but not the 'reload config' methods") + THEN("expect pre-, post- and done/delete_instance to be called accordingly ") { - /* Simulate reloading the config */ - factory1->indicateReload(); - - /* was "done" method called? */ - CHECK(1 == debugObject->doneCalled); + /* Signal before loading the config */ + debugObject->clear(); + + factory1->indicatePreReload(); + CHECK(0 == debugObject->deleteInstanceCalled); + CHECK(0 == debugObject->doneCalled); + CHECK(1 == debugObject->preReloadConfigCalled); + + /* ... parse the new remap config ... */ + + /* Assume (re)load was done OK and test */ + debugObject->clear(); + factory1->indicatePostReload(TS_SUCCESS); + CHECK(0 == debugObject->deleteInstanceCalled); + CHECK(0 == debugObject->doneCalled); + CHECK(1 == debugObject->postReloadConfigCalled); + CHECK(true == debugObject->postReloadConfigSuccess); + + /* Assume (re)load failed and test */ + debugObject->clear(); + factory1->indicatePostReload(TS_ERROR); + CHECK(0 == debugObject->deleteInstanceCalled); + CHECK(0 == debugObject->doneCalled); + CHECK(1 == debugObject->postReloadConfigCalled); + CHECK(false == debugObject->postReloadConfigSuccess); + + /* ... swap the new and the old config ... */ + + /* Signal de-activation of the old config */ + debugObject->clear(); + factory1->deactivate(); CHECK(1 == debugObject->deleteInstanceCalled); - CHECK(0 == debugObject->reloadConfigCalled); + CHECK(1 == debugObject->doneCalled); + CHECK(0 == debugObject->preReloadConfigCalled); } teardownConfigPathTest(factory1); @@ -585,7 +611,7 @@ SCENARIO("notifying plugins of config reload", "[plugin][core]") GIVEN("configuration with 2 plugins loaded by 1 factory") { - WHEN("indicating config reload") + WHEN("(1) signal pre-new-config-load, (2) signal post-new-config-load, (3) old-config deactivate") { /* Simulate configuration without plugins - an unused factory */ setupConfigPathTest(configName1, buildPath, uuid_t1, effectivePath1, runtimePath1, 1556825556); @@ -601,21 +627,60 @@ SCENARIO("notifying plugins of config reload", "[plugin][core]") /* Prapare the debug objects */ PluginDebugObject *debugObject1 = getDebugObject(plugin1->_plugin); PluginDebugObject *debugObject2 = getDebugObject(plugin2->_plugin); - debugObject1->clear(); - debugObject2->clear(); - THEN("expect 'done' methods to be called but not the 'reload config' methods") + THEN("expect pre-, post- and done/delete_instance to be called accordingly") { - /* Simulate reloading the config */ - factory1->indicateReload(); + /* Signal before loading the config */ + debugObject1->clear(); + debugObject2->clear(); + factory1->indicatePreReload(); + CHECK(0 == debugObject1->deleteInstanceCalled); + CHECK(0 == debugObject1->doneCalled); + CHECK(1 == debugObject1->preReloadConfigCalled); + CHECK(0 == debugObject2->doneCalled); + CHECK(0 == debugObject2->deleteInstanceCalled); + CHECK(1 == debugObject2->preReloadConfigCalled); - /* Was "done" method called? */ - CHECK(1 == debugObject1->doneCalled); + /* ... parse the new remap config ... */ + + /* Assume (re)load was done OK */ + debugObject1->clear(); + debugObject2->clear(); + factory1->indicatePostReload(TS_SUCCESS); + CHECK(0 == debugObject1->deleteInstanceCalled); + CHECK(0 == debugObject1->doneCalled); + CHECK(1 == debugObject1->postReloadConfigCalled); + CHECK(true == debugObject1->postReloadConfigSuccess); + CHECK(0 == debugObject2->deleteInstanceCalled); + CHECK(0 == debugObject2->doneCalled); + CHECK(1 == debugObject2->postReloadConfigCalled); + CHECK(true == debugObject2->postReloadConfigSuccess); + + /* Assume (re)load failed */ + debugObject1->clear(); + debugObject2->clear(); + factory1->indicatePostReload(TS_ERROR); + CHECK(0 == debugObject1->deleteInstanceCalled); + CHECK(0 == debugObject1->doneCalled); + CHECK(1 == debugObject1->postReloadConfigCalled); + CHECK(false == debugObject1->postReloadConfigSuccess); + CHECK(0 == debugObject2->deleteInstanceCalled); + CHECK(0 == debugObject2->doneCalled); + CHECK(1 == debugObject2->postReloadConfigCalled); + CHECK(false == debugObject2->postReloadConfigSuccess); + + /* ... swap the new and the old config ... */ + + /* Signal de-activation of the old config */ + debugObject1->clear(); + debugObject2->clear(); + factory1->deactivate(); CHECK(1 == debugObject1->deleteInstanceCalled); - CHECK(0 == debugObject1->reloadConfigCalled); - CHECK(1 == debugObject2->doneCalled); + CHECK(1 == debugObject1->doneCalled); + CHECK(0 == debugObject1->preReloadConfigCalled); CHECK(1 == debugObject2->deleteInstanceCalled); - CHECK(0 == debugObject2->reloadConfigCalled); + CHECK(1 == debugObject2->doneCalled); + CHECK(0 == debugObject2->preReloadConfigCalled); } teardownConfigPathTest(factory1); @@ -624,7 +689,7 @@ SCENARIO("notifying plugins of config reload", "[plugin][core]") GIVEN("configuration with 1 plugin loaded by 2 separate factories") { - WHEN("indicating config reload") + WHEN("indicating de-activation of the factories") { /* Simulate configuration without plugins - an unused factory */ setupConfigPathTest(configName1, buildPath, uuid_t1, effectivePath1, runtimePath1, 1556825556); @@ -633,25 +698,25 @@ SCENARIO("notifying plugins of config reload", "[plugin][core]") RemapPluginInst *plugin1 = factory1->getRemapPlugin(configName1, 0, nullptr, error); RemapPluginInst *plugin2 = factory2->getRemapPlugin(configName1, 0, nullptr, error); - /* Prapare the debug objects */ + /* Prepare the debug objects */ PluginDebugObject *debugObject1 = getDebugObject(plugin1->_plugin); PluginDebugObject *debugObject2 = getDebugObject(plugin2->_plugin); - THEN("expect instance 'done' to be always called, but plugin 'done' called only after destroying one factory") + THEN("expect instance 'done' to be always called, but plugin 'done' called only after destroying both factories") { debugObject2->clear(); - factory2->indicateReload(); + factory2->deactivate(); CHECK(0 == debugObject2->doneCalled); CHECK(1 == debugObject2->deleteInstanceCalled); - CHECK(1 == debugObject2->reloadConfigCalled); + CHECK(0 == debugObject2->preReloadConfigCalled); delete factory2; debugObject1->clear(); - factory1->indicateReload(); + factory1->deactivate(); CHECK(1 == debugObject1->doneCalled); CHECK(1 == debugObject1->deleteInstanceCalled); - CHECK(0 == debugObject1->reloadConfigCalled); + CHECK(0 == debugObject1->preReloadConfigCalled); delete factory1; } diff --git a/proxy/http/remap/unit-tests/test_RemapPlugin.cc b/proxy/http/remap/unit-tests/test_RemapPlugin.cc index 1b385cc51da..49be30ff36d 100644 --- a/proxy/http/remap/unit-tests/test_RemapPlugin.cc +++ b/proxy/http/remap/unit-tests/test_RemapPlugin.cc @@ -426,9 +426,14 @@ SCENARIO("config reload", "[plugin][core]") { debugObject->clear(); - plugin->indicateReload(); + plugin->indicatePreReload(); + plugin->indicatePostReload(TS_SUCCESS); - THEN("expect it to run") { CHECK(1 == debugObject->reloadConfigCalled); } + THEN("expect it to run") + { + CHECK(1 == debugObject->preReloadConfigCalled); + CHECK(1 == debugObject->postReloadConfigCalled); + } cleanupSandBox(plugin); } } From 970a9a2fceb9a12d39c757909b234fbf9a87ce90 Mon Sep 17 00:00:00 2001 From: Gancho Tenev Date: Fri, 27 Sep 2019 13:28:22 -0700 Subject: [PATCH 053/718] "Plugin (un)used" post reload notification Most of the plugins is assumed to use per-plugin-instance data-structures when reloading their configs and only a few of them that wish to optimize performance or deal with the complexities of using per-plugin DSO "global" data-structures would use plugin configuration reload notifications like `TSRemapPreConfigReload` and `TSRemapPostConfigReload`. Instead of trying to foresee the needs or the expectations of each use-case, a more "open-ended" and straight-forward design was chosen for the configuration reload notifications. The notifications are broadcasted to all loaded plugins at the moments before and after the reload attempt, regardless of whether a plugin is part of the new configuration or not. During the `TSRemapPostConfigReload` we already decided to notify the plugin if the plugin reload was successful or not so the plugins can recover adequately in case of configuration reload failure. This change adds a signal to show if the particular plugin was part of the new configuration. This will be beneficial for use-cases that expect plugin reload notification not to be called in case they are not part of the new configuration so they can ignore the notification. This change also attempts to clarify related documentation and code comments as well. (cherry picked from commit 78c7c0c0bf2afa87a90da5fa948a55d8ba747dbd) --- .../api/functions/TSRemap.en.rst | 20 ++++- .../plugins/remap-plugins.en.rst | 32 +++++-- include/ts/remap.h | 12 ++- proxy/http/remap/PluginDso.h | 9 +- proxy/http/remap/PluginFactory.cc | 20 ++++- proxy/http/remap/PluginFactory.h | 2 +- proxy/http/remap/RemapConfig.cc | 2 +- proxy/http/remap/RemapPluginInfo.cc | 2 +- proxy/http/remap/RemapPluginInfo.h | 4 +- .../remap/unit-tests/plugin_testing_calls.cc | 4 +- .../remap/unit-tests/plugin_testing_common.h | 52 ++++++------ proxy/http/remap/unit-tests/test_PluginDso.cc | 2 +- .../remap/unit-tests/test_PluginFactory.cc | 85 ++++++++++++++++--- .../http/remap/unit-tests/test_RemapPlugin.cc | 37 +++++++- 14 files changed, 215 insertions(+), 68 deletions(-) diff --git a/doc/developer-guide/api/functions/TSRemap.en.rst b/doc/developer-guide/api/functions/TSRemap.en.rst index bbfc2203a0a..0e8ad4eb8e6 100644 --- a/doc/developer-guide/api/functions/TSRemap.en.rst +++ b/doc/developer-guide/api/functions/TSRemap.en.rst @@ -72,8 +72,10 @@ invoked by current and all previous still used configurations. This is an option :func:`TSRemapPostConfigReload` is called to indicate the end of the the new remap configuration load. It is called on the newly and previously loaded plugins, invoked by the new, current and -previous still used configurations. It also indicates if the configuration reload was successful -by passing :macro:`TS_SUCCESS` or :macro:`TS_ERROR`. This is an optional entry point. +previous still used configurations. It also indicates wheather the configuration reload was successful +by passing :macro:`TSREMAP_CONFIG_RELOAD_FAILURE` in case of failure and to notify the plugins if they +are going to be part of the new configuration by passing :macro:`TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED` +or :macro:`TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED`. This is an optional entry point. Generally speaking, calls to these functions are mutually exclusive. The exception is for functions which take an HTTP transaction as a parameter. Calls to these @@ -111,6 +113,20 @@ Types The remapping attempt in general failed and the transaction should fail with an error return to the user agent. +.. type:: TSRemapReloadStatus + + .. macro:: TSREMAP_CONFIG_RELOAD_FAILURE + + Notify the plugin that configuration parsing failed. + + .. macro:: TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED + + Configuration parsing succeeded and plugin was used by the new configuration. + + .. macro:: TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED + + Configuration parsing succeeded but plugin was NOT used by the new configuration. + Return Values ============= diff --git a/doc/developer-guide/plugins/remap-plugins.en.rst b/doc/developer-guide/plugins/remap-plugins.en.rst index ead70b21724..d43616955f1 100644 --- a/doc/developer-guide/plugins/remap-plugins.en.rst +++ b/doc/developer-guide/plugins/remap-plugins.en.rst @@ -80,8 +80,9 @@ multiple times for the rule, once for each invocation. Only the value store in : available when the rule is actually matched. In particular the plugin arguments will not be available. -Calls to :func:`TSRemapNewInstance` are serialized. All calls to :func:`TSRemapNewInstance` -for a given configuration will be called and completed before any calls to :func:`TSRemapDoRemap`. +Calls to :func:`TSRemapNewInstance` are guaranteed to be serialized. All calls to +:func:`TSRemapNewInstance` for a given new configuration are guaranteed to be called and +completed before any calls to :func:`TSRemapDoRemap`. If there is an error then the callback should return :macro:`TS_ERROR` and fill in the :arg:`errbuff` with a C-string describing the error. Otherwise the function must return @@ -91,18 +92,30 @@ If there is an error then the callback should return :macro:`TS_ERROR` and fill Configuration reload notifications ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Most of the plugins is assumed to use per-plugin-instance data-structures when reloading their +configs and only a few of them that wish to optimize performance or deal with the complexities +of using a per-plugin DSO "global" data-structures would use pluging configuration reload +notifications like :func:`TSRemapPreConfigReload` and :func:`TSRemapPostConfigReload`. + +Instead of trying to foresee the needs or the expectations of each use-case, a more "open-ended" +and straight-forward design was chosen for the configuration reload notifications. +The notifications are broadcasted to all loaded plugins at the moments before and after +the reload attempt, regardless of whether a plugin is part of the new configuration or not. + :func:`TSRemapPreConfigReload` is called *before* the parsing of a new remap configuration starts to notify plugins of the coming configuration reload. It is called on all already loaded plugins, invoked by current and all previous still used configurations. This is an optional entry point. :func:`TSRemapPostConfigReload` is called to indicate the end of the the new remap configuration load. It is called on the newly and previously loaded plugins, invoked by the new, current and -previous still used configurations. It also indicates if the configuration reload was successful -by passing :macro:`TS_SUCCESS` or :macro:`TS_ERROR`. This is an optional entry point. +previous still used configurations. It also indicates wheather the configuration reload was successful +by passing :macro:`TSREMAP_CONFIG_RELOAD_FAILURE` in case of failure and to notify the plugins if they +are going to be part of the new configuration by passing :macro:`TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED` +or :macro:`TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED`. This is an optional entry point. These calls are called per *plugin*, not per invocation of the plugin in :file:`remap.config` -and only will be called if the plugin was called at least once with :func:`TSRemapNewInstance` -for any configuration and at least one configuration using it is still loaded. +and only will be called if the plugin was instantianted by at least one configuration loaded +after the traffic server started and at least one configuration using it is still loaded. :func:`TSRemapPreConfigReload` will be called serially for all loaded plugins before any call to :func:`TSRemapNewInstance` during parsing of the new configuration. @@ -115,9 +128,10 @@ A plugin could use :func:`TSRemapPreConfigReload` as a signal to drop (or alloca per plugin data structures. These structures can be created (or updated) as needed when a plugin invocation instance is loaded (:func:`TSRemapNewInstance` is called). Then it could be used in subsequent invocation instances loading. After the configuration -reload is done :func:`TSRemapPostConfigReload` could be used to confirm -the data structures update if :macro:`TS_SUCCESS` is passed or recover / clean-up -after a failed reload attempt if :macro:`TS_ERROR` is passed. +reload is done :func:`TSRemapPostConfigReload` could be used to confirm the data +structures update if reload was successful, recover / clean-up after a failed +reload attempt, or if so wishes to ignore the notification if plugin is not part +of the new configuration.. Runtime diff --git a/include/ts/remap.h b/include/ts/remap.h index dd7be385c9d..1e804b936a6 100644 --- a/include/ts/remap.h +++ b/include/ts/remap.h @@ -75,6 +75,16 @@ typedef enum { TSREMAP_ERROR = -1 /* Some error, that should generate an error page */ } TSRemapStatus; +/* Status code passed to the plugin by TSRemapPostConfigReload() signaling + * (1) if the configuration reload was successful and + * (2) if (1) is successful show if the plugin was part of the new configuration */ +typedef enum { + TSREMAP_CONFIG_RELOAD_FAILURE = 0, /* notify the plugin that configuration parsing failed */ + TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED = 1, /* configuration parsing succeeded and plugin was used by the new configuration */ + TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED = + 2 /* configuration parsing succeeded but plugin was NOT used by the new configuration */ +} TSRemapReloadStatus; + /* ---------------------------------------------------------------------------------- These are the entry points a plugin can implement. Note that TSRemapInit() and TSRemapDoRemap() are both required. @@ -108,7 +118,7 @@ tsapi void TSRemapPreConfigReload(void); TS_ERROR - (re)load failed. Return: none */ -tsapi void TSRemapPostConfigReload(TSReturnCode reloadStatus); +tsapi void TSRemapPostConfigReload(TSRemapReloadStatus reloadStatus); /* Remap new request Mandatory interface function. diff --git a/proxy/http/remap/PluginDso.h b/proxy/http/remap/PluginDso.h index 23a84b5b9a2..e5427187323 100644 --- a/proxy/http/remap/PluginDso.h +++ b/proxy/http/remap/PluginDso.h @@ -34,6 +34,7 @@ #include #include "ts/apidefs.h" +#include "ts/remap.h" #include "tscore/ts_file.h" namespace fs = ts::file; @@ -75,10 +76,10 @@ class PluginDso : public PluginThreadContext using PluginList = ts::IntrusiveDList; /* Methods to be called when processing a list of plugins, to be overloaded by the remap or the global plugins correspondingly */ - virtual void indicatePreReload() = 0; - virtual void indicatePostReload(TSReturnCode reloadStatus) = 0; - virtual bool init(std::string &error) = 0; - virtual void done() = 0; + virtual void indicatePreReload() = 0; + virtual void indicatePostReload(TSRemapReloadStatus reloadStatus) = 0; + virtual bool init(std::string &error) = 0; + virtual void done() = 0; void acquire(); void release(); diff --git a/proxy/http/remap/PluginFactory.cc b/proxy/http/remap/PluginFactory.cc index 8b045cc12b3..9491228df2e 100644 --- a/proxy/http/remap/PluginFactory.cc +++ b/proxy/http/remap/PluginFactory.cc @@ -22,6 +22,8 @@ */ +#include + #include "RemapPluginInfo.h" #include "PluginFactory.h" #ifdef PLUGIN_DSO_TESTS @@ -274,13 +276,25 @@ PluginFactory::indicatePreReload() * @brief Tell all plugins (that so wish) that remap.config is done reloading */ void -PluginFactory::indicatePostReload(TSReturnCode reloadStatus) +PluginFactory::indicatePostReload(bool reloadSuccessful) { Debug(_tag, "indicated config is done reloading by factory '%s' to %zu plugin%s", getUuid(), _list.count(), _list.count() != 1 ? "s" : ""); - for (auto it = _list.begin(); _list.end() != it; it++) { - it->indicatePostReload(reloadStatus); + /* Find out which plugins (DSO) are actually instantiated by this factory */ + std::unordered_map pluginUsed; + for (auto &inst : _instList) { + pluginUsed[&(inst._plugin)]++; + } + + for (auto &plugin : _list) { + TSRemapReloadStatus status = TSREMAP_CONFIG_RELOAD_FAILURE; + if (reloadSuccessful) { + /* reload succeeded but was the plugin instantiated by this factory? */ + status = (pluginUsed.end() == pluginUsed.find(&plugin) ? TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED : + TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED); + } + plugin.indicatePostReload(status); } } diff --git a/proxy/http/remap/PluginFactory.h b/proxy/http/remap/PluginFactory.h index db722bd6372..5982db45a30 100644 --- a/proxy/http/remap/PluginFactory.h +++ b/proxy/http/remap/PluginFactory.h @@ -102,7 +102,7 @@ class PluginFactory void deactivate(); void indicatePreReload(); - void indicatePostReload(TSReturnCode reloadStatus); + void indicatePostReload(bool reloadSuccessful); protected: PluginDso *findByEffectivePath(const fs::path &path); diff --git a/proxy/http/remap/RemapConfig.cc b/proxy/http/remap/RemapConfig.cc index 5774b18c6c4..424f4bfac8c 100644 --- a/proxy/http/remap/RemapConfig.cc +++ b/proxy/http/remap/RemapConfig.cc @@ -1329,7 +1329,7 @@ remap_parse_config(const char *path, UrlRewrite *rewrite) /* Now after we parsed the configuration and (re)loaded plugins and plugin instances * accordingly notify all plugins that we are done */ - rewrite->pluginFactory.indicatePostReload(status ? TS_SUCCESS : TS_ERROR); + rewrite->pluginFactory.indicatePostReload(status); return status; } diff --git a/proxy/http/remap/RemapPluginInfo.cc b/proxy/http/remap/RemapPluginInfo.cc index a98c3eeb29e..8f8962b1747 100644 --- a/proxy/http/remap/RemapPluginInfo.cc +++ b/proxy/http/remap/RemapPluginInfo.cc @@ -258,7 +258,7 @@ RemapPluginInfo::indicatePreReload() } void -RemapPluginInfo::indicatePostReload(TSReturnCode reloadStatus) +RemapPluginInfo::indicatePostReload(TSRemapReloadStatus reloadStatus) { setPluginContext(); diff --git a/proxy/http/remap/RemapPluginInfo.h b/proxy/http/remap/RemapPluginInfo.h index 731196a26de..6d06b45266d 100644 --- a/proxy/http/remap/RemapPluginInfo.h +++ b/proxy/http/remap/RemapPluginInfo.h @@ -57,7 +57,7 @@ class RemapPluginInfo : public PluginDso /// Reload function, called to inform the plugin that configuration is going to be reloaded. using PreReload_F = void(); /// Reload function, called to inform the plugin that configuration is done reloading. - using PostReload_F = void(TSReturnCode); + using PostReload_F = void(TSRemapReloadStatus); /// Called when remapping for a transaction has finished. using Done_F = void(); /// Create an rule instance. @@ -99,7 +99,7 @@ class RemapPluginInfo : public PluginDso /* Used by traffic server core to indicate configuration reload */ virtual void indicatePreReload(); - virtual void indicatePostReload(TSReturnCode reloadStatus); + virtual void indicatePostReload(TSRemapReloadStatus reloadStatus); protected: /* Utility to be used only with unit testing */ diff --git a/proxy/http/remap/unit-tests/plugin_testing_calls.cc b/proxy/http/remap/unit-tests/plugin_testing_calls.cc index 1d57da3426b..883b971cdc6 100644 --- a/proxy/http/remap/unit-tests/plugin_testing_calls.cc +++ b/proxy/http/remap/unit-tests/plugin_testing_calls.cc @@ -109,10 +109,10 @@ TSRemapPreConfigReload(void) } void -TSRemapPostConfigReload(TSReturnCode reloadStatus) +TSRemapPostConfigReload(TSRemapReloadStatus reloadStatus) { debugObject.postReloadConfigCalled++; - debugObject.postReloadConfigSuccess = (TS_SUCCESS == reloadStatus); + debugObject.postReloadConfigStatus = reloadStatus; } /* The folowing functions are meant for unit testing */ diff --git a/proxy/http/remap/unit-tests/plugin_testing_common.h b/proxy/http/remap/unit-tests/plugin_testing_common.h index 3662d0c5ec6..f96c42031cf 100644 --- a/proxy/http/remap/unit-tests/plugin_testing_common.h +++ b/proxy/http/remap/unit-tests/plugin_testing_common.h @@ -51,19 +51,19 @@ class PluginDebugObject void clear() { - contextInit = nullptr; - contextInitInstance = nullptr; - doRemapCalled = 0; - initCalled = 0; - doneCalled = 0; - initInstanceCalled = 0; - deleteInstanceCalled = 0; - preReloadConfigCalled = 0; - postReloadConfigCalled = 0; - postReloadConfigSuccess = 0; - ih = nullptr; - argc = 0; - argv = nullptr; + contextInit = nullptr; + contextInitInstance = nullptr; + doRemapCalled = 0; + initCalled = 0; + doneCalled = 0; + initInstanceCalled = 0; + deleteInstanceCalled = 0; + preReloadConfigCalled = 0; + postReloadConfigCalled = 0; + postReloadConfigStatus = TSREMAP_CONFIG_RELOAD_FAILURE; + ih = nullptr; + argc = 0; + argv = nullptr; } /* Input fields used to set the test behavior of the plugin call-backs */ @@ -71,19 +71,19 @@ class PluginDebugObject void *input_ih; /* the value to be returned by the plugin instance init function */ /* Output fields showing what happend during the test */ - const PluginThreadContext *contextInit = nullptr; /* plugin initialization context */ - const PluginThreadContext *contextInitInstance = nullptr; /* plugin instance initialization context */ - int doRemapCalled = 0; /* mark if remap was called */ - int initCalled = 0; /* mark if plugin init was called */ - int doneCalled = 0; /* mark if done was called */ - int initInstanceCalled = 0; /* mark if instance init was called */ - int deleteInstanceCalled = 0; /* mark if delete instance was called */ - int preReloadConfigCalled = 0; /* mark if pre-reload config was called */ - int postReloadConfigCalled = 0; /* mark if post-reload config was called */ - bool postReloadConfigSuccess = 0; /* mark if plugin reload status is passed correctly */ - void *ih = nullptr; /* instance handler */ - int argc = 0; /* number of plugin instance parameters received by the plugin */ - char **argv = nullptr; /* plugin instance parameters received by the plugin */ + const PluginThreadContext *contextInit = nullptr; /* plugin initialization context */ + const PluginThreadContext *contextInitInstance = nullptr; /* plugin instance initialization context */ + int doRemapCalled = 0; /* mark if remap was called */ + int initCalled = 0; /* mark if plugin init was called */ + int doneCalled = 0; /* mark if done was called */ + int initInstanceCalled = 0; /* mark if instance init was called */ + int deleteInstanceCalled = 0; /* mark if delete instance was called */ + int preReloadConfigCalled = 0; /* mark if pre-reload config was called */ + int postReloadConfigCalled = 0; /* mark if post-reload config was called */ + TSRemapReloadStatus postReloadConfigStatus = TSREMAP_CONFIG_RELOAD_FAILURE; /* mark if plugin reload status is passed correctly */ + void *ih = nullptr; /* instance handler */ + int argc = 0; /* number of plugin instance parameters received by the plugin */ + char **argv = nullptr; /* plugin instance parameters received by the plugin */ }; #ifdef __cplusplus diff --git a/proxy/http/remap/unit-tests/test_PluginDso.cc b/proxy/http/remap/unit-tests/test_PluginDso.cc index 1635a65493f..2db5d1c43fe 100644 --- a/proxy/http/remap/unit-tests/test_PluginDso.cc +++ b/proxy/http/remap/unit-tests/test_PluginDso.cc @@ -73,7 +73,7 @@ class PluginDsoUnitTest : public PluginDso { } virtual void - indicatePostReload(TSReturnCode reloadStatus) + indicatePostReload(TSRemapReloadStatus reloadStatus) { } virtual bool diff --git a/proxy/http/remap/unit-tests/test_PluginFactory.cc b/proxy/http/remap/unit-tests/test_PluginFactory.cc index 1c75bbe37e7..1456f206a79 100644 --- a/proxy/http/remap/unit-tests/test_PluginFactory.cc +++ b/proxy/http/remap/unit-tests/test_PluginFactory.cc @@ -556,7 +556,7 @@ SCENARIO("notifying plugins of config reload", "[plugin][core]") { WHEN("(1) signal pre-new-config-load, (2) signal post-new-config-load, (3) old-config deactivate") { - /* Simulate configuration without plugins - an unused factory */ + /* Simulate configuration with 1 factory and 1 plugin */ setupConfigPathTest(configName1, buildPath, uuid_t1, effectivePath1, runtimePath1, 1556825556); PluginFactoryUnitTest *factory1 = getFactory(uuid_t1); RemapPluginInst *plugin1 = factory1->getRemapPlugin(configName1, 0, nullptr, error); @@ -581,19 +581,19 @@ SCENARIO("notifying plugins of config reload", "[plugin][core]") /* Assume (re)load was done OK and test */ debugObject->clear(); - factory1->indicatePostReload(TS_SUCCESS); + factory1->indicatePostReload(/* reload succeeded */ true); CHECK(0 == debugObject->deleteInstanceCalled); CHECK(0 == debugObject->doneCalled); CHECK(1 == debugObject->postReloadConfigCalled); - CHECK(true == debugObject->postReloadConfigSuccess); + CHECK(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED == debugObject->postReloadConfigStatus); /* Assume (re)load failed and test */ debugObject->clear(); - factory1->indicatePostReload(TS_ERROR); + factory1->indicatePostReload(/* reload succeeded */ false); CHECK(0 == debugObject->deleteInstanceCalled); CHECK(0 == debugObject->doneCalled); CHECK(1 == debugObject->postReloadConfigCalled); - CHECK(false == debugObject->postReloadConfigSuccess); + CHECK(TSREMAP_CONFIG_RELOAD_FAILURE == debugObject->postReloadConfigStatus); /* ... swap the new and the old config ... */ @@ -613,7 +613,7 @@ SCENARIO("notifying plugins of config reload", "[plugin][core]") { WHEN("(1) signal pre-new-config-load, (2) signal post-new-config-load, (3) old-config deactivate") { - /* Simulate configuration without plugins - an unused factory */ + /* Simulate configuration with 1 factories and 2 plugin */ setupConfigPathTest(configName1, buildPath, uuid_t1, effectivePath1, runtimePath1, 1556825556); setupConfigPathTest(configName2, buildPath, uuid_t1, effectivePath2, runtimePath2, 1556825556, /* append */ true); PluginFactoryUnitTest *factory1 = getFactory(uuid_t1); @@ -646,28 +646,28 @@ SCENARIO("notifying plugins of config reload", "[plugin][core]") /* Assume (re)load was done OK */ debugObject1->clear(); debugObject2->clear(); - factory1->indicatePostReload(TS_SUCCESS); + factory1->indicatePostReload(/* reload succeeded */ true); CHECK(0 == debugObject1->deleteInstanceCalled); CHECK(0 == debugObject1->doneCalled); CHECK(1 == debugObject1->postReloadConfigCalled); - CHECK(true == debugObject1->postReloadConfigSuccess); + CHECK(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED == debugObject1->postReloadConfigStatus); CHECK(0 == debugObject2->deleteInstanceCalled); CHECK(0 == debugObject2->doneCalled); CHECK(1 == debugObject2->postReloadConfigCalled); - CHECK(true == debugObject2->postReloadConfigSuccess); + CHECK(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED == debugObject2->postReloadConfigStatus); /* Assume (re)load failed */ debugObject1->clear(); debugObject2->clear(); - factory1->indicatePostReload(TS_ERROR); + factory1->indicatePostReload(/* reload succeeded */ false); CHECK(0 == debugObject1->deleteInstanceCalled); CHECK(0 == debugObject1->doneCalled); CHECK(1 == debugObject1->postReloadConfigCalled); - CHECK(false == debugObject1->postReloadConfigSuccess); + CHECK(TSREMAP_CONFIG_RELOAD_FAILURE == debugObject1->postReloadConfigStatus); CHECK(0 == debugObject2->deleteInstanceCalled); CHECK(0 == debugObject2->doneCalled); CHECK(1 == debugObject2->postReloadConfigCalled); - CHECK(false == debugObject2->postReloadConfigSuccess); + CHECK(TSREMAP_CONFIG_RELOAD_FAILURE == debugObject2->postReloadConfigStatus); /* ... swap the new and the old config ... */ @@ -691,7 +691,7 @@ SCENARIO("notifying plugins of config reload", "[plugin][core]") { WHEN("indicating de-activation of the factories") { - /* Simulate configuration without plugins - an unused factory */ + /* Simulate configuration with 2 factories and 1 plugin */ setupConfigPathTest(configName1, buildPath, uuid_t1, effectivePath1, runtimePath1, 1556825556); PluginFactoryUnitTest *factory1 = getFactory(uuid_t1); PluginFactoryUnitTest *factory2 = getFactory(uuid_t2); @@ -724,4 +724,63 @@ SCENARIO("notifying plugins of config reload", "[plugin][core]") clean(); } } + + GIVEN("configuration with 2 plugin loaded by 2 factories") + { + WHEN("2 plugins are loaded by the 1st factory and only one of them loaded by the 2nd factory") + { + /* Simulate configuration with 2 factories and 2 different plugins */ + setupConfigPathTest(configName1, buildPath, uuid_t1, effectivePath1, runtimePath1, 1556825556, /* append */ false); + setupConfigPathTest(configName2, buildPath, uuid_t1, effectivePath2, runtimePath2, 1556825556, /* append */ true); + PluginFactoryUnitTest *factory1 = getFactory(uuid_t1); + PluginFactoryUnitTest *factory2 = getFactory(uuid_t2); + + /* 2 plugins loaded by the 1st factory */ + RemapPluginInst *pluginInst1 = factory1->getRemapPlugin(configName1, 0, nullptr, error); + RemapPluginInst *pluginInst2 = factory1->getRemapPlugin(configName2, 0, nullptr, error); + + /* only 1 plugin loaded by the 2st factory */ + RemapPluginInst *pluginInst3 = factory2->getRemapPlugin(configName1, 0, nullptr, error); + + /* pluginInst1 and pluginInst3 should be using the same plugin DSO named configName1 + * pluginInst2 should be using plugin DSO named configName 2*/ + CHECK_FALSE(nullptr == pluginInst1); + CHECK_FALSE(nullptr == pluginInst2); + CHECK_FALSE(nullptr == pluginInst3); + CHECK(&pluginInst1->_plugin == &pluginInst3->_plugin); + + /* Get test objects for the 2 plugins used by the 3 instances from the 2 factories */ + PluginDebugObject *debugObject1 = getDebugObject(pluginInst1->_plugin); + PluginDebugObject *debugObject2 = getDebugObject(pluginInst2->_plugin); + + THEN( + "expect the plugin that is not loaded by the second factory to receive 'plugin unused' notification from the 2nd factory") + { + /* Factory 1: reload was OK and both plugins were part of the configuration that used/instantiated that factory */ + debugObject1->clear(); + debugObject2->clear(); + + factory1->indicatePostReload(/* reload succeeded */ true); + CHECK(1 == debugObject1->postReloadConfigCalled); + CHECK(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED == debugObject1->postReloadConfigStatus); + CHECK(1 == debugObject2->postReloadConfigCalled); + CHECK(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED == debugObject2->postReloadConfigStatus); + + /* Factory 2: (re)load was OK and only 1 plugin was part of the configuration that used/instantiated that factory */ + debugObject1->clear(); + debugObject2->clear(); + + factory2->indicatePostReload(/* reload succeeded */ true); + CHECK(1 == debugObject1->postReloadConfigCalled); + CHECK(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED == debugObject1->postReloadConfigStatus); + CHECK(1 == debugObject2->postReloadConfigCalled); + CHECK(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED == debugObject2->postReloadConfigStatus); + + delete factory1; + delete factory2; + } + + clean(); + } + } } diff --git a/proxy/http/remap/unit-tests/test_RemapPlugin.cc b/proxy/http/remap/unit-tests/test_RemapPlugin.cc index 49be30ff36d..0184ab214b2 100644 --- a/proxy/http/remap/unit-tests/test_RemapPlugin.cc +++ b/proxy/http/remap/unit-tests/test_RemapPlugin.cc @@ -422,17 +422,50 @@ SCENARIO("config reload", "[plugin][core]") bool result = loadPlugin(plugin, error, debugObject); CHECK(true == result); - WHEN("'config reload' is called") + WHEN("'config reload' failed") { debugObject->clear(); plugin->indicatePreReload(); - plugin->indicatePostReload(TS_SUCCESS); + plugin->indicatePostReload(TSREMAP_CONFIG_RELOAD_FAILURE); THEN("expect it to run") { CHECK(1 == debugObject->preReloadConfigCalled); CHECK(1 == debugObject->postReloadConfigCalled); + CHECK(TSREMAP_CONFIG_RELOAD_FAILURE == debugObject->postReloadConfigStatus); + } + cleanupSandBox(plugin); + } + + WHEN("'config reload' is successful and the plugin is part of the new configuration") + { + debugObject->clear(); + + plugin->indicatePreReload(); + plugin->indicatePostReload(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED); + + THEN("expect it to run") + { + CHECK(1 == debugObject->preReloadConfigCalled); + CHECK(1 == debugObject->postReloadConfigCalled); + CHECK(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED == debugObject->postReloadConfigStatus); + } + cleanupSandBox(plugin); + } + + WHEN("'config reload' is successful and the plugin is part of the new configuration") + { + debugObject->clear(); + + plugin->indicatePreReload(); + plugin->indicatePostReload(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED); + + THEN("expect it to run") + { + CHECK(1 == debugObject->preReloadConfigCalled); + CHECK(1 == debugObject->postReloadConfigCalled); + CHECK(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED == debugObject->postReloadConfigStatus); } cleanupSandBox(plugin); } From e878cd1325cc284589ca330e7a4ceb4fee322a06 Mon Sep 17 00:00:00 2001 From: Masakazu Kitajo Date: Tue, 8 Oct 2019 15:27:37 -0700 Subject: [PATCH 054/718] Add QUIC draft-23 support Squashed commit of the following: commit 8aab554452ee9f9f770b2406b0df0d033eaae8e0 Merge: fa823387f 32b5dae81 Author: Masakazu Kitajo Date: Tue Oct 8 15:14:18 2019 -0700 Merge branch 'master' into quic-latest * master: Add filename to error message in header_rewrite Turn on certificate verification, in permissive mode for now Concurrent SRV request failures Fix use-after-free problem related to logging headers ssl_multicert.config -> params->configFilePath Adds build targets on CI for 9.0.x weak mutex macros Fix a build issue on enabling FIPS Change the ready checks for ats to use the actual ats port and not the server port. Add ready check on server port for the server Address possibe use after free issue in HttpVCTable::remove_entry YAML config: output erroneous keyword and line number in YAML file it appears on in diags.log. Convert old sni configuration file in lua to yaml First cut at a layout for Release Notes Clear api set bit to avoid crash in following redirect. commit fa823387f81aefe42cabf5a449977dc861b90587 Author: scw00 Date: Fri Sep 27 14:04:31 2019 +0800 QUIC: Fix test_QUICKeyGenerator commit e62f4af7a3ee6978986cbd490875286ce1fa2730 Author: Masakazu Kitajo Date: Fri Sep 27 16:35:07 2019 +0900 Fix a compile warning commit 887732b49527b4266b4b7956db3f627355b3bd14 Author: Masakazu Kitajo Date: Tue Sep 10 13:01:15 2019 +0900 Update initial salt commit c2b9be3a83919b0c863e2d5880956aaf2096e3a7 Author: Masakazu Kitajo Date: Tue Sep 10 10:16:20 2019 +0900 Update QUIC transport error codes commit 9d843ebf6e9399ff4dabd62952d7dc6a98f65f93 Author: Masakazu Kitajo Date: Tue Sep 10 09:58:26 2019 +0900 Rename DISABLE_MIGRATION to DISABLE_ACTIVE_MIGRATION commit d1951e98e86702f0769947c7541f64aed2045962 Author: Masakazu Kitajo Date: Tue Sep 10 09:54:22 2019 +0900 Update the length of unpredictable bits field in Stateless Reset Packet commit 617dd31a7bd904d839abc4fde50eb3f5280ce1e9 Author: Masakazu Kitajo Date: Tue Sep 10 09:51:47 2019 +0900 Update draft version numbers to 23 commit 2e78599cc634a85f9552f22132bfbdd084319391 Merge: 212fdd319 70de21d9c Author: Masakazu Kitajo Date: Fri Sep 27 10:24:45 2019 +0900 Merge branch 'master' into quic-latest * master: (23 commits) Rearrange config reload notifications Removed hardcoded sni.yaml configuration filename in logs Clarify docs on the change from redirect_enabled. Make code buildable with BoringSSL Fix debug output for global_user_agent_header. Add documentation for TSHttpTxnRedoCacheLookup Add example plugin to show how to use TSRedoCacheLookup. TSHttpTxnRedoCacheLookup. Fix reference to SMDebug. adding TSHttpTxnRedoCacheLookup Add AUTest using h2spec Track scheduled events to (read|write)_vio.cont from Http2Stream Cleanup AuTest for HTTP/2 Fix AuTest for HTTP/2 using httpbin Add base64 encoding/decoding to encryption/decryption, and general code cleanup. Update documentation for connect_attempts_timeout. Track SSL session cache evictions performed due to full bucket Perform a SSL quiet shutdown when close-notify is not sent Remove hard coded filename in error message Substitution string has changed ... commit 212fdd3198a846eca22e7bbe73a0765c3e4782ee Author: Masakazu Kitajo Date: Fri Sep 27 10:20:28 2019 +0900 Fix unit tests commit 6f470fa831d4401bc85703ad233218e535df9d90 Author: Masakazu Kitajo Date: Thu Sep 26 17:36:39 2019 +0900 Fix build issues on macOS (or clang) commit a786041f3e27d34d009636a781cf3bd6972f0882 Author: scw00 Date: Thu Sep 19 08:29:25 2019 +0800 QUIC: Remove useless default constructor in QUICStreamManager commit edc4b672b98e38dd95f6d9a80e271e999cd3297a Author: scw00 Date: Tue Sep 17 14:03:14 2019 +0800 QUIC: Rename QUICCongestionController.cc to QUICNewRenoCongestionController.cc commit 45c3f138633466f2bc31dd45bbd617b00e14938b Author: scw00 Date: Wed Sep 11 14:09:34 2019 +0800 QUIC: Remove unnecessary allocator commit 256a74c54f93cf86cd7fc8d866f195b23df2f2f0 Author: scw00 Date: Wed Sep 11 11:30:04 2019 +0800 QUIC: Add Token Creator commit 5980fa47083aca5df6d4f04e388ddab5344cdd2b Author: scw00 Date: Mon Sep 9 15:24:23 2019 +0800 QUIC: add more infomation to QUICPacketProtectionKeyInfo commit 814f39e8269d8c19064b698825c2b9441c9eacb5 Author: scw00 Date: Mon Sep 9 12:32:20 2019 +0800 QUIC: Hidden more pp_key_info detail in QUICContext commit fecacfbd973b7c5e3b10c21e94fdfff4300768e5 Author: Masakazu Kitajo Date: Tue Sep 10 14:33:52 2019 +0900 Stabilize unit tests commit e8565bbee89663a1c89b4052c0fc32ea80bccfb6 Author: scw00 Date: Wed Aug 7 10:55:54 2019 +0800 QUIC: Adds QUICContext to wrap some common params commit 5b04932d62ff66602923c7e63250660fd0992e84 Merge: 5c7b68a0d 92d4ef142 Author: Masakazu Kitajo Date: Fri Sep 6 11:16:38 2019 +0900 Merge branch 'master' into quic-latest * master: Check F_GETPIPE_SZ is defined to fix macOS build Update Server IP in Transaction when attaching a session from the pool Add unit tests for MIOBuffer:write() Allow disabling HTTP/2 priority frames limit Add implementation for TextView::rtrim(char const*) Doc: Guide to remap plugin API. Add helper functions to apply api timeouts consistently. address review comments pipe buffer size for log.pipe should be configurable Provide stats for the recently introduced HTTP/2 rate limits commit 5c7b68a0d337fefaf1d4cdde31574c0ab9144034 Author: Masakazu Kitajo Date: Wed Sep 4 14:40:30 2019 +0900 Send PreferredAddress only if necessary commit 2b5e2ce18e6367f142f2acad345489716486660a Author: Masakazu Kitajo Date: Tue Sep 3 17:04:27 2019 +0900 Fix memory leaks detected by ASAN commit 13bdd9d05f5348c0aaa37f7669f1fa425c434503 Merge: e7430fabb c65f0a1fb Author: Masakazu Kitajo Date: Tue Sep 3 14:12:38 2019 +0900 Merge branch 'master' into quic-latest * master: (30 commits) Cleanup: Remove unused AllocType and unused functions Ran clang-format ProxySsn renaming member vars cachekey: added --key-type (for parent selection) Bumped the version of master to 10.0.0 ProxySsn Refactor move code to cc 1) add autest for log filter; 2) support filter for duplicated param name in query parm of URL code clean from review comments move code to utility function to reduce the interface size fix typo issue fix the bug if filter word included in param value fix the bug if filter word included in param value correct the size of DNS buffers cachekey: added --canonical-prefix parameter static linking asan, tsan, lsan Fixed const issue with magick plugin CI: added support for disabling curl in the build Adds the v9.0.x Docs link to main docs page Updates the CI build scripts, adds QUIC support Expose client SSL stats via API & Lua ... commit e7430fabb29f91bf6d146834d7eb5ba867b130a0 Author: Masakazu Kitajo Date: Tue Sep 3 14:07:01 2019 +0900 Fix QUICPinger and tests for it commit f040d5fa7bcb170d054d5f0773a7aba38312bd3b Author: Masakazu Kitajo Date: Tue Sep 3 12:33:26 2019 +0900 Print a raw value of unknown transport parameter commit 13f9f63aef7e8b76d5aa11048d29112ccfaae533 Author: Masakazu Kitajo Date: Tue Aug 27 14:25:00 2019 +0900 Use active_connection_id_limit advertised commit 0e4622e62613fd8b7b9a8d65e2613131a7d1d9c6 Author: Masakazu Kitajo Date: Thu Aug 22 16:38:38 2019 +0900 Assert sending a frame that is allowed on the encryption level commit 72b1f79c0af422a1e383d7becf370a580bcfd159 Author: Masakazu Kitajo Date: Thu Aug 22 16:23:53 2019 +0900 Send PING only on Short packets commit e7a6cd6292ba54b6804b79298188e7042a73577a Merge: 3c8e6d12f 5886fb212 Author: Masakazu Kitajo Date: Wed Aug 21 11:42:41 2019 +0900 Merge branch 'master' into quic-latest * master: Fix inactivity timeout on QUIC Cleanup: Remove unused empty files Cleanup: unifdef WRITE_AND_TRANSFER Explain how SRV origin selection works Doc: fix build errors. HTTP/2 fix with realloc Fix clang-tidy's mistakes Ran make clang-tidy Updated clang-tidy configuration, scripts, and Makefiles Make proxy.config.http.per_server.min_keep_alive_connections overridable Make TS_NULL_MLOC a valid C compile-time constant. Doc: Remove python 2 vestiges from conf.py, traffic-server.py. Conflicts: iocore/net/QUICNetVConnection.cc commit 3c8e6d12f9335dc7b55ca45dafb21fc4c3c3c0b8 Merge: 7a9d7fd63 aa319a461 Author: Masakazu Kitajo Date: Mon Aug 19 09:29:44 2019 +0900 Merge branch 'master' into quic-latest * master: (48 commits) Fix H2 internal counters Reactivate active timeout enforcement Avoid AWS auth v4 path/query param double encoding Fix QUIC build Cleanup: Signal READ_READY event only if the buffer is readable Cleanup: Remove unused function & old comments Make client_context_dump test resilient to dump order changes Record HttpSM Id on new transaction make check race condition fix Doc: Improve handling of build when documentation is not enabled. fix. Limit resources used by regex_remap to prevent crashes on resource exhaustion. compress plugin: document undocumented options Allocate DependencyTree only if HTTP/2 stream priority is enabled HTTP/2 rate limiting Fixes various issues found in docs Remove double call of the SNI action on TLS accept. Refactor the alpn/npn handling into common ALPNSupport class Update for QUIC integration. Fixed the InkAPI to provide the TSVConnProtocolEnable/Disable functions. Update documentation and updated the example plugin. ... commit 7a9d7fd633dfdcd8a931dbbf35b76fa590707581 Author: Masakazu Kitajo Date: Fri Aug 16 11:56:12 2019 +0900 fix typo commit 5b5efeccb23e88b25e7b644a4a828208679f6416 Author: Masakazu Kitajo Date: Mon Aug 5 11:08:49 2019 +0900 Print sending Retry packets commit d222be218ef38f3f26e8a68b64f691b984f10799 Author: Masakazu Kitajo Date: Fri Aug 2 09:32:09 2019 +0900 Min/Max length of PreferredAddress commit fb350263dc0b8cc73d557c8ed1220afccfb9b244 Merge: 4938b7f85 e068b7685 Author: Masakazu Kitajo Date: Thu Aug 1 16:57:48 2019 +0900 Merge branch 'master' into quic-latest * master: Add support for updating Container fields as well Preserve the raw log fields when wiping using case insensitive contains Add soft limit for HTTP Request URI and Header field length. Add a default body_factory template when rejecting a request that's too long Doc: Minor typo in CONTRIBUTING.md Add QUIC draft-20 support Initialize EventIO fixed datatype in example plugin Cleanup debug logs around SSLWriteBuffer Remove unnecesary function name on debug logs in SSLNetVConnection TS API - Adds the TSHttpTxnNextHopNameGet() function. Conflicts: .gitignore iocore/net/P_QUICNetVConnection.h iocore/net/QUICNetVConnection.cc iocore/net/QUICPacketHandler.cc iocore/net/quic/Makefile.am iocore/net/quic/Mock.h iocore/net/quic/QUICAckFrameCreator.cc iocore/net/quic/QUICAckFrameCreator.h iocore/net/quic/QUICAltConnectionManager.cc iocore/net/quic/QUICAltConnectionManager.h iocore/net/quic/QUICBidirectionalStream.cc iocore/net/quic/QUICBidirectionalStream.h iocore/net/quic/QUICConfig.h iocore/net/quic/QUICCongestionController.cc iocore/net/quic/QUICCryptoStream.cc iocore/net/quic/QUICCryptoStream.h iocore/net/quic/QUICDebugNames.cc iocore/net/quic/QUICFlowController.cc iocore/net/quic/QUICFlowController.h iocore/net/quic/QUICFrame.cc iocore/net/quic/QUICFrame.h iocore/net/quic/QUICFrameDispatcher.cc iocore/net/quic/QUICFrameDispatcher.h iocore/net/quic/QUICFrameGenerator.cc iocore/net/quic/QUICFrameGenerator.h iocore/net/quic/QUICHandshake.cc iocore/net/quic/QUICHandshake.h iocore/net/quic/QUICKeyGenerator.cc iocore/net/quic/QUICLossDetector.cc iocore/net/quic/QUICLossDetector.h iocore/net/quic/QUICPacket.cc iocore/net/quic/QUICPacket.h iocore/net/quic/QUICPacketFactory.cc iocore/net/quic/QUICPacketFactory.h iocore/net/quic/QUICPacketHeaderProtector.cc iocore/net/quic/QUICPacketReceiveQueue.cc iocore/net/quic/QUICPacketReceiveQueue.h iocore/net/quic/QUICPathValidator.cc iocore/net/quic/QUICPathValidator.h iocore/net/quic/QUICPinger.cc iocore/net/quic/QUICPinger.h iocore/net/quic/QUICStreamManager.cc iocore/net/quic/QUICStreamManager.h iocore/net/quic/QUICTransportParameters.h iocore/net/quic/QUICTypes.cc iocore/net/quic/QUICTypes.h iocore/net/quic/QUICUnidirectionalStream.cc iocore/net/quic/QUICUnidirectionalStream.h iocore/net/quic/test/test_QUICAckFrameCreator.cc iocore/net/quic/test/test_QUICFlowController.cc iocore/net/quic/test/test_QUICFrame.cc iocore/net/quic/test/test_QUICFrameDispatcher.cc iocore/net/quic/test/test_QUICInvariants.cc iocore/net/quic/test/test_QUICKeyGenerator.cc iocore/net/quic/test/test_QUICLossDetector.cc iocore/net/quic/test/test_QUICPacket.cc iocore/net/quic/test/test_QUICPacketFactory.cc iocore/net/quic/test/test_QUICPacketHeaderProtector.cc iocore/net/quic/test/test_QUICStream.cc iocore/net/quic/test/test_QUICStreamManager.cc iocore/net/quic/test/test_QUICType.cc mgmt/RecordsConfig.cc src/traffic_quic/quic_client.cc src/tscore/ink_inet.cc commit 4938b7f854cb06411d6fd061bdbde28a53074103 Author: Masakazu Kitajo Date: Thu Aug 1 14:21:50 2019 +0900 Make QUICFrame:to_io_buffer_block pure virtual commit baaf97c51637116fcdd1ba3bf475788115c8662c Author: Masakazu Kitajo Date: Thu Aug 1 14:04:13 2019 +0900 Convert QUICAckFrame::store to to_io_buffer_block commit ad565245ed077205a6955a77d3250e2a39f5775b Author: Masakazu Kitajo Date: Thu Aug 1 12:21:42 2019 +0900 Convert QUICUnknownFrame::store to to_io_buffer_block commit 9cb75727328f8f02d9938a056ec5f5ac6091374c Author: Masakazu Kitajo Date: Thu Aug 1 12:15:30 2019 +0900 Convert QUICRetireConnectionIdFrame::store to to_io_buffer_block commit cc452b953d0cfb00be3abee374a99251d3139889 Author: Masakazu Kitajo Date: Thu Aug 1 12:06:40 2019 +0900 Convert QUICNewTokenFrame::store to to_io_buffer_block commit 748d66cfad7e7181bd7b1aa50ebb9bed51f00b81 Author: Masakazu Kitajo Date: Thu Aug 1 11:50:25 2019 +0900 Convert QUICCryptoFrame::store to to_io_buffer_block commit 2b38e5f88289a4e7d590d767c2b7c9a1942a184a Author: Masakazu Kitajo Date: Wed Jul 31 17:27:51 2019 +0900 Convert QUICPathResponseFrame::store to to_io_buffer_block commit e0f2c609212a617ae59ce0346dc9327a83421cc6 Author: Masakazu Kitajo Date: Wed Jul 31 17:18:23 2019 +0900 Convert QUICPathChallengeFrame::store to to_io_buffer_block commit edd2963e2e0b12f6e14364bd5cdd4473e1804600 Author: Masakazu Kitajo Date: Wed Jul 31 17:10:00 2019 +0900 Convert QUICNewConnectionIdFrame::store to to_io_buffer_block commit 93b79fb2e6386ce840130b08f46c8e58e56ffd2d Author: Masakazu Kitajo Date: Wed Jul 31 16:52:38 2019 +0900 Convert QUICStreamIdBlockedFrame::store to to_io_buffer_block commit d3b5ea831572403b037bba8585fa592acb585d14 Author: Masakazu Kitajo Date: Wed Jul 31 16:44:58 2019 +0900 Convert QUICStreamDataBlockedFrame::store to to_io_buffer_block commit a1390e86c95fffc8e62f7c4ea471e77bddd6554b Author: Masakazu Kitajo Date: Wed Jul 31 16:40:27 2019 +0900 Convert QUICDataBlockediFrame::store to to_io_buffer_block commit f419cd9752aa1312454fe819a08e0516f90a3ba2 Author: Masakazu Kitajo Date: Wed Jul 31 16:32:35 2019 +0900 Convert QUICPaddingFrame::store to to_io_buffer_block commit 6f5da6078bcb76cd1f0aabfc7c38defe7886e5d2 Author: Masakazu Kitajo Date: Wed Jul 31 16:23:10 2019 +0900 Convert QUICMaxStreamsFrame::store to to_io_buffer_block commit 08501a8886e35241ca08ed9cd558e6dce5a18735 Author: Masakazu Kitajo Date: Wed Jul 31 16:18:21 2019 +0900 Convert QUICMaxStreamDataFrame::store to to_io_buffer_block commit ac4a732c6f3f574f0558895b708bd557b50b95ce Author: Masakazu Kitajo Date: Wed Jul 31 16:13:36 2019 +0900 Convert QUICMaxDataFrame::store to to_io_buffer_block commit d996d4bcab89786783b9b4065c3ccf5ebc1008f0 Author: Masakazu Kitajo Date: Wed Jul 31 16:05:08 2019 +0900 Convert QUICPingFrame::store to to_io_buffer_block commit 578772f84d2fcf425ee06b661a5a7b2a655cf6a1 Merge: eb2a9d31c 78995bf4e Author: Masakazu Kitajo Date: Tue Jul 23 15:03:38 2019 +0900 Merge branch 'master' into quic-latest * master: (46 commits) Add dest addr information to UDPPacket class Update UDPNet for QUIC Add HKDF wrapper Use un-deprecated records for SSL server verification Removes proxy.config.http.cache.allow_empty_doc Deprecate the mysql_remap plugin. See #5395 Removes the stale_while_revalidate plugin. See #5395 Removes the memcached_remap plugin. See #5395 Removes the hipes plugin. See #5395 Removes the header_normalize plugin. See #5395 Removes the buffer_upload plugin. See #5395 Removes the balancer plugin. See #5395 Fixes spelling in lib/records Fixes memory leak in traffic_crashlog Promotes certifier to stable, see #5394 Promotes remap_purge to stable, see #5394 Promotes prefetch to stable, see #5394 Promotes multiplexer to stable, see #5394 Promotes cache_range_requests to stable, see #5394 fix If-Match and If-Unmodified-Since priority problem,about rfc https://tools.ietf.org/html/rfc7232#section-3.3 ... Conflicts: build/crypto.m4 configure.ac include/tscore/HKDF.h iocore/net/P_UDPNet.h iocore/net/P_UnixNet.h iocore/net/UnixUDPNet.cc src/tscore/HKDF_boringssl.cc src/tscore/HKDF_openssl.cc commit eb2a9d31c6c5eca02596181085509aa155126e16 Author: Masakazu Kitajo Date: Mon Jul 22 12:25:23 2019 +0900 Fix frame parsers for CON_CLOSE, STOP_SENDING and RST_STREAM Error codes were read as 16 bit integers commit 0dc9a3e542734909cd3466b555ecf56461fbd7e7 Author: Masakazu Kitajo Date: Mon Jul 22 09:43:54 2019 +0900 Fix CONNECTION_CLOSE frame parser commit a62388d1b538e0d2617465928124a4b7573119ef Author: Masakazu Kitajo Date: Mon Jul 22 07:36:02 2019 +0900 Set default value for initial_max_stream_data_uni to 4096 http-22 says it should be 1024 or greater. commit 0e46a6bccc582f02d65d4e11c228e423e35508b6 Author: Masaori Koshiba Date: Mon Jul 22 02:07:32 2019 +0900 Fix storing QUICConnectionId::ZERO commit 5db9a3b1cba535e6dac6664139c953b136e8adcb Author: Masakazu Kitajo Date: Fri Jul 19 23:39:13 2019 +0900 Update max cid length commit 6e6351e721d784121f40f0f381124d624f7e5a39 Author: Masaori Koshiba Date: Fri Jul 19 15:00:10 2019 +0900 Fix buffer length for VN packet commit bcf842a12a0a9ec67ca1d7e5e95f5c9be6a806ab Author: Masaori Koshiba Date: Fri Jul 19 14:45:59 2019 +0900 Fix stateless retry on server side Prior this change, getting the token filed offset of INITIAL packet was wrong when stateless retry is enabled. commit ab8508b28a48c0653bd9187ce4511cb96d76ec34 Author: Masaori Koshiba Date: Fri Jul 19 11:30:35 2019 +0900 Fix QUICFrame & unit tests for NEW_CONNECTION_ID commit 62f7174c6ec2428218f9b457f9b37a816a622e6a Author: Masakazu Kitajo Date: Thu Jul 18 16:26:25 2019 +0900 Add getter for retire_prior_to field commit 3fff0dec8aa7abc8ef34a3a9da50ac3336de06ab Author: Masakazu Kitajo Date: Thu Jul 18 16:14:27 2019 +0900 Add Retire Prior To field to sending NCID frames commit 2944fe85c21816ae5bcbeba8199f26c035049f8b Author: Masaori Koshiba Date: Thu Jul 18 15:57:30 2019 +0900 Add tests for static functions of QUICPacketLongHeader commit 1ce476c91cd50e66c916daa1446f7d2480f19604 Author: Masaori Koshiba Date: Thu Jul 18 12:28:55 2019 +0900 Fix getting packet length on dequeue from QUICPacketReceiveQueue commit 142e11e2cd4b6bfc4fb91db9b8fbcbd72123950c Author: Masaori Koshiba Date: Thu Jul 18 11:21:33 2019 +0900 Update to support new RETRY packet format commit 16d7129f14d259d290bbb2b06aa69ecb107ea906 Author: Masaori Koshiba Date: Thu Jul 18 11:00:27 2019 +0900 Fix sampling offset for packet header protection & unit tests commit 6f8682715cb604f838711b9ec6af5ed99db95f16 Author: Masakazu Kitajo Date: Thu Jul 18 08:56:53 2019 +0900 Fix tests for QUICFrameDispatcher commit c647ed4dac3ca538252857e8674aa3b7ec47dd05 Author: Masaori Koshiba Date: Wed Jul 17 16:20:48 2019 +0900 Fix unit tests for QUICPacketFactory commit f140407023a3377d9c4ce420d4e33f66da735a8e Author: Masaori Koshiba Date: Wed Jul 17 16:17:47 2019 +0900 Update storing long header packet & unit tests commit 7cc4b20ad7c82f9eaa2bda787897a0a1bb4b0560 Author: Masaori Koshiba Date: Wed Jul 17 16:16:29 2019 +0900 Fix loading long header packet commit c47874c3653191fb90543fbed5d6b734d69fba86 Author: Masaori Koshiba Date: Wed Jul 17 14:54:38 2019 +0900 Fix unit tests for QUICInvariants commit 87afcb077642df9c4902c15a7fc42f58b9a5f060 Author: Masakazu Kitajo Date: Tue Jul 16 21:38:00 2019 +0900 Update Long Header CID parser commit 86a4317b4fd2ef19456cf5d231d78c50d99db09d Author: Masakazu Kitajo Date: Tue Jul 9 17:10:20 2019 +0900 Use variable-length integer for error code fields on QUIC frames commit e105d33d7569739174abffddb89c491e3e729cb0 Author: Masakazu Kitajo Date: Fri Jul 5 17:10:55 2019 +0900 Make ErrorCode 62 bit unsigned integer commit 13d003757239833d8eff2e94aa387dc2dddb1dff Author: Masakazu Kitajo Date: Fri Jul 5 16:40:39 2019 +0900 Update initial_salt commit f0602a6e187e456b85e34b97d4aff6d2be9789ed Author: Masakazu Kitajo Date: Fri Jul 5 16:16:42 2019 +0900 Add active_connection_id_limit Transport Parameter commit 923916d7f0bbea19367fdfc7b2ddf430c5a54233 Author: Masakazu Kitajo Date: Thu Jul 4 17:22:48 2019 +0900 Update draft version numbers to 22 commit e95f03599f42743e8774908c9a8d0879f5c59890 Author: Masakazu Kitajo Date: Thu Jul 11 12:40:22 2019 +0900 Fix a heap-use-after-free in path validation commit c444068c28fe1693e056596faf3039ad0adde8e3 Merge: eb4092333 8510a1c24 Author: Masakazu Kitajo Date: Wed Jul 10 11:51:27 2019 +0900 Merge branch 'master' into quic-latest * master: Log H2 errors with the codes Separate out common header compression logic to hdrs directory TSIOBufferReaderCopy: copy data from a reader to a fixed buffer. Remove unused header file ink_inout.h Remove unused LibBulkIO Reverse internal order of HPACK Dynamic Table Entries More Autest cleanup Conflicts: proxy/hdrs/Makefile.am proxy/http2/HPACK.cc commit eb4092333da5734acd9cf6b933a97f6b160c0b14 Author: Masakazu Kitajo Date: Tue Jul 9 09:25:35 2019 +0900 Fix QUICPath::operator== commit 10805ba0dfe346dfbe93dad24656110e6d5fb250 Author: scw00 Date: Mon Jul 8 10:08:29 2019 +0800 QUIC: remove useless params in padder commit b0f248334200ec10be9d87d8593d7f46b4c88104 Author: scw00 Date: Mon Jul 8 09:25:28 2019 +0800 QUIC: Add inline generators into QUICFrameGenerator commit b76299f09e128e17d7103ee5ca5c72f3f4f67b22 Author: scw00 Date: Sun Jul 7 13:20:11 2019 +0800 QUIC: Add QUICPinger test commit fdff5b96f24e0d681884a1553ae1203161e9efaa Author: scw00 Date: Sun Jul 7 12:21:08 2019 +0800 QUIC: Fix test commit 816305894503400861fc4e830f464c6a3a3b1b41 Author: scw00 Date: Sun Jul 7 12:07:34 2019 +0800 QUIC: Using weight for QUICFrameGenerators commit 1eeb804564afb7db5164c8db90e6b5bcedd86b3e Author: scw00 Date: Thu Jul 4 08:58:15 2019 +0800 QUIC: Split QUICFrameGenerator into two queue (cherry picked from commit a80d779480e51c61e82d36f8e152d8d3ffa2367c) --- .gitignore | 24 +- iocore/eventsystem/I_Thread.h | 2 - iocore/net/P_QUICNetVConnection.h | 45 +- iocore/net/QUICNetVConnection.cc | 414 +++---- iocore/net/QUICPacketHandler.cc | 27 +- iocore/net/quic/Makefile.am | 26 +- iocore/net/quic/Mock.h | 408 +++--- iocore/net/quic/QUICAckFrameCreator.cc | 5 +- iocore/net/quic/QUICAckFrameCreator.h | 4 +- iocore/net/quic/QUICAltConnectionManager.cc | 166 +-- iocore/net/quic/QUICAltConnectionManager.h | 33 +- iocore/net/quic/QUICBidirectionalStream.cc | 14 +- iocore/net/quic/QUICBidirectionalStream.h | 4 +- iocore/net/quic/QUICConfig.cc | 21 +- iocore/net/quic/QUICConfig.h | 18 +- iocore/net/quic/QUICCongestionController.h | 53 + iocore/net/quic/QUICConnection.h | 1 + iocore/net/quic/QUICContext.cc | 147 +++ iocore/net/quic/QUICContext.h | 84 ++ iocore/net/quic/QUICCryptoStream.cc | 4 +- iocore/net/quic/QUICCryptoStream.h | 4 +- iocore/net/quic/QUICDebugNames.cc | 20 +- iocore/net/quic/QUICFlowController.cc | 4 +- iocore/net/quic/QUICFlowController.h | 4 +- iocore/net/quic/QUICFrame.cc | 1090 +++++++++++------ iocore/net/quic/QUICFrame.h | 172 +-- iocore/net/quic/QUICFrameDispatcher.cc | 4 +- iocore/net/quic/QUICFrameDispatcher.h | 3 +- iocore/net/quic/QUICFrameGenerator.cc | 29 + iocore/net/quic/QUICFrameGenerator.h | 56 +- iocore/net/quic/QUICHandshake.cc | 18 +- iocore/net/quic/QUICHandshake.h | 4 +- iocore/net/quic/QUICIncomingFrameBuffer.cc | 24 +- iocore/net/quic/QUICKeyGenerator.cc | 2 +- iocore/net/quic/QUICLossDetector.cc | 242 ++-- iocore/net/quic/QUICLossDetector.h | 96 +- ....cc => QUICNewRenoCongestionController.cc} | 105 +- iocore/net/quic/QUICPacket.cc | 168 ++- iocore/net/quic/QUICPacket.h | 35 +- iocore/net/quic/QUICPacketFactory.cc | 19 +- iocore/net/quic/QUICPacketFactory.h | 2 +- iocore/net/quic/QUICPacketHeaderProtector.cc | 25 +- iocore/net/quic/QUICPacketProtectionKeyInfo.h | 68 +- iocore/net/quic/QUICPacketReceiveQueue.cc | 35 +- iocore/net/quic/QUICPacketReceiveQueue.h | 1 + iocore/net/quic/QUICPadder.cc | 109 ++ iocore/net/quic/QUICPadder.h | 57 + iocore/net/quic/QUICPathManager.cc | 84 ++ iocore/net/quic/QUICPathManager.h | 53 + iocore/net/quic/QUICPathValidator.cc | 159 ++- iocore/net/quic/QUICPathValidator.h | 54 +- iocore/net/quic/QUICPinger.cc | 66 +- iocore/net/quic/QUICPinger.h | 25 +- iocore/net/quic/QUICStreamManager.cc | 22 +- iocore/net/quic/QUICStreamManager.h | 5 +- iocore/net/quic/QUICTokenCreator.cc | 71 ++ iocore/net/quic/QUICTokenCreator.h | 42 + iocore/net/quic/QUICTransportParameters.cc | 7 +- iocore/net/quic/QUICTransportParameters.h | 3 +- iocore/net/quic/QUICTypes.cc | 50 +- iocore/net/quic/QUICTypes.h | 101 +- iocore/net/quic/QUICUnidirectionalStream.cc | 15 +- iocore/net/quic/QUICUnidirectionalStream.h | 8 +- .../net/quic/test/test_QUICAckFrameCreator.cc | 103 +- .../test/test_QUICAltConnectionManager.cc | 3 + .../net/quic/test/test_QUICFlowController.cc | 56 +- iocore/net/quic/test/test_QUICFrame.cc | 374 ++++-- .../net/quic/test/test_QUICFrameDispatcher.cc | 21 +- .../quic/test/test_QUICIncomingFrameBuffer.cc | 23 +- iocore/net/quic/test/test_QUICInvariants.cc | 23 +- iocore/net/quic/test/test_QUICKeyGenerator.cc | 27 +- iocore/net/quic/test/test_QUICLossDetector.cc | 35 +- iocore/net/quic/test/test_QUICPacket.cc | 89 +- .../net/quic/test/test_QUICPacketFactory.cc | 5 +- .../test/test_QUICPacketHeaderProtector.cc | 45 +- .../net/quic/test/test_QUICPathValidator.cc | 112 ++ iocore/net/quic/test/test_QUICPinger.cc | 101 ++ iocore/net/quic/test/test_QUICStream.cc | 148 +-- .../net/quic/test/test_QUICStreamManager.cc | 4 +- .../quic/test/test_QUICTransportParameters.cc | 6 +- iocore/net/quic/test/test_QUICType.cc | 68 + mgmt/RecordsConfig.cc | 10 +- proxy/http3/QPACK.h | 4 +- src/traffic_quic/quic_client.cc | 4 +- src/tscore/ink_inet.cc | 4 +- 85 files changed, 3928 insertions(+), 1998 deletions(-) create mode 100644 iocore/net/quic/QUICCongestionController.h create mode 100644 iocore/net/quic/QUICContext.cc create mode 100644 iocore/net/quic/QUICContext.h rename iocore/net/quic/{QUICCongestionController.cc => QUICNewRenoCongestionController.cc} (62%) create mode 100644 iocore/net/quic/QUICPadder.cc create mode 100644 iocore/net/quic/QUICPadder.h create mode 100644 iocore/net/quic/QUICPathManager.cc create mode 100644 iocore/net/quic/QUICPathManager.h create mode 100644 iocore/net/quic/QUICTokenCreator.cc create mode 100644 iocore/net/quic/QUICTokenCreator.h create mode 100644 iocore/net/quic/test/test_QUICPathValidator.cc create mode 100644 iocore/net/quic/test/test_QUICPinger.cc diff --git a/.gitignore b/.gitignore index 23cdc5dd8b3..9d79cbd69ea 100644 --- a/.gitignore +++ b/.gitignore @@ -93,29 +93,7 @@ lib/perl/lib/Apache/TS.pm iocore/net/test_certlookup iocore/net/test_UDPNet -iocore/net/quic/test_QUICAckFrameCreator -iocore/net/quic/test_QUICAddrVerifyState -iocore/net/quic/test_QUICAltConnectionManager -iocore/net/quic/test_QUICFlowController -iocore/net/quic/test_QUICFrame -iocore/net/quic/test_QUICFrameDispatcher -iocore/net/quic/test_QUICFrameRetransmitter -iocore/net/quic/test_QUICHandshake -iocore/net/quic/test_QUICHandshakeProtocol -iocore/net/quic/test_QUICIncomingFrameBuffer -iocore/net/quic/test_QUICInvariants -iocore/net/quic/test_QUICKeyGenerator -iocore/net/quic/test_QUICLossDetector -iocore/net/quic/test_QUICPacket -iocore/net/quic/test_QUICPacketHeaderProtector -iocore/net/quic/test_QUICPacketFactory -iocore/net/quic/test_QUICStream -iocore/net/quic/test_QUICStreamManager -iocore/net/quic/test_QUICStreamState -iocore/net/quic/test_QUICTransportParameters -iocore/net/quic/test_QUICType -iocore/net/quic/test_QUICTypeUtil -iocore/net/quic/test_QUICVersionNegotiator +iocore/net/quic/test_QUIC* iocore/aio/test_AIO iocore/eventsystem/test_IOBuffer iocore/eventsystem/test_EventSystem diff --git a/iocore/eventsystem/I_Thread.h b/iocore/eventsystem/I_Thread.h index 116463fbc18..2ab995a83ed 100644 --- a/iocore/eventsystem/I_Thread.h +++ b/iocore/eventsystem/I_Thread.h @@ -123,11 +123,9 @@ class Thread ProxyAllocator http2ClientSessionAllocator; ProxyAllocator http2StreamAllocator; ProxyAllocator quicClientSessionAllocator; - ProxyAllocator quicHandshakeAllocator; ProxyAllocator quicBidiStreamAllocator; ProxyAllocator quicSendStreamAllocator; ProxyAllocator quicReceiveStreamAllocator; - ProxyAllocator quicStreamManagerAllocator; ProxyAllocator httpServerSessionAllocator; ProxyAllocator hdrHeapAllocator; ProxyAllocator strHeapAllocator; diff --git a/iocore/net/P_QUICNetVConnection.h b/iocore/net/P_QUICNetVConnection.h index 925a4fed057..d39824e8074 100644 --- a/iocore/net/P_QUICNetVConnection.h +++ b/iocore/net/P_QUICNetVConnection.h @@ -54,14 +54,18 @@ #include "quic/QUICHandshakeProtocol.h" #include "quic/QUICAckFrameCreator.h" #include "quic/QUICPinger.h" +#include "quic/QUICPadder.h" #include "quic/QUICLossDetector.h" #include "quic/QUICStreamManager.h" #include "quic/QUICAltConnectionManager.h" #include "quic/QUICPathValidator.h" +#include "quic/QUICPathManager.h" #include "quic/QUICApplicationMap.h" #include "quic/QUICPacketReceiveQueue.h" #include "quic/QUICAddrVerifyState.h" #include "quic/QUICPacketProtectionKeyInfo.h" +#include "quic/QUICContext.h" +#include "quic/QUICTokenCreator.h" // Size of connection ids for debug log : e.g. aaaaaaaa-bbbbbbbb\0 static constexpr size_t MAX_CIDS_SIZE = 8 + 1 + 8 + 1; @@ -127,11 +131,7 @@ class SSLNextProtocolSet; * WRITE: * Do nothing **/ -class QUICNetVConnection : public UnixNetVConnection, - public QUICConnection, - public QUICFrameGenerator, - public RefCountObj, - public ALPNSupport +class QUICNetVConnection : public UnixNetVConnection, public QUICConnection, public RefCountObj, public ALPNSupport { using super = UnixNetVConnection; ///< Parent type. @@ -145,6 +145,9 @@ class QUICNetVConnection : public UnixNetVConnection, // accept new conn_id int acceptEvent(int event, Event *e); + // NetVConnection + void set_local_addr() override; + // UnixNetVConnection void reenable(VIO *vio) override; VIO *do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf) override; @@ -197,11 +200,6 @@ class QUICNetVConnection : public UnixNetVConnection, std::vector interests() override; QUICConnectionErrorUPtr handle_frame(QUICEncryptionLevel level, const QUICFrame &frame) override; - // QUICFrameGenerator - bool will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) override; - QUICFrame *generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, - ink_hrtime timestamp) override; - int in_closed_queue = 0; bool shouldDestroy(); @@ -231,7 +229,6 @@ class QUICNetVConnection : public UnixNetVConnection, QUICPacketFactory _packet_factory; QUICFrameFactory _frame_factory; QUICAckFrameManager _ack_frame_manager; - QUICPinger _pinger; QUICPacketHeaderProtector _ph_protector; QUICRTTMeasure _rtt_measure; QUICApplicationMap *_application_map = nullptr; @@ -240,6 +237,8 @@ class QUICNetVConnection : public UnixNetVConnection, // TODO: use custom allocator and make them std::unique_ptr or std::shared_ptr // or make them just member variables. + QUICPinger *_pinger = nullptr; + QUICPadder *_padder = nullptr; QUICHandshake *_handshake_handler = nullptr; QUICHandshakeProtocol *_hs_protocol = nullptr; QUICLossDetector *_loss_detector = nullptr; @@ -251,8 +250,10 @@ class QUICNetVConnection : public UnixNetVConnection, QUICConnectionTable *_ctable = nullptr; QUICAltConnectionManager *_alt_con_manager = nullptr; QUICPathValidator *_path_validator = nullptr; + QUICPathManager *_path_manager = nullptr; + QUICTokenCreator *_token_creator = nullptr; - std::vector _frame_generators; + QUICFrameGeneratorManager _frame_generators; QUICPacketReceiveQueue _packet_recv_queue = {this->_packet_factory, this->_ph_protector}; @@ -276,11 +277,6 @@ class QUICNetVConnection : public UnixNetVConnection, void _close_closed_event(Event *data); Event *_closed_event = nullptr; - void _schedule_path_validation_timeout(ink_hrtime interval); - void _unschedule_path_validation_timeout(); - void _close_path_validation_timeout(Event *data); - Event *_path_validation_timeout = nullptr; - void _schedule_ack_manager_periodic(ink_hrtime interval); void _unschedule_ack_manager_periodic(); Event *_ack_manager_periodic = nullptr; @@ -296,7 +292,6 @@ class QUICNetVConnection : public UnixNetVConnection, std::vector &frames); QUICPacketUPtr _packetize_frames(QUICEncryptionLevel level, uint64_t max_packet_size, std::vector &frames); void _packetize_closing_frame(); - Ptr _generate_padding_frame(size_t frame_size); QUICPacketUPtr _build_packet(QUICEncryptionLevel level, Ptr parent_block, bool retransmittable, bool probing, bool crypto); @@ -324,7 +319,7 @@ class QUICNetVConnection : public UnixNetVConnection, const std::shared_ptr &remote_tp); void _handle_error(QUICConnectionErrorUPtr error); QUICPacketUPtr _dequeue_recv_packet(QUICPacketCreationResult &result); - void _validate_new_path(); + void _validate_new_path(const QUICPath &path); int _complete_handshake_if_possible(); void _switch_to_handshake_state(); @@ -337,7 +332,6 @@ class QUICNetVConnection : public UnixNetVConnection, void _start_application(); void _handle_periodic_ack_event(); - void _handle_path_validation_timeout(Event *data); void _handle_idle_timeout(); QUICConnectionErrorUPtr _handle_frame(const QUICNewConnectionIdFrame &frame); @@ -352,19 +346,16 @@ class QUICNetVConnection : public UnixNetVConnection, QUICPacketUPtr _the_final_packet = QUICPacketFactory::create_null_packet(); QUICStatelessResetToken _reset_token; - ats_unique_buf _av_token = {nullptr}; - size_t _av_token_len = 0; - bool _is_resumption_token_sent = false; + ats_unique_buf _av_token = {nullptr}; + size_t _av_token_len = 0; uint64_t _stream_frames_sent = 0; + uint32_t _seq_num = 0; // TODO: Source addresses verification through an address validation token - bool _has_ack_eliciting_packet_out = true; - QUICAddrVerifyState _verfied_state; - // QUICFrameGenerator - void _on_frame_lost(QUICFrameInformationUPtr &info) override; + std::unique_ptr _context; }; typedef int (QUICNetVConnection::*QUICNetVConnHandler)(int, void *); diff --git a/iocore/net/QUICNetVConnection.cc b/iocore/net/QUICNetVConnection.cc index 7070727e72b..22d2e61cec4 100644 --- a/iocore/net/QUICNetVConnection.cc +++ b/iocore/net/QUICNetVConnection.cc @@ -64,7 +64,7 @@ static constexpr uint32_t MINIMUM_INITIAL_PACKET_SIZE = 1200; static constexpr ink_hrtime WRITE_READY_INTERVAL = HRTIME_MSECONDS(2); static constexpr uint32_t PACKET_PER_EVENT = 256; static constexpr uint32_t MAX_CONSECUTIVE_STREAMS = 8; ///< Interrupt sending STREAM frames to send ACK frame -static constexpr uint32_t MIN_PKT_PAYLOAD_LEN = 3; ///< Minimum payload length for sampling for header protection +// static constexpr uint32_t MIN_PKT_PAYLOAD_LEN = 3; ///< Minimum payload length for sampling for header protection static constexpr uint32_t STATE_CLOSING_MAX_SEND_PKT_NUM = 8; ///< Max number of sending packets which contain a closing frame. static constexpr uint32_t STATE_CLOSING_MAX_RECV_PKT_WIND = 1 << STATE_CLOSING_MAX_SEND_PKT_NUM; @@ -178,81 +178,19 @@ class QUICTPConfigQCP : public QUICTPConfig } } -private: - const QUICConfigParams *_params; - NetVConnectionContext_t _ctx; -}; - -class QUICCCConfigQCP : public QUICCCConfig -{ -public: - QUICCCConfigQCP(const QUICConfigParams *params) : _params(params) {} - - uint32_t - max_datagram_size() const override - { - return this->_params->cc_max_datagram_size(); - } - - uint32_t - initial_window() const override - { - return this->_params->cc_initial_window(); - } - - uint32_t - minimum_window() const override - { - return this->_params->cc_minimum_window(); - } - - float - loss_reduction_factor() const override - { - return this->_params->cc_loss_reduction_factor(); - } - - uint32_t - persistent_congestion_threshold() const override - { - return this->_params->cc_persistent_congestion_threshold(); - } - -private: - const QUICConfigParams *_params; -}; - -class QUICLDConfigQCP : public QUICLDConfig -{ -public: - QUICLDConfigQCP(const QUICConfigParams *params) : _params(params) {} - - uint32_t - packet_threshold() const override - { - return this->_params->ld_packet_threshold(); - } - - float - time_threshold() const override - { - return this->_params->ld_time_threshold(); - } - - ink_hrtime - granularity() const override - { - return this->_params->ld_granularity(); - } - - ink_hrtime - initial_rtt() const override + uint8_t + active_cid_limit() const override { - return this->_params->ld_initial_rtt(); + if (this->_ctx == NET_VCONNECTION_IN) { + return this->_params->active_cid_limit_in(); + } else { + return this->_params->active_cid_limit_out(); + } } private: const QUICConfigParams *_params; + NetVConnectionContext_t _ctx; }; QUICNetVConnection::QUICNetVConnection() : _packet_factory(this->_pp_key_info), _ph_protector(this->_pp_key_info) {} @@ -263,7 +201,6 @@ QUICNetVConnection::~QUICNetVConnection() this->_unschedule_packet_write_ready(); this->_unschedule_closing_timeout(); this->_unschedule_closed_event(); - this->_unschedule_path_validation_timeout(); } // XXX This might be called on ET_UDP thread @@ -419,8 +356,9 @@ void QUICNetVConnection::start() { ink_release_assert(this->thread != nullptr); - + this->_context = std::make_unique(&this->_rtt_measure, this, &this->_pp_key_info); this->_five_tuple.update(this->local_addr, this->remote_addr, SOCK_DGRAM); + QUICPath trusted_path = {{}, {}}; // Version 0x00000001 uses stream 0 for cryptographic handshake with TLS 1.3, but newer version may not if (this->direction() == NET_VCONNECTION_IN) { QUICCertConfig::scoped_config server_cert; @@ -434,6 +372,7 @@ QUICNetVConnection::start() this->_ack_frame_manager.set_max_ack_delay(this->_quic_config->max_ack_delay_in()); this->_schedule_ack_manager_periodic(this->_quic_config->max_ack_delay_in()); } else { + trusted_path = {this->local_addr, this->remote_addr}; QUICTPConfigQCP tp_config(this->_quic_config, NET_VCONNECTION_OUT); this->_pp_key_info.set_context(QUICPacketProtectionKeyInfo::Context::CLIENT); this->_ack_frame_manager.set_ack_delay_exponent(this->_quic_config->ack_delay_exponent_out()); @@ -450,27 +389,47 @@ QUICNetVConnection::start() this->_frame_dispatcher = new QUICFrameDispatcher(this); // Create frame handlers - QUICCCConfigQCP cc_config(this->_quic_config); - QUICLDConfigQCP ld_config(this->_quic_config); - this->_rtt_measure.init(ld_config); - this->_congestion_controller = new QUICCongestionController(this->_rtt_measure, this, cc_config); - this->_loss_detector = new QUICLossDetector(this, this->_congestion_controller, &this->_rtt_measure, ld_config); + this->_pinger = new QUICPinger(); + this->_padder = new QUICPadder(this->netvc_context); + this->_rtt_measure.init(this->_context->ld_config()); + this->_congestion_controller = new QUICNewRenoCongestionController(*_context); + this->_loss_detector = + new QUICLossDetector(*_context, this->_congestion_controller, &this->_rtt_measure, this->_pinger, this->_padder); this->_frame_dispatcher->add_handler(this->_loss_detector); this->_remote_flow_controller = new QUICRemoteConnectionFlowController(UINT64_MAX); this->_local_flow_controller = new QUICLocalConnectionFlowController(&this->_rtt_measure, UINT64_MAX); - this->_path_validator = new QUICPathValidator(); + this->_path_validator = new QUICPathValidator(*this, [this](bool succeeded) { + if (succeeded) { + this->_alt_con_manager->drop_cid(this->_peer_old_quic_connection_id); + // FIXME This is a kind of workaround for connection migration. + // This PING make peer to send an ACK frame so that ATS can detect packet loss. + // It would be better if QUICLossDetector could detect the loss in another way. + this->ping(); + } + }); this->_stream_manager = new QUICStreamManager(this, &this->_rtt_measure, this->_application_map); + this->_path_manager = new QUICPathManager(*this, *this->_path_validator); + this->_path_manager->set_trusted_path(trusted_path); + this->_token_creator = new QUICTokenCreator(this->_context.get()); + + static constexpr int QUIC_STREAM_MANAGER_WEIGHT = QUICFrameGeneratorWeight::AFTER_DATA - 1; + static constexpr int QUIC_PINGER_WEIGHT = QUICFrameGeneratorWeight::LATE + 1; + static constexpr int QUIC_PADDER_WEIGHT = QUICFrameGeneratorWeight::LATE + 2; // Register frame generators - this->_frame_generators.push_back(this->_handshake_handler); // CRYPTO - this->_frame_generators.push_back(this->_path_validator); // PATH_CHALLENGE, PATH_RESPOSNE - this->_frame_generators.push_back(this->_local_flow_controller); // MAX_DATA - this->_frame_generators.push_back(this->_remote_flow_controller); // DATA_BLOCKED - this->_frame_generators.push_back(this); // NEW_TOKEN - this->_frame_generators.push_back(this->_stream_manager); // STREAM, MAX_STREAM_DATA, STREAM_DATA_BLOCKED - this->_frame_generators.push_back(&this->_ack_frame_manager); // ACK - this->_frame_generators.push_back(&this->_pinger); // PING + this->_frame_generators.add_generator(*this->_handshake_handler, QUICFrameGeneratorWeight::EARLY); // CRYPTO + this->_frame_generators.add_generator(*this->_path_validator, QUICFrameGeneratorWeight::EARLY); // PATH_CHALLENGE, PATH_RESPOSNE + this->_frame_generators.add_generator(*this->_local_flow_controller, QUICFrameGeneratorWeight::BEFORE_DATA); // MAX_DATA + this->_frame_generators.add_generator(*this->_remote_flow_controller, QUICFrameGeneratorWeight::BEFORE_DATA); // DATA_BLOCKED + this->_frame_generators.add_generator(*this->_token_creator, QUICFrameGeneratorWeight::BEFORE_DATA); // NEW_TOKEN + this->_frame_generators.add_generator(*this->_stream_manager, + QUIC_STREAM_MANAGER_WEIGHT); // STREAM, MAX_STREAM_DATA, STREAM_DATA_BLOCKED + this->_frame_generators.add_generator(this->_ack_frame_manager, QUICFrameGeneratorWeight::BEFORE_DATA); // ACK + + this->_frame_generators.add_generator(*this->_pinger, QUIC_PINGER_WEIGHT); // PING + // Warning: padder should be tail of the frame generators + this->_frame_generators.add_generator(*this->_padder, QUIC_PADDER_WEIGHT); // PADDING // Register frame handlers this->_frame_dispatcher->add_handler(this); @@ -541,6 +500,13 @@ QUICNetVConnection::destroy(EThread *t) */ } +void +QUICNetVConnection::set_local_addr() +{ + int local_sa_size = sizeof(local_addr); + ATS_UNUSED_RETURN(safe_getsockname(this->_udp_con->getFd(), &local_addr.sa, &local_sa_size)); +} + void QUICNetVConnection::reenable(VIO *vio) { @@ -566,6 +532,9 @@ QUICNetVConnection::connectUp(EThread *t, int fd) // FIXME: complete do_io_xxxx instead this->read.enabled = 1; + this->set_local_addr(); + this->remote_addr = con.addr; + this->start(); // start QUIC handshake @@ -672,7 +641,7 @@ QUICNetVConnection::handle_received_packet(UDPPacket *packet) void QUICNetVConnection::ping() { - this->_pinger.request(QUICEncryptionLevel::ONE_RTT); + this->_pinger->request(); } void @@ -808,9 +777,6 @@ QUICNetVConnection::state_handshake(int event, Event *data) // Reschedule WRITE_READY this->_schedule_packet_write_ready(true); break; - case QUIC_EVENT_PATH_VALIDATION_TIMEOUT: - this->_handle_path_validation_timeout(data); - break; case VC_EVENT_INACTIVITY_TIMEOUT: // Start Immediate Close because of Idle Timeout this->_handle_idle_timeout(); @@ -844,9 +810,6 @@ QUICNetVConnection::state_connection_established(int event, Event *data) // Reschedule WRITE_READY this->_schedule_packet_write_ready(true); break; - case QUIC_EVENT_PATH_VALIDATION_TIMEOUT: - this->_handle_path_validation_timeout(data); - break; case VC_EVENT_INACTIVITY_TIMEOUT: // Start Immediate Close because of Idle Timeout this->_handle_idle_timeout(); @@ -877,9 +840,6 @@ QUICNetVConnection::state_connection_closing(int event, Event *data) this->_close_packet_write_ready(data); this->_state_closing_send_packet(); break; - case QUIC_EVENT_PATH_VALIDATION_TIMEOUT: - this->_handle_path_validation_timeout(data); - break; case QUIC_EVENT_CLOSING_TIMEOUT: this->_close_closing_timeout(data); this->_switch_to_close_state(); @@ -908,9 +868,6 @@ QUICNetVConnection::state_connection_draining(int event, Event *data) // This should be the only difference between this and closing_state. this->_close_packet_write_ready(data); break; - case QUIC_EVENT_PATH_VALIDATION_TIMEOUT: - this->_handle_path_validation_timeout(data); - break; case QUIC_EVENT_CLOSING_TIMEOUT: this->_close_closing_timeout(data); this->_switch_to_close_state(); @@ -933,7 +890,6 @@ QUICNetVConnection::state_connection_closed(int event, Event *data) this->_unschedule_ack_manager_periodic(); this->_unschedule_packet_write_ready(); this->_unschedule_closing_timeout(); - this->_unschedule_path_validation_timeout(); this->_close_closed_event(data); this->next_inactivity_timeout_at = 0; this->next_activity_timeout_at = 0; @@ -1139,12 +1095,16 @@ QUICNetVConnection::_state_handshake_process_initial_packet(const QUICPacket &pa // Start handshake if (this->netvc_context == NET_VCONNECTION_IN) { + this->local_addr.sa = packet.to().sa; + this->remote_addr.sa = packet.from().sa; + this->_five_tuple.update(this->local_addr, this->remote_addr, SOCK_DGRAM); + if (!this->_alt_con_manager) { this->_alt_con_manager = new QUICAltConnectionManager(this, *this->_ctable, this->_peer_quic_connection_id, this->_quic_config->instance_id(), - this->_quic_config->num_alt_connection_ids(), this->_quic_config->preferred_address_ipv4(), + this->_quic_config->active_cid_limit_in(), this->_quic_config->preferred_address_ipv4(), this->_quic_config->preferred_address_ipv6()); - this->_frame_generators.push_back(this->_alt_con_manager); + this->_frame_generators.add_generator(*this->_alt_con_manager, QUICFrameGeneratorWeight::EARLY); this->_frame_dispatcher->add_handler(this->_alt_con_manager); } QUICTPConfigQCP tp_config(this->_quic_config, NET_VCONNECTION_IN); @@ -1159,6 +1119,14 @@ QUICNetVConnection::_state_handshake_process_initial_packet(const QUICPacket &pa } } } else { + if (!this->_alt_con_manager) { + this->_alt_con_manager = + new QUICAltConnectionManager(this, *this->_ctable, this->_peer_quic_connection_id, this->_quic_config->instance_id(), + this->_quic_config->active_cid_limit_out()); + this->_frame_generators.add_generator(*this->_alt_con_manager, QUICFrameGeneratorWeight::BEFORE_DATA); + this->_frame_dispatcher->add_handler(this->_alt_con_manager); + } + // on client side, _handshake_handler is already started. Just process packet like _state_handshake_process_handshake_packet() error = this->_recv_and_ack(packet); } @@ -1184,6 +1152,8 @@ QUICNetVConnection::_state_handshake_process_retry_packet(const QUICPacket &pack this->_av_token = ats_unique_malloc(this->_av_token_len); memcpy(this->_av_token.get(), packet.payload(), this->_av_token_len); + this->_padder->set_av_token_len(this->_av_token_len); + // discard all transport state this->_handshake_handler->reset(); this->_packet_factory.reset(); @@ -1366,7 +1336,7 @@ QUICNetVConnection::_state_common_send_packet() uint32_t packet_count = 0; uint32_t error = 0; while (error == 0 && packet_count < PACKET_PER_EVENT) { - uint32_t window = this->_congestion_controller->open_window(); + uint32_t window = this->_congestion_controller->credit(); if (window == 0) { break; @@ -1418,7 +1388,9 @@ QUICNetVConnection::_state_common_send_packet() written += len; int dcil = (this->_peer_quic_connection_id == QUICConnectionId::ZERO()) ? 0 : this->_peer_quic_connection_id.length(); - this->_ph_protector.protect(buf, len, dcil); + if (!this->_ph_protector.protect(buf, len, dcil)) { + ink_assert(!"failed to protect buffer"); + } QUICConDebug("[TX] %s packet #%" PRIu64 " size=%zu", QUICDebugNames::packet_type(packet->type()), packet->packet_number(), len); @@ -1507,25 +1479,9 @@ QUICNetVConnection::_store_frame(Ptr parent_block, size_t &size_a return parent_block; } -// FIXME QUICNetVConnection should not know the actual type value of PADDING frame -Ptr -QUICNetVConnection::_generate_padding_frame(size_t frame_size) -{ - Ptr block = make_ptr(new_IOBufferBlock()); - block->alloc(iobuffer_size_to_index(frame_size)); - memset(block->start(), 0, frame_size); - block->fill(frame_size); - - ink_assert(frame_size == static_cast(block->size())); - - return block; -} - QUICPacketUPtr QUICNetVConnection::_packetize_frames(QUICEncryptionLevel level, uint64_t max_packet_size, std::vector &frames) { - ink_hrtime timestamp = Thread::get_hrtime(); - QUICPacketUPtr packet = QUICPacketFactory::create_null_packet(); if (max_packet_size <= MAX_PACKET_OVERHEAD) { return packet; @@ -1546,30 +1502,43 @@ QUICNetVConnection::_packetize_frames(QUICEncryptionLevel level, uint64_t max_pa first_block->alloc(iobuffer_size_to_index(0)); first_block->fill(0); - if (!this->_has_ack_eliciting_packet_out) { - // Sent too much ack_only packet. At this moment we need to packetize a ping frame - // to force peer send ack frame. - this->_pinger.request(level); - } - + uint32_t seq_num = this->_seq_num++; size_t size_added = 0; bool ack_eliciting = false; bool crypto = false; uint8_t frame_instance_buffer[QUICFrame::MAX_INSTANCE_SIZE]; // This is for a frame instance but not serialized frame data QUICFrame *frame = nullptr; - for (auto g : this->_frame_generators) { - while (g->will_generate_frame(level, timestamp)) { + for (auto g : this->_frame_generators.generators()) { + // a non-ack_eliciting packet is ready, but we can not send continuous two ack_eliciting packets. + while (g->will_generate_frame(level, len, ack_eliciting, seq_num)) { // FIXME will_generate_frame should receive more parameters so we don't need extra checks - if (g == this->_remote_flow_controller && !this->_stream_manager->will_generate_frame(level, timestamp)) { + if (g == this->_remote_flow_controller && !this->_stream_manager->will_generate_frame(level, len, ack_eliciting, seq_num)) { break; } - if (g == this->_stream_manager && this->_path_validator->is_validating()) { - break; + + if (g == this->_stream_manager) { + // Don't send DATA frames if current path is not validated + // FIXME will_generate_frame should receive more parameters so we don't need extra checks + if (auto path = this->_path_manager->get_verified_path(); !path.remote_ep().isValid()) { + break; + } } // Common block - frame = g->generate_frame(frame_instance_buffer, level, this->_remote_flow_controller->credit(), max_frame_size, timestamp); + frame = + g->generate_frame(frame_instance_buffer, level, this->_remote_flow_controller->credit(), max_frame_size, len, seq_num); if (frame) { + // Some frame types must not be sent on Initial and Handshake packets + switch (auto t = frame->type(); level) { + case QUICEncryptionLevel::INITIAL: + case QUICEncryptionLevel::HANDSHAKE: + ink_assert(t == QUICFrameType::CRYPTO || t == QUICFrameType::ACK || t == QUICFrameType::PADDING || + t == QUICFrameType::CONNECTION_CLOSE); + break; + default: + break; + } + ++frame_count; probing |= frame->is_probing_frame(); if (frame->is_flow_controlled()) { @@ -1588,13 +1557,11 @@ QUICNetVConnection::_packetize_frames(QUICEncryptionLevel level, uint64_t max_pa } } - if (!ack_eliciting && frame->type() != QUICFrameType::ACK) { + if (!ack_eliciting && frame->ack_eliciting()) { ack_eliciting = true; - this->_pinger.cancel(level); } - if (frame->type() == QUICFrameType::CRYPTO && - (level == QUICEncryptionLevel::INITIAL || level == QUICEncryptionLevel::HANDSHAKE)) { + if (frame->type() == QUICFrameType::CRYPTO && frame->ack_eliciting()) { crypto = true; } @@ -1608,31 +1575,8 @@ QUICNetVConnection::_packetize_frames(QUICEncryptionLevel level, uint64_t max_pa // Schedule a packet if (len != 0) { - if (level == QUICEncryptionLevel::INITIAL && this->netvc_context == NET_VCONNECTION_OUT) { - // Pad with PADDING frames - uint64_t min_size = this->_minimum_quic_packet_size(); - if (this->_av_token) { - min_size = min_size - this->_av_token_len; - } - min_size = std::min(min_size, max_packet_size); - - if (min_size > len) { - Ptr pad_block = _generate_padding_frame(min_size - len); - last_block->next = pad_block; - len += pad_block->size(); - } - } else { - // Pad with PADDING frames to make sure payload length satisfy the minimum length for sampling for header protection - if (MIN_PKT_PAYLOAD_LEN > len) { - Ptr pad_block = _generate_padding_frame(MIN_PKT_PAYLOAD_LEN - len); - last_block->next = pad_block; - len += pad_block->size(); - } - } - // Packet is retransmittable if it's not ack only packet - packet = this->_build_packet(level, first_block, ack_eliciting, probing, crypto); - this->_has_ack_eliciting_packet_out = ack_eliciting; + packet = this->_build_packet(level, first_block, ack_eliciting, probing, crypto); } return packet; @@ -1683,7 +1627,8 @@ QUICNetVConnection::_recv_and_ack(const QUICPacket &packet, bool *has_non_probin *has_non_probing_frame = false; } - error = this->_frame_dispatcher->receive_frames(level, payload, size, ack_only, is_flow_controlled, has_non_probing_frame); + error = + this->_frame_dispatcher->receive_frames(level, payload, size, ack_only, is_flow_controlled, has_non_probing_frame, &packet); if (error != nullptr) { return error; } @@ -1986,33 +1931,6 @@ QUICNetVConnection::_complete_handshake_if_possible() return 0; } -void -QUICNetVConnection::_schedule_path_validation_timeout(ink_hrtime interval) -{ - if (!this->_path_validation_timeout) { - QUICConDebug("Schedule %s event in %" PRIu64 "ms", QUICDebugNames::quic_event(QUIC_EVENT_PATH_VALIDATION_TIMEOUT), - interval / HRTIME_MSECOND); - this->_path_validation_timeout = this->thread->schedule_in_local(this, interval, QUIC_EVENT_PATH_VALIDATION_TIMEOUT); - } -} - -void -QUICNetVConnection::_unschedule_path_validation_timeout() -{ - if (this->_path_validation_timeout) { - QUICConDebug("Unschedule %s event", QUICDebugNames::quic_event(QUIC_EVENT_PATH_VALIDATION_TIMEOUT)); - this->_path_validation_timeout->cancel(); - this->_path_validation_timeout = nullptr; - } -} - -void -QUICNetVConnection::_close_path_validation_timeout(Event *data) -{ - ink_assert(this->_path_validation_timeout == data); - this->_path_validation_timeout = nullptr; -} - void QUICNetVConnection::_start_application() { @@ -2029,7 +1947,7 @@ QUICNetVConnection::_start_application() if (netvc_context == NET_VCONNECTION_IN) { if (!this->setSelectedProtocol(app_name, app_name_len)) { - this->_handle_error(std::make_unique(QUICTransErrorCode::VERSION_NEGOTIATION_ERROR)); + this->_handle_error(std::make_unique(QUICTransErrorCode::PROTOCOL_VIOLATION)); } else { this->endpoint()->handleEvent(NET_EVENT_ACCEPT, this); } @@ -2055,15 +1973,22 @@ QUICNetVConnection::_switch_to_established_state() SET_HANDLER((NetVConnHandler)&QUICNetVConnection::state_connection_established); + std::shared_ptr remote_tp = this->_handshake_handler->remote_transport_parameters(); + + uint64_t active_cid_limit = remote_tp->getAsUInt(QUICTransportParameterId::ACTIVE_CONNECTION_ID_LIMIT); + if (active_cid_limit) { + this->_alt_con_manager->set_remote_active_cid_limit(active_cid_limit); + } + if (this->direction() == NET_VCONNECTION_OUT) { - std::shared_ptr remote_tp = this->_handshake_handler->remote_transport_parameters(); - const uint8_t *pref_addr_buf; uint16_t len; - pref_addr_buf = remote_tp->getAsBytes(QUICTransportParameterId::PREFERRED_ADDRESS, len); - this->_alt_con_manager = new QUICAltConnectionManager(this, *this->_ctable, this->_peer_quic_connection_id, - this->_quic_config->instance_id(), 1, {pref_addr_buf, len}); - this->_frame_generators.push_back(this->_alt_con_manager); - this->_frame_dispatcher->add_handler(this->_alt_con_manager); + const uint8_t *pref_addr_buf = remote_tp->getAsBytes(QUICTransportParameterId::PREFERRED_ADDRESS, len); + if (pref_addr_buf) { + this->_alt_con_manager->set_remote_preferred_address({pref_addr_buf, len}); + } + } else { + QUICPath trusted_path = {this->local_addr, this->remote_addr}; + this->_path_manager->set_trusted_path(trusted_path); } } else { // Illegal state change @@ -2135,7 +2060,6 @@ void QUICNetVConnection::_switch_to_close_state() { this->_unschedule_closing_timeout(); - this->_unschedule_path_validation_timeout(); if (this->_complete_handshake_if_possible() != 0) { QUICConDebug("Switching state without handshake completion"); @@ -2155,13 +2079,12 @@ QUICNetVConnection::_handle_idle_timeout() } void -QUICNetVConnection::_validate_new_path() +QUICNetVConnection::_validate_new_path(const QUICPath &path) { - this->_path_validator->validate(); // Not sure how long we should wait. The spec says just "enough time". // Use the same time amount as the closing timeout. ink_hrtime rto = this->_rtt_measure.current_pto_period(); - this->_schedule_path_validation_timeout(3 * rto); + this->_path_manager->open_new_path(path, 3 * rto); } void @@ -2253,6 +2176,7 @@ QUICNetVConnection::_state_connection_established_migrate_connection(const QUICP } if (this->connection_id() == dcid) { + QUICConDebug("Maybe NAT rebinding"); // On client side (NET_VCONNECTION_OUT), nothing to do any more if (this->netvc_context == NET_VCONNECTION_IN) { Connection con; @@ -2260,9 +2184,12 @@ QUICNetVConnection::_state_connection_established_migrate_connection(const QUICP this->con.move(con); this->set_remote_addr(); this->_udp_con = p.udp_con(); - this->_validate_new_path(); + + QUICPath new_path = {p.to(), p.from()}; + this->_validate_new_path(new_path); } } else { + QUICConDebug("Different CID"); if (this->_alt_con_manager->migrate_to(dcid, this->_reset_token)) { // DCID of received packet is local cid this->_update_local_cid(dcid); @@ -2276,7 +2203,9 @@ QUICNetVConnection::_state_connection_established_migrate_connection(const QUICP this->_udp_con = p.udp_con(); this->_update_peer_cid(this->_alt_con_manager->migrate_to_alt_cid()); - this->_validate_new_path(); + + QUICPath new_path = {this->local_addr, con.addr}; + this->_validate_new_path(new_path); } } else { char dcid_str[QUICConnectionId::MAX_HEX_STR_LENGTH]; @@ -2298,13 +2227,12 @@ QUICNetVConnection::_state_connection_established_initiate_connection_migration( ink_assert(this->netvc_context == NET_VCONNECTION_OUT); QUICConnectionErrorUPtr error = nullptr; - ink_hrtime timestamp = Thread::get_hrtime(); std::shared_ptr remote_tp = this->_handshake_handler->remote_transport_parameters(); - if (this->_connection_migration_initiated || remote_tp->contains(QUICTransportParameterId::DISABLE_MIGRATION) || + if (this->_connection_migration_initiated || remote_tp->contains(QUICTransportParameterId::DISABLE_ACTIVE_MIGRATION) || !this->_alt_con_manager->is_ready_to_migrate() || - this->_alt_con_manager->will_generate_frame(QUICEncryptionLevel::ONE_RTT, timestamp)) { + this->_alt_con_manager->will_generate_frame(QUICEncryptionLevel::ONE_RTT, 0, true, this->_seq_num++)) { return error; } @@ -2313,7 +2241,9 @@ QUICNetVConnection::_state_connection_established_initiate_connection_migration( this->_update_peer_cid(this->_alt_con_manager->migrate_to_alt_cid()); - this->_validate_new_path(); + auto current_path = this->_path_manager->get_verified_path(); + QUICPath new_path = {current_path.local_ep(), current_path.remote_ep()}; + this->_validate_new_path(new_path); return error; } @@ -2321,10 +2251,9 @@ QUICNetVConnection::_state_connection_established_initiate_connection_migration( void QUICNetVConnection::_handle_periodic_ack_event() { - ink_hrtime timestamp = Thread::get_hrtime(); - bool need_schedule = false; + bool need_schedule = false; for (int i = static_cast(this->_minimum_encryption_level); i <= static_cast(QUICEncryptionLevel::ONE_RTT); ++i) { - if (this->_ack_frame_manager.will_generate_frame(QUIC_ENCRYPTION_LEVELS[i], timestamp)) { + if (this->_ack_frame_manager.will_generate_frame(QUIC_ENCRYPTION_LEVELS[i], 0, true, this->_seq_num++)) { need_schedule = true; break; } @@ -2336,68 +2265,3 @@ QUICNetVConnection::_handle_periodic_ack_event() this->_schedule_packet_write_ready(); } } - -void -QUICNetVConnection::_handle_path_validation_timeout(Event *data) -{ - this->_close_path_validation_timeout(data); - if (this->_path_validator->is_validated()) { - QUICConDebug("Path validated"); - this->_alt_con_manager->drop_cid(this->_peer_old_quic_connection_id); - // FIXME This is a kind of workaround for connection migration. - // This PING make peer to send an ACK frame so that ATS can detect packet loss. - // It would be better if QUICLossDetector could detect the loss in another way. - this->ping(); - } else { - QUICConDebug("Path validation failed"); - this->_switch_to_close_state(); - } -} - -// QUICFrameGenerator -bool -QUICNetVConnection::will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) -{ - if (!this->_is_level_matched(level)) { - return false; - } - - return !this->_is_resumption_token_sent; -} - -QUICFrame * -QUICNetVConnection::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, - ink_hrtime timestamp) -{ - QUICFrame *frame = nullptr; - - if (!this->_is_level_matched(level)) { - return frame; - } - - if (this->_is_resumption_token_sent) { - return frame; - } - - if (this->direction() == NET_VCONNECTION_IN) { - // TODO Make expiration period configurable - QUICResumptionToken token(this->get_remote_endpoint(), this->connection_id(), Thread::get_hrtime() + HRTIME_HOURS(24)); - frame = QUICFrameFactory::create_new_token_frame(buf, token, this->_issue_frame_id(), this); - if (frame) { - if (frame->size() < maximum_frame_size) { - this->_is_resumption_token_sent = true; - } else { - // Cancel generating frame - frame = nullptr; - } - } - } - - return frame; -} - -void -QUICNetVConnection::_on_frame_lost(QUICFrameInformationUPtr &info) -{ - this->_is_resumption_token_sent = false; -} diff --git a/iocore/net/QUICPacketHandler.cc b/iocore/net/QUICPacketHandler.cc index fc906b2d366..230acbb7dda 100644 --- a/iocore/net/QUICPacketHandler.cc +++ b/iocore/net/QUICPacketHandler.cc @@ -30,8 +30,7 @@ #include "QUICDebugNames.h" #include "QUICEvents.h" -static constexpr int LONG_HDR_OFFSET_CONNECTION_ID = 6; -static constexpr char debug_tag[] = "quic_sec"; +static constexpr char debug_tag[] = "quic_sec"; #define QUICDebug(fmt, ...) Debug(debug_tag, fmt, ##__VA_ARGS__) #define QUICDebugQC(qc, fmt, ...) Debug(debug_tag, "[%s] " fmt, qc->cids().data(), ##__VA_ARGS__) @@ -381,9 +380,10 @@ QUICPacketHandlerIn::_stateless_retry(const uint8_t *buf, uint64_t buf_len, UDPC } // TODO: refine packet parsers in here, QUICPacketLongHeader, and QUICPacketReceiveQueue - size_t token_length = 0; - uint8_t token_length_field_len = 0; - if (!QUICPacketLongHeader::token_length(token_length, &token_length_field_len, buf, buf_len)) { + size_t token_length = 0; + uint8_t token_length_field_len = 0; + size_t token_length_field_offset = 0; + if (!QUICPacketLongHeader::token_length(token_length, token_length_field_len, token_length_field_offset, buf, buf_len)) { return -1; } @@ -393,19 +393,18 @@ QUICPacketHandlerIn::_stateless_retry(const uint8_t *buf, uint64_t buf_len, UDPC local_cid.randomize(); QUICPacketUPtr retry_packet = QUICPacketFactory::create_retry_packet(scid, local_cid, dcid, token); + QUICDebug("[TX] %s packet ODCID=%" PRIx64, QUICDebugNames::packet_type(retry_packet->type()), + static_cast(static_cast(retry_packet->header()).original_dcid())); this->_send_packet(*retry_packet, connection, from, 1200, nullptr, 0); return -2; } else { - uint8_t dcil, scil; - QUICPacketLongHeader::dcil(dcil, buf, buf_len); - QUICPacketLongHeader::scil(scil, buf, buf_len); - const uint8_t *token = buf + LONG_HDR_OFFSET_CONNECTION_ID + dcil + scil + token_length_field_len; - - if (QUICAddressValidationToken::type(token) == QUICAddressValidationToken::Type::RETRY) { - QUICRetryToken token1(token, token_length); - if (token1.is_valid(from)) { - *original_cid = token1.original_dcid(); + size_t token_offset = token_length_field_offset + token_length_field_len; + + if (QUICAddressValidationToken::type(buf + token_offset) == QUICAddressValidationToken::Type::RETRY) { + QUICRetryToken token(buf + token_offset, token_length); + if (token.is_valid(from)) { + *original_cid = token.original_dcid(); return 0; } else { return -3; diff --git a/iocore/net/quic/Makefile.am b/iocore/net/quic/Makefile.am index e13d1de2a93..73c4e5f486e 100644 --- a/iocore/net/quic/Makefile.am +++ b/iocore/net/quic/Makefile.am @@ -56,7 +56,7 @@ libquic_a_SOURCES = \ QUICVersionNegotiator.cc \ QUICLossDetector.cc \ QUICStreamManager.cc \ - QUICCongestionController.cc \ + QUICNewRenoCongestionController.cc \ QUICFlowController.cc \ QUICStreamState.cc \ QUICStream.cc \ @@ -82,6 +82,7 @@ libquic_a_SOURCES = \ QUICApplicationMap.cc \ QUICIncomingFrameBuffer.cc \ QUICPacketReceiveQueue.cc \ + QUICPathManager.cc \ QUICPathValidator.cc \ QUICPinger.cc \ QUICFrameGenerator.cc \ @@ -90,7 +91,10 @@ libquic_a_SOURCES = \ QUICBidirectionalStream.cc \ QUICCryptoStream.cc \ QUICUnidirectionalStream.cc \ - QUICStreamFactory.cc + QUICStreamFactory.cc \ + QUICPadder.cc \ + QUICContext.cc \ + QUICTokenCreator.cc # # Check Programs @@ -109,6 +113,7 @@ check_PROGRAMS = \ test_QUICPacket \ test_QUICPacketHeaderProtector \ test_QUICPacketFactory \ + test_QUICPathValidator \ test_QUICStream \ test_QUICStreamManager \ test_QUICStreamState \ @@ -117,7 +122,8 @@ check_PROGRAMS = \ test_QUICTypeUtil \ test_QUICVersionNegotiator \ test_QUICFrameRetransmitter \ - test_QUICAddrVerifyState + test_QUICAddrVerifyState \ + test_QUICPinger TESTS = $(check_PROGRAMS) @@ -226,6 +232,13 @@ test_QUICPacketFactory_SOURCES = \ $(test_main_SOURCES) \ ./test/test_QUICPacketFactory.cc +test_QUICPathValidator_CPPFLAGS = $(test_CPPFLAGS) +test_QUICPathValidator_LDFLAGS = @AM_LDFLAGS@ +test_QUICPathValidator_LDADD = $(test_LDADD) +test_QUICPathValidator_SOURCES = \ + $(test_main_SOURCES) \ + ./test/test_QUICPathValidator.cc + test_QUICPacketHeaderProtector_CPPFLAGS = $(test_CPPFLAGS) test_QUICPacketHeaderProtector_LDFLAGS = @AM_LDFLAGS@ test_QUICPacketHeaderProtector_LDADD = $(test_LDADD) @@ -296,6 +309,13 @@ test_QUICAddrVerifyState_SOURCES = \ $(test_main_SOURCES) \ ./test/test_QUICAddrVerifyState.cc +test_QUICPinger_CPPFLAGS = $(test_CPPFLAGS) +test_QUICPinger_LDFLAGS = @AM_LDFLAGS@ +test_QUICPinger_LDADD = $(test_LDADD) +test_QUICPinger_SOURCES = \ + $(test_main_SOURCES) \ + ./test/test_QUICPinger.cc + # # clang-tidy # diff --git a/iocore/net/quic/Mock.h b/iocore/net/quic/Mock.h index d4692b05d43..535dff56b46 100644 --- a/iocore/net/quic/Mock.h +++ b/iocore/net/quic/Mock.h @@ -30,13 +30,147 @@ #include "QUICLossDetector.h" #include "QUICEvents.h" +class MockQUICContext; + using namespace std::literals; -std::string_view negotiated_application_name_sv = "h3-20"sv; +std::string_view negotiated_application_name_sv = "h3-23"sv; + +class MockQUICLDConfig : public QUICLDConfig +{ + uint32_t + packet_threshold() const + { + return 3; + } + + float + time_threshold() const + { + return 1.25; + } + + ink_hrtime + granularity() const + { + return HRTIME_MSECONDS(1); + } + + ink_hrtime + initial_rtt() const + { + return HRTIME_MSECONDS(100); + } +}; + +class MockQUICCCConfig : public QUICCCConfig +{ + uint32_t + max_datagram_size() const + { + return 1200; + } + + uint32_t + initial_window() const + { + return 10; + } + + uint32_t + minimum_window() const + { + return 2; + } + + float + loss_reduction_factor() const + { + return 0.5; + } + + uint32_t + persistent_congestion_threshold() const + { + return 2; + } +}; + +class MockQUICConnectionInfoProvider : public QUICConnectionInfoProvider +{ + QUICConnectionId + connection_id() const override + { + return {reinterpret_cast("\x00"), 1}; + } + + QUICConnectionId + peer_connection_id() const override + { + return {reinterpret_cast("\x00"), 1}; + } + + QUICConnectionId + original_connection_id() const override + { + return {reinterpret_cast("\x00"), 1}; + } + + QUICConnectionId + first_connection_id() const override + { + return {reinterpret_cast("\x00"), 1}; + } + + const QUICFiveTuple + five_tuple() const override + { + return QUICFiveTuple(); + } + + std::string_view + cids() const override + { + using namespace std::literals; + return std::string_view("00000000-00000000"sv); + } + + uint32_t + pmtu() const override + { + return 1280; + } + + NetVConnectionContext_t + direction() const override + { + return NET_VCONNECTION_OUT; + } + + int + select_next_protocol(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, + unsigned inlen) const override + { + return SSL_TLSEXT_ERR_OK; + } + + bool + is_closed() const override + { + return false; + } + + std::string_view + negotiated_application_name() const override + { + return negotiated_application_name_sv; + } +}; class MockQUICStreamManager : public QUICStreamManager { public: - MockQUICStreamManager() : QUICStreamManager() {} + MockQUICStreamManager(QUICConnectionInfoProvider *info) : QUICStreamManager(info, nullptr, nullptr) {} + // Override virtual QUICConnectionErrorUPtr handle_frame(QUICEncryptionLevel level, const QUICFrame &f) override @@ -263,141 +397,167 @@ class MockQUICConnection : public QUICConnection int _transmit_count = 0; int _retransmit_count = 0; Ptr _mutex; - int _totalFrameCount = 0; - int _frameCount[256] = {0}; - MockQUICStreamManager _stream_manager; + int _totalFrameCount = 0; + int _frameCount[256] = {0}; + MockQUICStreamManager _stream_manager = {this}; QUICTransportParametersInEncryptedExtensions dummy_transport_parameters(); NetVConnectionContext_t _direction; }; -class MockQUICConnectionInfoProvider : public QUICConnectionInfoProvider +class MockQUICCongestionController : public QUICCongestionController { - QUICConnectionId - connection_id() const override +public: + MockQUICCongestionController() {} + // Override + virtual void + on_packets_lost(const std::map &packets) override { - return {reinterpret_cast("\x00"), 1}; + for (auto &p : packets) { + lost_packets.insert(p.first); + } } - QUICConnectionId - peer_connection_id() const override + virtual void + on_packet_sent(size_t bytes_sent) override { - return {reinterpret_cast("\x00"), 1}; } - - QUICConnectionId - original_connection_id() const override + virtual void + on_packet_acked(const QUICPacketInfo &acked_packet) override { - return {reinterpret_cast("\x00"), 1}; } - - QUICConnectionId - first_connection_id() const override + virtual void + process_ecn(const QUICPacketInfo &acked_largest_packet, const QUICAckFrame::EcnSection *ecn_section) override { - return {reinterpret_cast("\x00"), 1}; } - - const QUICFiveTuple - five_tuple() const override + virtual void + add_extra_credit() override { - return QUICFiveTuple(); } - - std::string_view - cids() const override + virtual void + reset() override { - using namespace std::literals; - return std::string_view("00000000-00000000"sv); } - - uint32_t - pmtu() const override + virtual uint32_t + credit() const override { - return 1280; + return 0; } - NetVConnectionContext_t - direction() const override + // for Test + int + getStreamFrameCount() { - return NET_VCONNECTION_OUT; + return _frameCount[static_cast(QUICFrameType::STREAM)]; } int - select_next_protocol(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, - unsigned inlen) const override + getAckFrameCount() { - return SSL_TLSEXT_ERR_OK; + return _frameCount[static_cast(QUICFrameType::ACK)]; } - bool - is_closed() const override + int + getPingFrameCount() { - return false; + return _frameCount[static_cast(QUICFrameType::PING)]; } - std::string_view - negotiated_application_name() const override + int + getTotalFrameCount() { - return negotiated_application_name_sv; + return _totalFrameCount; } + + std::set lost_packets; + +private: + int _totalFrameCount = 0; + int _frameCount[256] = {0}; }; -class MockQUICCongestionController : public QUICCongestionController +class MockQUICPacketProtectionKeyInfo : public QUICPacketProtectionKeyInfo { public: - MockQUICCongestionController(QUICConnectionInfoProvider *info, const QUICCCConfig &cc_config) - : QUICCongestionController(this->_rtt_measure, info, cc_config) + const EVP_CIPHER * + get_cipher(QUICKeyPhase phase) const override { + return EVP_aes_128_gcm(); } - // Override - virtual void - on_packets_lost(const std::map &packets) override + + size_t + get_tag_len(QUICKeyPhase phase) const override { - for (auto &p : packets) { - lost_packets.insert(p.first); - } + return EVP_GCM_TLS_TAG_LEN; } - // for Test - int - getStreamFrameCount() + const size_t *encryption_iv_len(QUICKeyPhase) const override { - return _frameCount[static_cast(QUICFrameType::STREAM)]; + static size_t dummy = 12; + return &dummy; } +}; - int - getAckFrameCount() +class MockQUICContext : public QUICContext, public QUICLDContext, public QUICCCContext +{ +public: + MockQUICContext() { - return _frameCount[static_cast(QUICFrameType::ACK)]; + _info = std::make_unique(); + _key_info = std::make_unique(); + _ld_config = std::make_unique(); + _cc_config = std::make_unique(); } - int - getPingFrameCount() + virtual QUICConnectionInfoProvider * + connection_info() const override { - return _frameCount[static_cast(QUICFrameType::PING)]; + return _info.get(); + } + virtual QUICConfig::scoped_config + config() const override + { + return _config; + } + virtual QUICRTTProvider * + rtt_provider() const override + { + return const_cast(&_rtt_measure); } - int - getTotalFrameCount() + virtual QUICPacketProtectionKeyInfo * + key_info() const override { - return _totalFrameCount; + return _key_info.get(); } - std::set lost_packets; + virtual QUICLDConfig & + ld_config() const override + { + return *_ld_config; + } -private: - int _totalFrameCount = 0; - int _frameCount[256] = {0}; + virtual QUICCCConfig & + cc_config() const override + { + return *_cc_config; + } +private: + QUICConfig::scoped_config _config; QUICRTTMeasure _rtt_measure; + std::unique_ptr _info; + std::unique_ptr _key_info; + std::unique_ptr _ld_config; + std::unique_ptr _cc_config; }; class MockQUICLossDetector : public QUICLossDetector { public: - MockQUICLossDetector(QUICConnectionInfoProvider *info, QUICCongestionController *cc, QUICRTTMeasure *rtt_measure, - const QUICLDConfig &ld_config) - : QUICLossDetector(info, cc, rtt_measure, ld_config) + MockQUICLossDetector(MockQUICContext &context) + : QUICLossDetector(context, &_cc, &_rtt_measure, &this->_pinger, &this->_padder), + _padder(NetVConnectionContext_t::NET_VCONNECTION_UNSET) { } void @@ -409,6 +569,12 @@ class MockQUICLossDetector : public QUICLossDetector on_packet_sent(QUICPacketUPtr packet) { } + +private: + QUICPinger _pinger; + QUICPadder _padder; + QUICRTTMeasure _rtt_measure; + MockQUICCongestionController _cc; }; class MockQUICApplication : public QUICApplication @@ -436,26 +602,36 @@ class MockQUICApplication : public QUICApplication } }; -class MockQUICPacketProtectionKeyInfo : public QUICPacketProtectionKeyInfo +class MockQUICPacket : public QUICPacket { public: - const EVP_CIPHER * - get_cipher(QUICKeyPhase phase) const override + const IpEndpoint & + from() const override { - return EVP_aes_128_gcm(); + return this->_from; } - size_t - get_tag_len(QUICKeyPhase phase) const override + const IpEndpoint & + to() const override { - return EVP_GCM_TLS_TAG_LEN; + return this->_to; } - const size_t *encryption_iv_len(QUICKeyPhase) const override + void + set_to(const IpEndpoint ep) { - static size_t dummy = 12; - return &dummy; + this->_to = ep; + } + + void + set_from(const IpEndpoint ep) + { + this->_from = ep; } + +private: + IpEndpoint _to; + IpEndpoint _from; }; class MockQUICHandshakeProtocol : public QUICHandshakeProtocol @@ -646,14 +822,14 @@ class MockQUICFrameGenerator : public QUICFrameGenerator { public: bool - will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) override + will_generate_frame(QUICEncryptionLevel level, size_t connection_credit, bool ack_eliciting, uint32_t seq_num) override { return true; } QUICFrame * generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, - ink_hrtime timestamp) override + size_t current_packet_size, uint32_t seq_num) override { QUICFrame *frame = QUICFrameFactory::create_ping_frame(buf, 0, this); QUICFrameInformationUPtr info = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc()); @@ -670,63 +846,3 @@ class MockQUICFrameGenerator : public QUICFrameGenerator lost_frame_count++; } }; - -class MockQUICLDConfig : public QUICLDConfig -{ - uint32_t - packet_threshold() const - { - return 3; - } - - float - time_threshold() const - { - return 1.25; - } - - ink_hrtime - granularity() const - { - return HRTIME_MSECONDS(1); - } - - ink_hrtime - initial_rtt() const - { - return HRTIME_MSECONDS(100); - } -}; - -class MockQUICCCConfig : public QUICCCConfig -{ - uint32_t - max_datagram_size() const - { - return 1200; - } - - uint32_t - initial_window() const - { - return 10; - } - - uint32_t - minimum_window() const - { - return 2; - } - - float - loss_reduction_factor() const - { - return 0.5; - } - - uint32_t - persistent_congestion_threshold() const - { - return 2; - } -}; diff --git a/iocore/net/quic/QUICAckFrameCreator.cc b/iocore/net/quic/QUICAckFrameCreator.cc index 27923b0f499..98ca8983d7a 100644 --- a/iocore/net/quic/QUICAckFrameCreator.cc +++ b/iocore/net/quic/QUICAckFrameCreator.cc @@ -61,7 +61,7 @@ QUICAckFrameManager::update(QUICEncryptionLevel level, QUICPacketNumber packet_n */ QUICFrame * QUICAckFrameManager::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t /* connection_credit */, - uint16_t maximum_frame_size, ink_hrtime timestamp) + uint16_t maximum_frame_size, size_t current_packet_size, uint32_t seq_num) { QUICAckFrame *ack_frame = nullptr; @@ -87,7 +87,8 @@ QUICAckFrameManager::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uin } bool -QUICAckFrameManager::will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) +QUICAckFrameManager::will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, + uint32_t seq_num) { // No ACK frame on ZERO_RTT level if (!this->_is_level_matched(level) || level == QUICEncryptionLevel::ZERO_RTT) { diff --git a/iocore/net/quic/QUICAckFrameCreator.h b/iocore/net/quic/QUICAckFrameCreator.h index 08b50d470bc..58e28e86868 100644 --- a/iocore/net/quic/QUICAckFrameCreator.h +++ b/iocore/net/quic/QUICAckFrameCreator.h @@ -100,13 +100,13 @@ class QUICAckFrameManager : public QUICFrameGenerator /* * Returns true only if should send ack. */ - bool will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) override; + bool will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) override; /* * Calls create directly. */ QUICFrame *generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, - ink_hrtime timestamp) override; + size_t current_packet_size, uint32_t seq_num) override; QUICFrameId issue_frame_id(); uint8_t ack_delay_exponent() const; diff --git a/iocore/net/quic/QUICAltConnectionManager.cc b/iocore/net/quic/QUICAltConnectionManager.cc index faca19e8743..4e39e930244 100644 --- a/iocore/net/quic/QUICAltConnectionManager.cc +++ b/iocore/net/quic/QUICAltConnectionManager.cc @@ -21,6 +21,9 @@ limitations under the License. */ +#include "algorithm" +#include "tscore/ink_assert.h" +#include "tscore/ink_defs.h" #include "QUICAltConnectionManager.h" #include "QUICConnectionTable.h" @@ -30,43 +33,47 @@ static constexpr char V_DEBUG_TAG[] = "v_quic_alt_con"; QUICAltConnectionManager::QUICAltConnectionManager(QUICConnection *qc, QUICConnectionTable &ctable, const QUICConnectionId &peer_initial_cid, uint32_t instance_id, - uint8_t num_alt_con, const QUICPreferredAddress &preferred_address) - : _qc(qc), _ctable(ctable), _instance_id(instance_id), _nids(num_alt_con) + uint8_t local_active_cid_limit, const IpEndpoint *preferred_endpoint_ipv4, + const IpEndpoint *preferred_endpoint_ipv6) + : _qc(qc), _ctable(ctable), _instance_id(instance_id), _local_active_cid_limit(local_active_cid_limit) { // Sequence number of the initial CID is 0 this->_alt_quic_connection_ids_remote.push_back({0, peer_initial_cid, {}, {true}}); - // Sequence number of the preferred address is 1 if available - if (preferred_address.is_available()) { - this->_alt_quic_connection_ids_remote.push_back({1, preferred_address.cid(), preferred_address.token(), {false}}); - } - - this->_alt_quic_connection_ids_local = static_cast(ats_malloc(sizeof(AltConnectionInfo) * this->_nids)); -} + if ((preferred_endpoint_ipv4 && !ats_ip_addr_port_eq(*preferred_endpoint_ipv4, qc->five_tuple().source())) || + (preferred_endpoint_ipv6 && !ats_ip_addr_port_eq(*preferred_endpoint_ipv6, qc->five_tuple().source()))) { + this->_alt_quic_connection_ids_local[0] = this->_generate_next_alt_con_info(); + // This alt cid will be advertised via Transport Parameter, so no need to advertise it via NCID frame + this->_alt_quic_connection_ids_local[0].advertised = true; -QUICAltConnectionManager::QUICAltConnectionManager(QUICConnection *qc, QUICConnectionTable &ctable, - const QUICConnectionId &peer_initial_cid, uint32_t instance_id, - uint8_t num_alt_con, const IpEndpoint *preferred_endpoint_ipv4, - const IpEndpoint *preferred_endpoint_ipv6) - : _qc(qc), _ctable(ctable), _instance_id(instance_id), _nids(num_alt_con) -{ - // Sequence number of the initial CID is 0 - this->_alt_quic_connection_ids_remote.push_back({0, peer_initial_cid, {}, {true}}); + IpEndpoint empty_endpoint_ipv4; + IpEndpoint empty_endpoint_ipv6; + empty_endpoint_ipv4.sa.sa_family = AF_UNSPEC; + empty_endpoint_ipv6.sa.sa_family = AF_UNSPEC; + if (preferred_endpoint_ipv4 == nullptr) { + preferred_endpoint_ipv4 = &empty_endpoint_ipv4; + } + if (preferred_endpoint_ipv6 == nullptr) { + preferred_endpoint_ipv6 = &empty_endpoint_ipv6; + } - this->_alt_quic_connection_ids_local = static_cast(ats_malloc(sizeof(AltConnectionInfo) * this->_nids)); - this->_init_alt_connection_ids(preferred_endpoint_ipv4, preferred_endpoint_ipv6); + // FIXME Check nullptr dereference + this->_local_preferred_address = + new QUICPreferredAddress(*preferred_endpoint_ipv4, *preferred_endpoint_ipv6, this->_alt_quic_connection_ids_local[0].id, + this->_alt_quic_connection_ids_local[0].token); + } } QUICAltConnectionManager::~QUICAltConnectionManager() { ats_free(this->_alt_quic_connection_ids_local); - delete this->_preferred_address; + delete this->_local_preferred_address; } const QUICPreferredAddress * QUICAltConnectionManager::preferred_address() const { - return this->_preferred_address; + return this->_local_preferred_address; } std::vector @@ -118,32 +125,9 @@ QUICAltConnectionManager::_generate_next_alt_con_info() } void -QUICAltConnectionManager::_init_alt_connection_ids(const IpEndpoint *preferred_endpoint_ipv4, - const IpEndpoint *preferred_endpoint_ipv6) +QUICAltConnectionManager::_init_alt_connection_ids() { - if (preferred_endpoint_ipv4 || preferred_endpoint_ipv6) { - this->_alt_quic_connection_ids_local[0] = this->_generate_next_alt_con_info(); - // This alt cid will be advertised via Transport Parameter - this->_alt_quic_connection_ids_local[0].advertised = true; - - IpEndpoint empty_endpoint_ipv4; - IpEndpoint empty_endpoint_ipv6; - empty_endpoint_ipv4.sa.sa_family = AF_UNSPEC; - empty_endpoint_ipv6.sa.sa_family = AF_UNSPEC; - if (preferred_endpoint_ipv4 == nullptr) { - preferred_endpoint_ipv4 = &empty_endpoint_ipv4; - } - if (preferred_endpoint_ipv6 == nullptr) { - preferred_endpoint_ipv6 = &empty_endpoint_ipv6; - } - - // FIXME Check nullptr dereference - this->_preferred_address = - new QUICPreferredAddress(*preferred_endpoint_ipv4, *preferred_endpoint_ipv6, this->_alt_quic_connection_ids_local[0].id, - this->_alt_quic_connection_ids_local[0].token); - } - - for (int i = (preferred_endpoint_ipv4 || preferred_endpoint_ipv6 ? 1 : 0); i < this->_nids; ++i) { + for (int i = 0; i < this->_remote_active_cid_limit; ++i) { this->_alt_quic_connection_ids_local[i] = this->_generate_next_alt_con_info(); } this->_need_advertise = true; @@ -152,19 +136,24 @@ QUICAltConnectionManager::_init_alt_connection_ids(const IpEndpoint *preferred_e bool QUICAltConnectionManager::_update_alt_connection_id(uint64_t chosen_seq_num) { - for (int i = 0; i < this->_nids; ++i) { - if (_alt_quic_connection_ids_local[i].seq_num == chosen_seq_num) { - _alt_quic_connection_ids_local[i] = this->_generate_next_alt_con_info(); - this->_need_advertise = true; - return true; - } - } - // Seq 0 is special so it's not in the array if (chosen_seq_num == 0) { return true; } + // Seq 1 is for Preferred Address + if (chosen_seq_num == 1) { + return true; + } + + for (int i = 0; i < this->_remote_active_cid_limit; ++i) { + if (this->_alt_quic_connection_ids_local[i].seq_num == chosen_seq_num) { + this->_alt_quic_connection_ids_local[i] = this->_generate_next_alt_con_info(); + this->_need_advertise = true; + return true; + } + } + return false; } @@ -177,8 +166,15 @@ QUICAltConnectionManager::_register_remote_connection_id(const QUICNewConnection error = std::make_unique(QUICTransErrorCode::PROTOCOL_VIOLATION, "received zero-length cid", QUICFrameType::NEW_CONNECTION_ID); } else { - this->_alt_quic_connection_ids_remote.push_back( - {frame.sequence(), frame.connection_id(), frame.stateless_reset_token(), {false}}); + int unused = std::count_if(this->_alt_quic_connection_ids_remote.begin(), this->_alt_quic_connection_ids_remote.end(), + [](AltConnectionInfo info) { return info.used == false && info.seq_num != 1; }); + if (unused > this->_local_active_cid_limit) { + error = std::make_unique(QUICTransErrorCode::PROTOCOL_VIOLATION, "received too many alt CIDs", + QUICFrameType::NEW_CONNECTION_ID); + } else { + this->_alt_quic_connection_ids_remote.push_back( + {frame.sequence(), frame.connection_id(), frame.stateless_reset_token(), {false}}); + } } return error; @@ -214,10 +210,6 @@ QUICAltConnectionManager::is_ready_to_migrate() const QUICConnectionId QUICAltConnectionManager::migrate_to_alt_cid() { - if (this->_qc->direction() == NET_VCONNECTION_OUT) { - this->_init_alt_connection_ids(); - } - for (auto &info : this->_alt_quic_connection_ids_remote) { if (info.used) { continue; @@ -233,7 +225,14 @@ QUICAltConnectionManager::migrate_to_alt_cid() bool QUICAltConnectionManager::migrate_to(const QUICConnectionId &cid, QUICStatelessResetToken &new_reset_token) { - for (unsigned int i = 0; i < this->_nids; ++i) { + if (this->_local_preferred_address) { + if (cid == this->_local_preferred_address->cid()) { + new_reset_token = this->_local_preferred_address->token(); + return true; + } + } + + for (int i = 0; i < this->_remote_active_cid_limit; ++i) { AltConnectionInfo &info = this->_alt_quic_connection_ids_local[i]; if (info.id == cid) { // Migrate connection @@ -260,13 +259,33 @@ QUICAltConnectionManager::drop_cid(const QUICConnectionId &cid) void QUICAltConnectionManager::invalidate_alt_connections() { - for (unsigned int i = 0; i < this->_nids; ++i) { + int n = this->_remote_active_cid_limit + ((this->_local_preferred_address == nullptr) ? 1 : 0); + + for (int i = 0; i < n; ++i) { this->_ctable.erase(this->_alt_quic_connection_ids_local[i].id, this->_qc); } } +void +QUICAltConnectionManager::set_remote_preferred_address(const QUICPreferredAddress &preferred_address) +{ + ink_assert(preferred_address.is_available()); + + // Sequence number of the preferred address is 1 if available + this->_alt_quic_connection_ids_remote.push_back({1, preferred_address.cid(), preferred_address.token(), {false}}); +} + +void +QUICAltConnectionManager::set_remote_active_cid_limit(uint8_t active_cid_limit) +{ + this->_remote_active_cid_limit = + std::min(static_cast(active_cid_limit), countof(this->_alt_quic_connection_ids_local)); + this->_init_alt_connection_ids(); +} + bool -QUICAltConnectionManager::will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) +QUICAltConnectionManager::will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, + uint32_t seq_num) { if (!this->_is_level_matched(level)) { return false; @@ -280,7 +299,7 @@ QUICAltConnectionManager::will_generate_frame(QUICEncryptionLevel level, ink_hrt */ QUICFrame * QUICAltConnectionManager::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t /* connection_credit */, - uint16_t maximum_frame_size, ink_hrtime timestamp) + uint16_t maximum_frame_size, size_t current_packet_size, uint32_t seq_num) { QUICFrame *frame = nullptr; if (!this->_is_level_matched(level)) { @@ -288,10 +307,10 @@ QUICAltConnectionManager::generate_frame(uint8_t *buf, QUICEncryptionLevel level } if (this->_need_advertise) { - int count = this->_nids; - for (int i = 0; i < count; ++i) { + for (int i = 0; i < this->_remote_active_cid_limit; ++i) { if (!this->_alt_quic_connection_ids_local[i].advertised) { - frame = QUICFrameFactory::create_new_connection_id_frame(buf, this->_alt_quic_connection_ids_local[i].seq_num, + // FIXME Should send a sequence number for retire_prior_to. Sending 0 for now. + frame = QUICFrameFactory::create_new_connection_id_frame(buf, this->_alt_quic_connection_ids_local[i].seq_num, 0, this->_alt_quic_connection_ids_local[i].id, this->_alt_quic_connection_ids_local[i].token); @@ -310,12 +329,11 @@ QUICAltConnectionManager::generate_frame(uint8_t *buf, QUICEncryptionLevel level } if (!this->_retired_seq_nums.empty()) { - if (auto s = this->_retired_seq_nums.front()) { - frame = QUICFrameFactory::create_retire_connection_id_frame(buf, s); - this->_records_retire_connection_id_frame(level, static_cast(*frame)); - this->_retired_seq_nums.pop(); - return frame; - } + auto s = this->_retired_seq_nums.front(); + frame = QUICFrameFactory::create_retire_connection_id_frame(buf, s); + this->_records_retire_connection_id_frame(level, static_cast(*frame)); + this->_retired_seq_nums.pop(); + return frame; } return frame; @@ -351,7 +369,7 @@ QUICAltConnectionManager::_on_frame_lost(QUICFrameInformationUPtr &info) switch (info->type) { case QUICFrameType::NEW_CONNECTION_ID: { AltConnectionInfo *frame_info = reinterpret_cast(info->data); - for (int i = 0; i < this->_nids; ++i) { + for (int i = 0; i < this->_remote_active_cid_limit; ++i) { if (this->_alt_quic_connection_ids_local[i].seq_num == frame_info->seq_num) { ink_assert(this->_alt_quic_connection_ids_local[i].advertised); this->_alt_quic_connection_ids_local[i].advertised = false; diff --git a/iocore/net/quic/QUICAltConnectionManager.h b/iocore/net/quic/QUICAltConnectionManager.h index 501ab99a28c..09b99ca3d7c 100644 --- a/iocore/net/quic/QUICAltConnectionManager.h +++ b/iocore/net/quic/QUICAltConnectionManager.h @@ -35,16 +35,8 @@ class QUICConnectionTable; class QUICAltConnectionManager : public QUICFrameHandler, public QUICFrameGenerator { public: - /** - * Constructor for clients - */ - QUICAltConnectionManager(QUICConnection *qc, QUICConnectionTable &ctable, const QUICConnectionId &peer_initial_cid, - uint32_t instance_id, uint8_t num_alt_con, const QUICPreferredAddress &preferred_address); - /** - * Constructor for servers - */ QUICAltConnectionManager(QUICConnection *qc, QUICConnectionTable &ctable, const QUICConnectionId &peer_initial_cid, - uint32_t instance_id, uint8_t num_alt_con, const IpEndpoint *preferred_endpoint_ipv4 = nullptr, + uint32_t instance_id, uint8_t active_cid_limit, const IpEndpoint *preferred_endpoint_ipv4 = nullptr, const IpEndpoint *preferred_endpoint_ipv6 = nullptr); ~QUICAltConnectionManager(); @@ -68,6 +60,9 @@ class QUICAltConnectionManager : public QUICFrameHandler, public QUICFrameGenera void drop_cid(const QUICConnectionId &cid); + void set_remote_preferred_address(const QUICPreferredAddress &preferred_address); + void set_remote_active_cid_limit(uint8_t active_cid_limit); + /** * Invalidate all CIDs prepared */ @@ -83,9 +78,9 @@ class QUICAltConnectionManager : public QUICFrameHandler, public QUICFrameGenera virtual QUICConnectionErrorUPtr handle_frame(QUICEncryptionLevel level, const QUICFrame &frame) override; // QUICFrameGenerator - bool will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) override; + bool will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) override; QUICFrame *generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, - ink_hrtime timestamp) override; + size_t current_packet_size, uint32_t seq_num) override; private: struct AltConnectionInfo { @@ -100,18 +95,18 @@ class QUICAltConnectionManager : public QUICFrameHandler, public QUICFrameGenera QUICConnection *_qc = nullptr; QUICConnectionTable &_ctable; - AltConnectionInfo *_alt_quic_connection_ids_local; + AltConnectionInfo _alt_quic_connection_ids_local[8]; // 8 is perhaps enough std::vector _alt_quic_connection_ids_remote; std::queue _retired_seq_nums; - uint32_t _instance_id = 0; - uint8_t _nids = 1; - uint64_t _alt_quic_connection_id_seq_num = 0; - bool _need_advertise = false; - QUICPreferredAddress *_preferred_address = nullptr; + uint32_t _instance_id = 0; + uint8_t _local_active_cid_limit = 0; + uint8_t _remote_active_cid_limit = 0; + uint64_t _alt_quic_connection_id_seq_num = 0; + bool _need_advertise = false; + QUICPreferredAddress *_local_preferred_address = nullptr; AltConnectionInfo _generate_next_alt_con_info(); - void _init_alt_connection_ids(const IpEndpoint *preferred_endpoint_ipv4 = nullptr, - const IpEndpoint *preferred_endpoint_ipv6 = nullptr); + void _init_alt_connection_ids(); bool _update_alt_connection_id(uint64_t chosen_seq_num); void _records_new_connection_id_frame(QUICEncryptionLevel level, const QUICNewConnectionIdFrame &frame); diff --git a/iocore/net/quic/QUICBidirectionalStream.cc b/iocore/net/quic/QUICBidirectionalStream.cc index bbd98d9652a..c028998c765 100644 --- a/iocore/net/quic/QUICBidirectionalStream.cc +++ b/iocore/net/quic/QUICBidirectionalStream.cc @@ -352,15 +352,16 @@ QUICBidirectionalStream::reenable(VIO *vio) } bool -QUICBidirectionalStream::will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) +QUICBidirectionalStream::will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, + uint32_t seq_num) { - return this->_local_flow_controller.will_generate_frame(level, timestamp) || !this->is_retransmited_frame_queue_empty() || - this->_write_vio.get_reader()->is_read_avail_more_than(0); + return this->_local_flow_controller.will_generate_frame(level, current_packet_size, ack_eliciting, seq_num) || + !this->is_retransmited_frame_queue_empty() || this->_write_vio.get_reader()->is_read_avail_more_than(0); } QUICFrame * QUICBidirectionalStream::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, - uint16_t maximum_frame_size, ink_hrtime timestamp) + uint16_t maximum_frame_size, size_t current_packet_size, uint32_t seq_num) { SCOPED_MUTEX_LOCK(lock, this->_write_vio.mutex, this_ethread()); @@ -391,7 +392,7 @@ QUICBidirectionalStream::generate_frame(uint8_t *buf, QUICEncryptionLevel level, } // MAX_STREAM_DATA - frame = this->_local_flow_controller.generate_frame(buf, level, UINT16_MAX, maximum_frame_size, timestamp); + frame = this->_local_flow_controller.generate_frame(buf, level, UINT16_MAX, maximum_frame_size, current_packet_size, seq_num); if (frame) { return frame; } @@ -427,7 +428,8 @@ QUICBidirectionalStream::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t stream_credit = this->_remote_flow_controller.credit(); if (stream_credit == 0) { // STREAM_DATA_BLOCKED - frame = this->_remote_flow_controller.generate_frame(buf, level, UINT16_MAX, maximum_frame_size, timestamp); + frame = + this->_remote_flow_controller.generate_frame(buf, level, UINT16_MAX, maximum_frame_size, current_packet_size, seq_num); return frame; } diff --git a/iocore/net/quic/QUICBidirectionalStream.h b/iocore/net/quic/QUICBidirectionalStream.h index fcbd5d7140b..d64f899bd6c 100644 --- a/iocore/net/quic/QUICBidirectionalStream.h +++ b/iocore/net/quic/QUICBidirectionalStream.h @@ -44,9 +44,9 @@ class QUICBidirectionalStream : public QUICStreamVConnection, public QUICTransfe int state_stream_closed(int event, void *data); // QUICFrameGenerator - bool will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) override; + bool will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) override; QUICFrame *generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, - ink_hrtime timestamp) override; + size_t current_packet_size, uint32_t seq_num) override; virtual QUICConnectionErrorUPtr recv(const QUICStreamFrame &frame) override; virtual QUICConnectionErrorUPtr recv(const QUICMaxStreamDataFrame &frame) override; diff --git a/iocore/net/quic/QUICConfig.cc b/iocore/net/quic/QUICConfig.cc index 600cef8e75f..1cfe703fc3f 100644 --- a/iocore/net/quic/QUICConfig.cc +++ b/iocore/net/quic/QUICConfig.cc @@ -117,7 +117,6 @@ QUICConfigParams::initialize() { REC_EstablishStaticConfigInt32U(this->_instance_id, "proxy.config.quic.instance_id"); REC_EstablishStaticConfigInt32(this->_connection_table_size, "proxy.config.quic.connection_table.size"); - REC_EstablishStaticConfigInt32U(this->_num_alt_connection_ids, "proxy.config.quic.num_alt_connection_ids"); REC_EstablishStaticConfigInt32U(this->_stateless_retry, "proxy.config.quic.server.stateless_retry_enabled"); REC_EstablishStaticConfigInt32U(this->_vn_exercise_enabled, "proxy.config.quic.client.vn_exercise_enabled"); REC_EstablishStaticConfigInt32U(this->_cm_exercise_enabled, "proxy.config.quic.client.cm_exercise_enabled"); @@ -158,6 +157,8 @@ QUICConfigParams::initialize() REC_EstablishStaticConfigInt32U(this->_ack_delay_exponent_out, "proxy.config.quic.ack_delay_exponent_out"); REC_EstablishStaticConfigInt32U(this->_max_ack_delay_in, "proxy.config.quic.max_ack_delay_in"); REC_EstablishStaticConfigInt32U(this->_max_ack_delay_out, "proxy.config.quic.max_ack_delay_out"); + REC_EstablishStaticConfigInt32U(this->_active_cid_limit_in, "proxy.config.quic.active_cid_limit_in"); + REC_EstablishStaticConfigInt32U(this->_active_cid_limit_out, "proxy.config.quic.active_cid_limit_out"); // Loss Detection REC_EstablishStaticConfigInt32U(this->_ld_packet_threshold, "proxy.config.quic.loss_detection.packet_threshold"); @@ -225,12 +226,6 @@ QUICConfigParams::connection_table_size() return _connection_table_size; } -uint32_t -QUICConfigParams::num_alt_connection_ids() const -{ - return this->_num_alt_connection_ids; -} - uint32_t QUICConfigParams::stateless_retry() const { @@ -345,6 +340,18 @@ QUICConfigParams::max_ack_delay_out() const return this->_max_ack_delay_out; } +uint8_t +QUICConfigParams::active_cid_limit_in() const +{ + return this->_active_cid_limit_in; +} + +uint8_t +QUICConfigParams::active_cid_limit_out() const +{ + return this->_active_cid_limit_out; +} + const char * QUICConfigParams::server_supported_groups() const { diff --git a/iocore/net/quic/QUICConfig.h b/iocore/net/quic/QUICConfig.h index 36ff7af9554..67106e65ffb 100644 --- a/iocore/net/quic/QUICConfig.h +++ b/iocore/net/quic/QUICConfig.h @@ -37,7 +37,6 @@ class QUICConfigParams : public ConfigInfo void initialize(); uint32_t instance_id() const; - uint32_t num_alt_connection_ids() const; uint32_t stateless_retry() const; uint32_t vn_exercise_enabled() const; uint32_t cm_exercise_enabled() const; @@ -70,6 +69,8 @@ class QUICConfigParams : public ConfigInfo uint8_t ack_delay_exponent_out() const; uint8_t max_ack_delay_in() const; uint8_t max_ack_delay_out() const; + uint8_t active_cid_limit_in() const; + uint8_t active_cid_limit_out() const; // Loss Detection uint32_t ld_packet_threshold() const; @@ -92,11 +93,10 @@ class QUICConfigParams : public ConfigInfo // TODO: make configurable static const uint8_t _scid_len = 18; //< Length of Source Connection ID - uint32_t _instance_id = 0; - uint32_t _num_alt_connection_ids = 0; - uint32_t _stateless_retry = 0; - uint32_t _vn_exercise_enabled = 0; - uint32_t _cm_exercise_enabled = 0; + uint32_t _instance_id = 0; + uint32_t _stateless_retry = 0; + uint32_t _vn_exercise_enabled = 0; + uint32_t _cm_exercise_enabled = 0; char *_server_supported_groups = nullptr; char *_client_supported_groups = nullptr; @@ -128,19 +128,21 @@ class QUICConfigParams : public ConfigInfo uint32_t _ack_delay_exponent_out = 0; uint32_t _max_ack_delay_in = 0; uint32_t _max_ack_delay_out = 0; + uint32_t _active_cid_limit_in = 0; + uint32_t _active_cid_limit_out = 0; // [draft-17 recovery] 6.4.1. Constants of interest uint32_t _ld_packet_threshold = 3; float _ld_time_threshold = 1.25; ink_hrtime _ld_granularity = HRTIME_MSECONDS(1); - ink_hrtime _ld_initial_rtt = HRTIME_MSECONDS(100); + ink_hrtime _ld_initial_rtt = HRTIME_MSECONDS(500); // [draft-11 recovery] 4.7.1. Constants of interest uint32_t _cc_max_datagram_size = 1200; uint32_t _cc_initial_window_scale = 10; // Actual initial window size is this value multiplied by the _cc_default_mss uint32_t _cc_minimum_window_scale = 2; // Actual minimum window size is this value multiplied by the _cc_default_mss float _cc_loss_reduction_factor = 0.5; - uint32_t _cc_persistent_congestion_threshold = 2; + uint32_t _cc_persistent_congestion_threshold = 3; }; class QUICConfig diff --git a/iocore/net/quic/QUICCongestionController.h b/iocore/net/quic/QUICCongestionController.h new file mode 100644 index 00000000000..46341dc2ba2 --- /dev/null +++ b/iocore/net/quic/QUICCongestionController.h @@ -0,0 +1,53 @@ +/** @file + * + * A brief file description + * + * @section license License + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +struct QUICPacketInfo { + // 6.3.1. Sent Packet Fields + QUICPacketNumber packet_number; + ink_hrtime time_sent; + bool ack_eliciting; + bool is_crypto_packet; + bool in_flight; + size_t sent_bytes; + + // addition + QUICPacketType type; + std::vector frames; + QUICPacketNumberSpace pn_space; + // end +}; + +class QUICCongestionController +{ +public: + virtual ~QUICCongestionController() {} + virtual void on_packet_sent(size_t bytes_sent) = 0; + virtual void on_packet_acked(const QUICPacketInfo &acked_packet) = 0; + virtual void process_ecn(const QUICPacketInfo &acked_largest_packet, const QUICAckFrame::EcnSection *ecn_section) = 0; + virtual void on_packets_lost(const std::map &packets) = 0; + virtual void add_extra_credit() = 0; + virtual void reset() = 0; + virtual uint32_t credit() const = 0; +}; diff --git a/iocore/net/quic/QUICConnection.h b/iocore/net/quic/QUICConnection.h index d2c3d56b78a..28c5a83ec8c 100644 --- a/iocore/net/quic/QUICConnection.h +++ b/iocore/net/quic/QUICConnection.h @@ -34,6 +34,7 @@ class UDPPacket; class QUICConnectionInfoProvider { public: + virtual ~QUICConnectionInfoProvider() {} virtual QUICConnectionId peer_connection_id() const = 0; virtual QUICConnectionId original_connection_id() const = 0; virtual QUICConnectionId first_connection_id() const = 0; diff --git a/iocore/net/quic/QUICContext.cc b/iocore/net/quic/QUICContext.cc new file mode 100644 index 00000000000..7ccb9e4043f --- /dev/null +++ b/iocore/net/quic/QUICContext.cc @@ -0,0 +1,147 @@ +/** @file + + A brief file description + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "QUICContext.h" +#include "QUICConnection.h" +#include "QUICLossDetector.h" +#include "QUICPacketProtectionKeyInfo.h" + +class QUICCCConfigQCP : public QUICCCConfig +{ +public: + virtual ~QUICCCConfigQCP() {} + QUICCCConfigQCP(const QUICConfigParams *params) : _params(params) {} + + uint32_t + max_datagram_size() const override + { + return this->_params->cc_max_datagram_size(); + } + + uint32_t + initial_window() const override + { + return this->_params->cc_initial_window(); + } + + uint32_t + minimum_window() const override + { + return this->_params->cc_minimum_window(); + } + + float + loss_reduction_factor() const override + { + return this->_params->cc_loss_reduction_factor(); + } + + uint32_t + persistent_congestion_threshold() const override + { + return this->_params->cc_persistent_congestion_threshold(); + } + +private: + const QUICConfigParams *_params; +}; + +class QUICLDConfigQCP : public QUICLDConfig +{ +public: + virtual ~QUICLDConfigQCP() {} + QUICLDConfigQCP(const QUICConfigParams *params) : _params(params) {} + + uint32_t + packet_threshold() const override + { + return this->_params->ld_packet_threshold(); + } + + float + time_threshold() const override + { + return this->_params->ld_time_threshold(); + } + + ink_hrtime + granularity() const override + { + return this->_params->ld_granularity(); + } + + ink_hrtime + initial_rtt() const override + { + return this->_params->ld_initial_rtt(); + } + +private: + const QUICConfigParams *_params; +}; + +QUICContextImpl::QUICContextImpl(QUICRTTProvider *rtt, QUICConnectionInfoProvider *info, + QUICPacketProtectionKeyInfoProvider *key_info) + : _key_info(key_info), + _connection_info(info), + _rtt_provider(rtt), + _ld_config(std::make_unique(_config)), + _cc_config(std::make_unique(_config)) +{ +} + +QUICConnectionInfoProvider * +QUICContextImpl::connection_info() const +{ + return _connection_info; +} + +QUICConfig::scoped_config +QUICContextImpl::config() const +{ + return _config; +} + +QUICPacketProtectionKeyInfoProvider * +QUICContextImpl::key_info() const +{ + return _key_info; +} + +QUICRTTProvider * +QUICContextImpl::rtt_provider() const +{ + return _rtt_provider; +} + +QUICLDConfig & +QUICContextImpl::ld_config() const +{ + return *_ld_config; +} + +QUICCCConfig & +QUICContextImpl::cc_config() const +{ + return *_cc_config; +} diff --git a/iocore/net/quic/QUICContext.h b/iocore/net/quic/QUICContext.h new file mode 100644 index 00000000000..57e6c0b3a3b --- /dev/null +++ b/iocore/net/quic/QUICContext.h @@ -0,0 +1,84 @@ +/** @file + + A brief file description + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#pragma once + +#include "QUICConnection.h" +#include "QUICConfig.h" + +class QUICRTTProvider; +class QUICCongestionController; +class QUICPacketProtectionKeyInfoProvider; + +class QUICNetVConnection; + +class QUICContext +{ +public: + virtual ~QUICContext(){}; + virtual QUICConnectionInfoProvider *connection_info() const = 0; + virtual QUICConfig::scoped_config config() const = 0; +}; + +class QUICLDContext +{ +public: + virtual ~QUICLDContext() {} + virtual QUICConnectionInfoProvider *connection_info() const = 0; + virtual QUICLDConfig &ld_config() const = 0; + virtual QUICPacketProtectionKeyInfoProvider *key_info() const = 0; +}; + +class QUICCCContext +{ +public: + virtual ~QUICCCContext() {} + virtual QUICConnectionInfoProvider *connection_info() const = 0; + virtual QUICCCConfig &cc_config() const = 0; + virtual QUICRTTProvider *rtt_provider() const = 0; +}; + +class QUICContextImpl : public QUICContext, public QUICCCContext, public QUICLDContext +{ +public: + QUICContextImpl(QUICRTTProvider *rtt, QUICConnectionInfoProvider *info, QUICPacketProtectionKeyInfoProvider *key_info); + + virtual QUICConnectionInfoProvider *connection_info() const override; + virtual QUICConfig::scoped_config config() const override; + virtual QUICRTTProvider *rtt_provider() const override; + + // TODO should be more abstract + virtual QUICPacketProtectionKeyInfoProvider *key_info() const override; + + virtual QUICLDConfig &ld_config() const override; + virtual QUICCCConfig &cc_config() const override; + +private: + QUICConfig::scoped_config _config; + QUICPacketProtectionKeyInfoProvider *_key_info = nullptr; + QUICConnectionInfoProvider *_connection_info = nullptr; + QUICRTTProvider *_rtt_provider = nullptr; + + std::unique_ptr _ld_config = nullptr; + std::unique_ptr _cc_config = nullptr; +}; diff --git a/iocore/net/quic/QUICCryptoStream.cc b/iocore/net/quic/QUICCryptoStream.cc index f3b702cc487..ba3afa277b7 100644 --- a/iocore/net/quic/QUICCryptoStream.cc +++ b/iocore/net/quic/QUICCryptoStream.cc @@ -102,7 +102,7 @@ QUICCryptoStream::write(const uint8_t *buf, int64_t len) } bool -QUICCryptoStream::will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) +QUICCryptoStream::will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) { return this->_write_buffer_reader->is_read_avail_more_than(0) || !this->is_retransmited_frame_queue_empty(); } @@ -112,7 +112,7 @@ QUICCryptoStream::will_generate_frame(QUICEncryptionLevel level, ink_hrtime time */ QUICFrame * QUICCryptoStream::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t /* connection_credit */, - uint16_t maximum_frame_size, ink_hrtime timestamp) + uint16_t maximum_frame_size, size_t current_packet_size, uint32_t seq_num) { QUICConnectionErrorUPtr error = nullptr; diff --git a/iocore/net/quic/QUICCryptoStream.h b/iocore/net/quic/QUICCryptoStream.h index 6da3b2fcd2b..42f99db742e 100644 --- a/iocore/net/quic/QUICCryptoStream.h +++ b/iocore/net/quic/QUICCryptoStream.h @@ -53,9 +53,9 @@ class QUICCryptoStream : public QUICStream int64_t write(const uint8_t *buf, int64_t len); // QUICFrameGenerator - bool will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) override; + bool will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) override; QUICFrame *generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, - ink_hrtime timestamp) override; + size_t current_packet_size, uint32_t seq_num) override; private: void _on_frame_acked(QUICFrameInformationUPtr &info) override; diff --git a/iocore/net/quic/QUICDebugNames.cc b/iocore/net/quic/QUICDebugNames.cc index b70d95975bf..bf9d2d8f45a 100644 --- a/iocore/net/quic/QUICDebugNames.cc +++ b/iocore/net/quic/QUICDebugNames.cc @@ -121,22 +121,20 @@ QUICDebugNames::error_code(uint16_t code) return "INTERNAL_ERROR"; case static_cast(QUICTransErrorCode::FLOW_CONTROL_ERROR): return "FLOW_CONTROL_ERROR"; - case static_cast(QUICTransErrorCode::STREAM_ID_ERROR): - return "STREAM_ID_ERROR"; + case static_cast(QUICTransErrorCode::STREAM_LIMIT_ERROR): + return "STREAM_LIMIT_ERROR"; case static_cast(QUICTransErrorCode::STREAM_STATE_ERROR): return "STREAM_STATE_ERROR"; - case static_cast(QUICTransErrorCode::FINAL_OFFSET_ERROR): - return "FINAL_OFFSET_ERROR"; + case static_cast(QUICTransErrorCode::FINAL_SIZE_ERROR): + return "FINAL_SIZE_ERROR"; case static_cast(QUICTransErrorCode::FRAME_ENCODING_ERROR): return "FRAME_ENCODING_ERROR"; case static_cast(QUICTransErrorCode::TRANSPORT_PARAMETER_ERROR): return "TRANSPORT_PARAMETER_ERROR"; - case static_cast(QUICTransErrorCode::VERSION_NEGOTIATION_ERROR): - return "VERSION_NEGOTIATION_ERROR"; case static_cast(QUICTransErrorCode::PROTOCOL_VIOLATION): return "PROTOCOL_VIOLATION"; - case static_cast(QUICTransErrorCode::INVALID_MIGRATION): - return "INVALID_MIGRATION"; + case static_cast(QUICTransErrorCode::CRYPTO_BUFFER_EXCEEDED): + return "CRYPTO_BUFFER_EXCEEDED"; default: if (0x0100 <= code && code <= 0x01FF) { return "CRYPTO_ERROR"; @@ -193,8 +191,8 @@ QUICDebugNames::transport_parameter_id(QUICTransportParameterId id) return "ACK_DELAY_EXPONENT"; case QUICTransportParameterId::INITIAL_MAX_STREAMS_UNI: return "INITIAL_MAX_STREAMS_UNI"; - case QUICTransportParameterId::DISABLE_MIGRATION: - return "DISABLE_MIGRATION"; + case QUICTransportParameterId::DISABLE_ACTIVE_MIGRATION: + return "DISABLE_ACTIVE_MIGRATION"; case QUICTransportParameterId::INITIAL_MAX_STREAM_DATA_BIDI_REMOTE: return "INITIAL_MAX_STREAM_DATA_BIDI_REMOTE"; case QUICTransportParameterId::INITIAL_MAX_STREAM_DATA_UNI: @@ -203,6 +201,8 @@ QUICDebugNames::transport_parameter_id(QUICTransportParameterId id) return "INITIAL_MAX_ACK_DELAY"; case QUICTransportParameterId::ORIGINAL_CONNECTION_ID: return "INITIAL_ORIGINAL_CONNECTION_ID"; + case QUICTransportParameterId::ACTIVE_CONNECTION_ID_LIMIT: + return "ACTIVE_CONNECTION_ID_LIMIT"; default: return "UNKNOWN"; } diff --git a/iocore/net/quic/QUICFlowController.cc b/iocore/net/quic/QUICFlowController.cc index 7c2e3db9e0b..b5275d0818b 100644 --- a/iocore/net/quic/QUICFlowController.cc +++ b/iocore/net/quic/QUICFlowController.cc @@ -96,7 +96,7 @@ QUICFlowController::set_limit(QUICOffset limit) // For RemoteFlowController, caller of this function should also check QUICStreamManager::will_generate_frame() bool -QUICFlowController::will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) +QUICFlowController::will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) { if (!this->_is_level_matched(level)) { return false; @@ -110,7 +110,7 @@ QUICFlowController::will_generate_frame(QUICEncryptionLevel level, ink_hrtime ti */ QUICFrame * QUICFlowController::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t /* connection_credit */, - uint16_t maximum_frame_size, ink_hrtime timestamp) + uint16_t maximum_frame_size, size_t current_packet_size, uint32_t seq_num) { QUICFrame *frame = nullptr; diff --git a/iocore/net/quic/QUICFlowController.h b/iocore/net/quic/QUICFlowController.h index c3cb6371139..62adf9f0093 100644 --- a/iocore/net/quic/QUICFlowController.h +++ b/iocore/net/quic/QUICFlowController.h @@ -60,9 +60,9 @@ class QUICFlowController : public QUICFrameGenerator virtual void set_limit(QUICOffset limit); // QUICFrameGenerator - bool will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) override; + bool will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) override; QUICFrame *generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, - ink_hrtime timestamp) override; + size_t current_packet_size, uint32_t seq_num) override; protected: QUICFlowController(uint64_t initial_limit) : _limit(initial_limit) {} diff --git a/iocore/net/quic/QUICFrame.cc b/iocore/net/quic/QUICFrame.cc index 903c4e96679..0c4e0ba5e13 100644 --- a/iocore/net/quic/QUICFrame.cc +++ b/iocore/net/quic/QUICFrame.cc @@ -58,6 +58,20 @@ QUICFrame::type() const return QUICFrameType::UNKNOWN; } +bool +QUICFrame::ack_eliciting() const +{ + auto type = this->type(); + + return type != QUICFrameType::PADDING && type != QUICFrameType::ACK; +} + +const QUICPacket * +QUICFrame::packet() const +{ + return this->_packet; +} + bool QUICFrame::is_probing_frame() const { @@ -105,22 +119,6 @@ QUICFrame::type(const uint8_t *buf) } } -Ptr -QUICFrame::to_io_buffer_block(size_t limit) const -{ - // FIXME Each classes should override this and drop store(). - // This just wraps store() for now. - - Ptr block = make_ptr(new_IOBufferBlock()); - block->alloc(iobuffer_size_to_index(limit)); - - size_t written_len = 0; - this->store(reinterpret_cast(block->start()), &written_len, limit); - block->fill(written_len); - - return block; -} - int QUICFrame::debug_msg(char *msg, size_t msg_len) const { @@ -149,9 +147,9 @@ QUICStreamFrame::QUICStreamFrame(Ptr &block, QUICStreamId stream_ { } -QUICStreamFrame::QUICStreamFrame(const uint8_t *buf, size_t len) +QUICStreamFrame::QUICStreamFrame(const uint8_t *buf, size_t len, const QUICPacket *packet) : QUICFrame(0, nullptr, packet) { - this->parse(buf, len); + this->parse(buf, len, packet); } QUICStreamFrame::QUICStreamFrame(const QUICStreamFrame &o) @@ -166,10 +164,11 @@ QUICStreamFrame::QUICStreamFrame(const QUICStreamFrame &o) } void -QUICStreamFrame::parse(const uint8_t *buf, size_t len) +QUICStreamFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet) { ink_assert(len >= 1); this->_reset(); + this->_packet = packet; uint8_t *pos = const_cast(buf); this->_has_offset_field = (buf[0] & 0x04) != 0; // "O" of "0b00010OLF" @@ -261,12 +260,6 @@ QUICStreamFrame::is_flow_controlled() const return true; } -size_t -QUICStreamFrame::store(uint8_t *buf, size_t *len, size_t limit) const -{ - return this->store(buf, len, limit, true); -} - int QUICStreamFrame::debug_msg(char *msg, size_t msg_len) const { @@ -333,13 +326,6 @@ QUICStreamFrame::_store_header(uint8_t *buf, size_t *len, bool include_length_fi return *len; } -size_t -QUICStreamFrame::store(uint8_t *buf, size_t *len, size_t limit, bool include_length_field) const -{ - ink_assert(!"Call to_io_buffer_block() instead"); - return 0; -} - QUICStreamId QUICStreamFrame::stream_id() const { @@ -406,9 +392,9 @@ QUICCryptoFrame::QUICCryptoFrame(Ptr &block, QUICOffset offset, Q { } -QUICCryptoFrame::QUICCryptoFrame(const uint8_t *buf, size_t len) +QUICCryptoFrame::QUICCryptoFrame(const uint8_t *buf, size_t len, const QUICPacket *packet) : QUICFrame(0, nullptr, packet) { - this->parse(buf, len); + this->parse(buf, len, packet); } QUICCryptoFrame::QUICCryptoFrame(const QUICCryptoFrame &o) @@ -417,11 +403,12 @@ QUICCryptoFrame::QUICCryptoFrame(const QUICCryptoFrame &o) } void -QUICCryptoFrame::parse(const uint8_t *buf, size_t len) +QUICCryptoFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet) { ink_assert(len >= 1); this->_reset(); - uint8_t *pos = const_cast(buf) + 1; + this->_packet = packet; + uint8_t *pos = const_cast(buf) + 1; size_t field_len = 0; if (!read_varint(pos, LEFT_SPACE(pos), this->_offset, field_len)) { @@ -488,14 +475,34 @@ QUICCryptoFrame::debug_msg(char *msg, size_t msg_len) const this->data_length()); } -size_t -QUICCryptoFrame::store(uint8_t *buf, size_t *len, size_t limit) const +Ptr +QUICCryptoFrame::to_io_buffer_block(size_t limit) const { + Ptr header; + if (limit < this->size()) { - return 0; + return header; } - // Frame Type + // Create header block + size_t written_len = 0; + header = make_ptr(new_IOBufferBlock()); + header->alloc(iobuffer_size_to_index(MAX_HEADER_SIZE)); + this->_store_header(reinterpret_cast(header->start()), &written_len); + header->fill(written_len); + + // Append payload block to a chain + ink_assert(written_len + this->data_length() <= limit); + header->next = this->data(); + + // Return the chain + return header; +} + +size_t +QUICCryptoFrame::_store_header(uint8_t *buf, size_t *len) const +{ + // Type buf[0] = static_cast(QUICFrameType::CRYPTO); *len = 1; @@ -509,10 +516,6 @@ QUICCryptoFrame::store(uint8_t *buf, size_t *len, size_t limit) const QUICIntUtil::write_QUICVariableInt(this->data_length(), buf + *len, &n); *len += n; - // Crypto Data (*) - memcpy(buf + *len, this->data()->start(), this->data_length()); - *len += this->data_length(); - return *len; } @@ -538,18 +541,19 @@ QUICCryptoFrame::data() const // ACK frame // -QUICAckFrame::QUICAckFrame(const uint8_t *buf, size_t len) +QUICAckFrame::QUICAckFrame(const uint8_t *buf, size_t len, const QUICPacket *packet) : QUICFrame(0, nullptr, packet) { - this->parse(buf, len); + this->parse(buf, len, packet); } void -QUICAckFrame::parse(const uint8_t *buf, size_t len) +QUICAckFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet) { ink_assert(len >= 1); this->_reset(); - uint8_t *pos = const_cast(buf) + 1; - bool has_ecn = (buf[0] == static_cast(QUICFrameType::ACK_WITH_ECN)); + this->_packet = packet; + uint8_t *pos = const_cast(buf) + 1; + bool has_ecn = (buf[0] == static_cast(QUICFrameType::ACK_WITH_ECN)); size_t field_len = 0; if (!read_varint(pos, LEFT_SPACE(pos), this->_largest_acknowledged, field_len)) { @@ -666,33 +670,43 @@ QUICAckFrame::size() const return pre_len; } -size_t -QUICAckFrame::store(uint8_t *buf, size_t *len, size_t limit) const +Ptr +QUICAckFrame::to_io_buffer_block(size_t limit) const { + Ptr block; + size_t n = 0; + if (limit < this->size()) { - return 0; + return block; } - uint8_t *p = buf; - size_t n; - *p = static_cast(QUICFrameType::ACK); - ++p; + size_t written_len = 0; + block = make_ptr(new_IOBufferBlock()); + block->alloc(iobuffer_size_to_index(1 + 24)); + uint8_t *block_start = reinterpret_cast(block->start()); - QUICIntUtil::write_QUICVariableInt(this->_largest_acknowledged, p, &n); - p += n; - QUICIntUtil::write_QUICVariableInt(this->_ack_delay, p, &n); - p += n; - QUICIntUtil::write_QUICVariableInt(this->ack_block_count(), p, &n); - p += n; + // Type + block_start[0] = static_cast(QUICFrameType::ACK); + n += 1; - ink_assert(limit >= static_cast(p - buf)); - limit -= (p - buf); - this->_ack_block_section->store(p, &n, limit); - p += n; + // Largest Acknowledged (i) + QUICIntUtil::write_QUICVariableInt(this->_largest_acknowledged, block_start + n, &written_len); + n += written_len; - *len = p - buf; + // Ack Delay (i) + QUICIntUtil::write_QUICVariableInt(this->_ack_delay, block_start + n, &written_len); + n += written_len; - return *len; + // Ack Range Count (i) + QUICIntUtil::write_QUICVariableInt(this->ack_block_count(), block_start + n, &written_len); + n += written_len; + + block->fill(n); + + // First Ack Range (i) + Ack Ranges (*) + block->next = this->_ack_block_section->to_io_buffer_block(limit - n); + + return block; } int @@ -829,29 +843,33 @@ QUICAckFrame::AckBlockSection::size() const return n; } -size_t -QUICAckFrame::AckBlockSection::store(uint8_t *buf, size_t *len, size_t limit) const +Ptr +QUICAckFrame::AckBlockSection::to_io_buffer_block(size_t limit) const { + Ptr block; + size_t n = 0; + if (limit < this->size()) { - return 0; + return block; } - size_t n; - uint8_t *p = buf; + size_t written_len = 0; + block = make_ptr(new_IOBufferBlock()); + block->alloc(iobuffer_size_to_index(limit)); + uint8_t *block_start = reinterpret_cast(block->start()); - QUICIntUtil::write_QUICVariableInt(this->_first_ack_block, p, &n); - p += n; + QUICIntUtil::write_QUICVariableInt(this->_first_ack_block, block_start + n, &written_len); + n += written_len; for (auto &&block : *this) { - QUICIntUtil::write_QUICVariableInt(block.gap(), p, &n); - p += n; - QUICIntUtil::write_QUICVariableInt(block.length(), p, &n); - p += n; + QUICIntUtil::write_QUICVariableInt(block.gap(), block_start + n, &written_len); + n += written_len; + QUICIntUtil::write_QUICVariableInt(block.length(), block_start + n, &written_len); + n += written_len; } - *len = p - buf; - - return *len; + block->fill(n); + return block; } uint64_t @@ -979,30 +997,35 @@ QUICRstStreamFrame::QUICRstStreamFrame(QUICStreamId stream_id, QUICAppErrorCode { } -QUICRstStreamFrame::QUICRstStreamFrame(const uint8_t *buf, size_t len) +QUICRstStreamFrame::QUICRstStreamFrame(const uint8_t *buf, size_t len, const QUICPacket *packet) : QUICFrame(0, nullptr, packet) { - this->parse(buf, len); + this->parse(buf, len, packet); } void -QUICRstStreamFrame::parse(const uint8_t *buf, size_t len) +QUICRstStreamFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet) { ink_assert(len >= 1); this->_reset(); - uint8_t *pos = 1 + const_cast(buf); + this->_packet = packet; + uint8_t *pos = 1 + const_cast(buf); size_t field_len = 0; + + // Stream ID (i) if (!read_varint(pos, LEFT_SPACE(pos), this->_stream_id, field_len)) { return; } - if (LEFT_SPACE(pos) < 2) { + // Error Code (i) + if (LEFT_SPACE(pos) < 1) { + return; + } + if (!read_varint(pos, LEFT_SPACE(pos), this->_error_code, field_len)) { return; } - this->_error_code = QUICIntUtil::read_nbytes_as_uint(pos, 2); - pos += 2; - + // Final Offset (i) if (!read_varint(pos, LEFT_SPACE(pos), this->_final_offset, field_len)) { return; } @@ -1037,36 +1060,49 @@ QUICRstStreamFrame::size() const return this->_size; } - return 1 + QUICVariableInt::size(this->_stream_id) + sizeof(QUICAppErrorCode) + QUICVariableInt::size(this->_final_offset); + return 1 + QUICVariableInt::size(this->_stream_id) + QUICVariableInt::size(this->_error_code) + + QUICVariableInt::size(this->_final_offset); } -size_t -QUICRstStreamFrame::store(uint8_t *buf, size_t *len, size_t limit) const +Ptr +QUICRstStreamFrame::to_io_buffer_block(size_t limit) const { + Ptr block; + size_t n = 0; + if (limit < this->size()) { - return 0; + return block; } - size_t n; - uint8_t *p = buf; - *p = static_cast(QUICFrameType::RESET_STREAM); - ++p; - QUICTypeUtil::write_QUICStreamId(this->_stream_id, p, &n); - p += n; - QUICTypeUtil::write_QUICAppErrorCode(this->_error_code, p, &n); - p += n; - QUICTypeUtil::write_QUICOffset(this->_final_offset, p, &n); - p += n; - - *len = p - buf; + size_t written_len = 0; + block = make_ptr(new_IOBufferBlock()); + block->alloc(iobuffer_size_to_index(1 + 24)); + uint8_t *block_start = reinterpret_cast(block->start()); - return *len; + // Type + block_start[0] = static_cast(QUICFrameType::RESET_STREAM); + n += 1; + + // Stream ID (i) + QUICTypeUtil::write_QUICStreamId(this->_stream_id, block_start + n, &written_len); + n += written_len; + + // Application Error Code (i) + QUICTypeUtil::write_QUICAppErrorCode(this->_error_code, block_start + n, &written_len); + n += written_len; + + // Final Size (i) + QUICTypeUtil::write_QUICOffset(this->_final_offset, block_start + n, &written_len); + n += written_len; + + block->fill(n); + return block; } int QUICRstStreamFrame::debug_msg(char *msg, size_t msg_len) const { - return snprintf(msg, msg_len, "RESET_STREAM size=%zu stream_id=%" PRIu64 " code=0x%" PRIx16, this->size(), this->stream_id(), + return snprintf(msg, msg_len, "RESET_STREAM size=%zu stream_id=%" PRIu64 " code=0x%" PRIx64, this->size(), this->stream_id(), this->error_code()); } @@ -1092,17 +1128,18 @@ QUICRstStreamFrame::final_offset() const // PING frame // -QUICPingFrame::QUICPingFrame(const uint8_t *buf, size_t len) +QUICPingFrame::QUICPingFrame(const uint8_t *buf, size_t len, const QUICPacket *packet) : QUICFrame(0, nullptr, packet) { - this->parse(buf, len); + this->parse(buf, len, packet); } void -QUICPingFrame::parse(const uint8_t *buf, size_t len) +QUICPingFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet) { this->_reset(); - this->_valid = true; - this->_size = 1; + this->_packet = packet; + this->_valid = true; + this->_size = 1; } QUICFrameType @@ -1117,33 +1154,52 @@ QUICPingFrame::size() const return 1; } -size_t -QUICPingFrame::store(uint8_t *buf, size_t *len, size_t limit) const +Ptr +QUICPingFrame::to_io_buffer_block(size_t limit) const { + Ptr block; + size_t n = 0; + if (limit < this->size()) { - return 0; + return block; } - *len = this->size(); - buf[0] = static_cast(QUICFrameType::PING); - return *len; + block = make_ptr(new_IOBufferBlock()); + block->alloc(iobuffer_size_to_index(this->size())); + uint8_t *block_start = reinterpret_cast(block->start()); + + // Type + block_start[0] = static_cast(QUICFrameType::PING); + n += 1; + + block->fill(n); + return block; } // // PADDING frame // -QUICPaddingFrame::QUICPaddingFrame(const uint8_t *buf, size_t len) +QUICPaddingFrame::QUICPaddingFrame(const uint8_t *buf, size_t len, const QUICPacket *packet) : QUICFrame(0, nullptr, packet) { - this->parse(buf, len); + this->parse(buf, len, packet); } void -QUICPaddingFrame::parse(const uint8_t *buf, size_t len) +QUICPaddingFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet) { ink_assert(len >= 1); this->_reset(); - this->_valid = true; - this->_size = 1; + this->_packet = packet; + this->_size = 0; + this->_valid = true; + // find out how many padding frames in this buf + for (size_t i = 0; i < len; i++) { + if (*(buf + i) == static_cast(QUICFrameType::PADDING)) { + ++this->_size; + } else { + break; + } + } } QUICFrameType @@ -1155,7 +1211,7 @@ QUICPaddingFrame::type() const size_t QUICPaddingFrame::size() const { - return 1; + return this->_size; } bool @@ -1164,22 +1220,31 @@ QUICPaddingFrame::is_probing_frame() const return true; } -size_t -QUICPaddingFrame::store(uint8_t *buf, size_t *len, size_t limit) const +Ptr +QUICPaddingFrame::to_io_buffer_block(size_t limit) const { + Ptr block; + size_t n = 0; + if (limit < this->size()) { - return 0; + return block; } - buf[0] = static_cast(QUICFrameType::PADDING); - *len = 1; - return *len; + block = make_ptr(new_IOBufferBlock()); + block->alloc(iobuffer_size_to_index(this->_size)); + uint8_t *block_start = reinterpret_cast(block->start()); + + memset(block_start, 0, this->_size); + n = this->_size; + + block->fill(n); + return block; } // // CONNECTION_CLOSE frame // -QUICConnectionCloseFrame::QUICConnectionCloseFrame(uint16_t error_code, QUICFrameType frame_type, uint64_t reason_phrase_length, +QUICConnectionCloseFrame::QUICConnectionCloseFrame(uint64_t error_code, QUICFrameType frame_type, uint64_t reason_phrase_length, const char *reason_phrase, QUICFrameId id, QUICFrameGenerator *owner) : QUICFrame(id, owner), _type(0x1c), @@ -1190,7 +1255,7 @@ QUICConnectionCloseFrame::QUICConnectionCloseFrame(uint16_t error_code, QUICFram { } -QUICConnectionCloseFrame::QUICConnectionCloseFrame(uint16_t error_code, uint64_t reason_phrase_length, const char *reason_phrase, +QUICConnectionCloseFrame::QUICConnectionCloseFrame(uint64_t error_code, uint64_t reason_phrase_length, const char *reason_phrase, QUICFrameId id, QUICFrameGenerator *owner) : QUICFrame(id, owner), _type(0x1d), @@ -1200,9 +1265,10 @@ QUICConnectionCloseFrame::QUICConnectionCloseFrame(uint16_t error_code, uint64_t { } -QUICConnectionCloseFrame::QUICConnectionCloseFrame(const uint8_t *buf, size_t len) +QUICConnectionCloseFrame::QUICConnectionCloseFrame(const uint8_t *buf, size_t len, const QUICPacket *packet) + : QUICFrame(0, nullptr, packet) { - this->parse(buf, len); + this->parse(buf, len, packet); } void @@ -1220,28 +1286,29 @@ QUICConnectionCloseFrame::_reset() } void -QUICConnectionCloseFrame::parse(const uint8_t *buf, size_t len) +QUICConnectionCloseFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet) { ink_assert(len >= 1); this->_reset(); - this->_type = buf[0]; - uint8_t *pos = const_cast(buf) + 1; - - if (LEFT_SPACE(pos) < 2) { - return; - } - - this->_error_code = QUICIntUtil::read_nbytes_as_uint(pos, 2); - pos += 2; + this->_packet = packet; + this->_type = buf[0]; + uint8_t *pos = const_cast(buf) + 1; size_t field_len = 0; uint64_t field = 0; + // Error Code (i) + if (LEFT_SPACE(pos) < 1) { + return; + } + read_varint(pos, LEFT_SPACE(pos), field, field_len); + this->_error_code = field; + if (this->_type == 0x1c) { + // Frame Type (i) if (!read_varint(pos, LEFT_SPACE(pos), field, field_len)) { return; } - this->_frame_type = static_cast(field); /** @@ -1255,16 +1322,21 @@ QUICConnectionCloseFrame::parse(const uint8_t *buf, size_t len) } } + // Reason Phrase Length (i) + if (LEFT_SPACE(pos) < 1) { + return; + } if (!read_varint(pos, LEFT_SPACE(pos), this->_reason_phrase_length, field_len)) { return; } + // Reason Phrase if (LEFT_SPACE(pos) < this->_reason_phrase_length) { return; } - - this->_valid = true; this->_reason_phrase = reinterpret_cast(pos); + + this->_valid = true; pos += this->_reason_phrase_length; this->_size = FRAME_SIZE(pos); } @@ -1282,7 +1354,7 @@ QUICConnectionCloseFrame::size() const return this->_size; } - return 1 + sizeof(QUICTransErrorCode) + QUICVariableInt::size(sizeof(QUICFrameType)) + + return 1 + QUICVariableInt::size(sizeof(QUICTransErrorCode)) + QUICVariableInt::size(sizeof(QUICFrameType)) + QUICVariableInt::size(this->_reason_phrase_length) + this->_reason_phrase_length; } @@ -1292,42 +1364,58 @@ QUICConnectionCloseFrame::size() const PADDING frame in Frame Type field means frame type that triggered the error is unknown. When `_frame_type` is QUICFrameType::UNKNOWN, it's converted to QUICFrameType::PADDING (0x0). */ -size_t -QUICConnectionCloseFrame::store(uint8_t *buf, size_t *len, size_t limit) const +Ptr +QUICConnectionCloseFrame::to_io_buffer_block(size_t limit) const { + Ptr first_block; + size_t n = 0; + if (limit < this->size()) { - return 0; + return first_block; } - size_t n; - uint8_t *p = buf; - *p = this->_type; - ++p; + // Create a block for Error Code(i) and Frame Type(i) + size_t written_len = 0; + first_block = make_ptr(new_IOBufferBlock()); + first_block->alloc(iobuffer_size_to_index(1 + 24)); + uint8_t *block_start = reinterpret_cast(first_block->start()); + + // Type + block_start[0] = this->_type; + n += 1; - // Error Code (16) - QUICTypeUtil::write_QUICTransErrorCode(this->_error_code, p, &n); - p += n; + // Error Code (i) + QUICIntUtil::write_QUICVariableInt(this->_error_code, block_start + n, &written_len); + n += written_len; // Frame Type (i) QUICFrameType frame_type = this->_frame_type; if (frame_type == QUICFrameType::UNKNOWN) { frame_type = QUICFrameType::PADDING; } - *p = static_cast(frame_type); - ++p; + QUICIntUtil::write_QUICVariableInt(static_cast(frame_type), block_start + n, &written_len); + n += written_len; // Reason Phrase Length (i) - QUICIntUtil::write_QUICVariableInt(this->_reason_phrase_length, p, &n); - p += n; + QUICIntUtil::write_QUICVariableInt(this->_reason_phrase_length, block_start + n, &written_len); + n += written_len; + + first_block->fill(n); + + // Create a block for reason if necessary + if (this->_reason_phrase_length != 0) { + // Reason Phrase (*) + Ptr reason_block = make_ptr(new_IOBufferBlock()); + reason_block->alloc(iobuffer_size_to_index(this->_reason_phrase_length)); + memcpy(reinterpret_cast(reason_block->start()), this->_reason_phrase, this->_reason_phrase_length); + reason_block->fill(this->_reason_phrase_length); - // Reason Phrase (*) - if (this->_reason_phrase_length > 0) { - memcpy(p, this->_reason_phrase, this->_reason_phrase_length); - p += this->_reason_phrase_length; + // Append reason block to the first block + first_block->next = reason_block; } - *len = p - buf; - return *len; + // Return the chain + return first_block; } int @@ -1400,17 +1488,18 @@ QUICMaxDataFrame::_reset() this->_size = 0; } -QUICMaxDataFrame::QUICMaxDataFrame(const uint8_t *buf, size_t len) +QUICMaxDataFrame::QUICMaxDataFrame(const uint8_t *buf, size_t len, const QUICPacket *packet) : QUICFrame(0, nullptr, packet) { - this->parse(buf, len); + this->parse(buf, len, packet); } void -QUICMaxDataFrame::parse(const uint8_t *buf, size_t len) +QUICMaxDataFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet) { ink_assert(len >= 1); this->_reset(); - uint8_t *pos = 1 + const_cast(buf); + this->_packet = packet; + uint8_t *pos = 1 + const_cast(buf); size_t field_len = 0; if (!read_varint(pos, LEFT_SPACE(pos), this->_maximum_data, field_len)) { @@ -1437,22 +1526,31 @@ QUICMaxDataFrame::size() const return sizeof(QUICFrameType) + QUICVariableInt::size(this->_maximum_data); } -size_t -QUICMaxDataFrame::store(uint8_t *buf, size_t *len, size_t limit) const +Ptr +QUICMaxDataFrame::to_io_buffer_block(size_t limit) const { + Ptr block; + size_t n = 0; + if (limit < this->size()) { - return 0; + return block; } - size_t n; - uint8_t *p = buf; - *p = static_cast(QUICFrameType::MAX_DATA); - ++p; - QUICTypeUtil::write_QUICMaxData(this->_maximum_data, p, &n); - p += n; + size_t written_len = 0; + block = make_ptr(new_IOBufferBlock()); + block->alloc(iobuffer_size_to_index(1 + sizeof(size_t))); + uint8_t *block_start = reinterpret_cast(block->start()); - *len = p - buf; - return *len; + // Type + block_start[0] = static_cast(QUICFrameType::MAX_DATA); + n += 1; + + // Maximum Data (i) + QUICTypeUtil::write_QUICMaxData(this->_maximum_data, block_start + n, &written_len); + n += written_len; + + block->fill(n); + return block; } int @@ -1490,17 +1588,19 @@ QUICMaxStreamDataFrame::_reset() this->_size = 0; } -QUICMaxStreamDataFrame::QUICMaxStreamDataFrame(const uint8_t *buf, size_t len) +QUICMaxStreamDataFrame::QUICMaxStreamDataFrame(const uint8_t *buf, size_t len, const QUICPacket *packet) + : QUICFrame(0, nullptr, packet) { - this->parse(buf, len); + this->parse(buf, len, packet); } void -QUICMaxStreamDataFrame::parse(const uint8_t *buf, size_t len) +QUICMaxStreamDataFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet) { ink_assert(len >= 1); this->_reset(); - uint8_t *pos = const_cast(buf) + 1; + this->_packet = packet; + uint8_t *pos = const_cast(buf) + 1; size_t field_len = 0; if (!read_varint(pos, LEFT_SPACE(pos), this->_stream_id, field_len)) { @@ -1531,23 +1631,35 @@ QUICMaxStreamDataFrame::size() const return sizeof(QUICFrameType) + QUICVariableInt::size(this->_maximum_stream_data) + QUICVariableInt::size(this->_stream_id); } -size_t -QUICMaxStreamDataFrame::store(uint8_t *buf, size_t *len, size_t limit) const +Ptr +QUICMaxStreamDataFrame::to_io_buffer_block(size_t limit) const { + Ptr block; + size_t n = 0; + if (limit < this->size()) { - return 0; + return block; } - size_t n; - uint8_t *p = buf; - *p = static_cast(QUICFrameType::MAX_STREAM_DATA); - ++p; - QUICTypeUtil::write_QUICStreamId(this->_stream_id, p, &n); - p += n; - QUICTypeUtil::write_QUICMaxData(this->_maximum_stream_data, p, &n); - p += n; - - *len = p - buf; - return *len; + + size_t written_len = 0; + block = make_ptr(new_IOBufferBlock()); + block->alloc(iobuffer_size_to_index(1 + sizeof(uint64_t) + sizeof(size_t))); + uint8_t *block_start = reinterpret_cast(block->start()); + + // Type + block_start[0] = static_cast(QUICFrameType::MAX_STREAM_DATA); + n += 1; + + // Stream ID (i) + QUICTypeUtil::write_QUICStreamId(this->_stream_id, block_start + n, &written_len); + n += written_len; + + // Maximum Stream Data (i) + QUICTypeUtil::write_QUICMaxData(this->_maximum_stream_data, block_start + n, &written_len); + n += written_len; + + block->fill(n); + return block; } int @@ -1589,17 +1701,18 @@ QUICMaxStreamsFrame::_reset() this->_size = 0; } -QUICMaxStreamsFrame::QUICMaxStreamsFrame(const uint8_t *buf, size_t len) +QUICMaxStreamsFrame::QUICMaxStreamsFrame(const uint8_t *buf, size_t len, const QUICPacket *packet) : QUICFrame(0, nullptr, packet) { - this->parse(buf, len); + this->parse(buf, len, packet); } void -QUICMaxStreamsFrame::parse(const uint8_t *buf, size_t len) +QUICMaxStreamsFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet) { ink_assert(len >= 1); this->_reset(); - uint8_t *pos = const_cast(buf) + 1; + this->_packet = packet; + uint8_t *pos = const_cast(buf) + 1; size_t field_len = 0; if (!read_varint(pos, LEFT_SPACE(pos), this->_maximum_streams, field_len)) { @@ -1626,22 +1739,31 @@ QUICMaxStreamsFrame::size() const return sizeof(QUICFrameType) + QUICVariableInt::size(this->_maximum_streams); } -size_t -QUICMaxStreamsFrame::store(uint8_t *buf, size_t *len, size_t limit) const +Ptr +QUICMaxStreamsFrame::to_io_buffer_block(size_t limit) const { + Ptr block; + size_t n = 0; + if (limit < this->size()) { - return 0; + return block; } - size_t n; - uint8_t *p = buf; - *p = static_cast(QUICFrameType::MAX_STREAMS); - ++p; - QUICTypeUtil::write_QUICStreamId(this->_maximum_streams, p, &n); - p += n; + size_t written_len = 0; + block = make_ptr(new_IOBufferBlock()); + block->alloc(iobuffer_size_to_index(1 + sizeof(size_t))); + uint8_t *block_start = reinterpret_cast(block->start()); - *len = p - buf; - return *len; + // Type + block_start[0] = static_cast(QUICFrameType::MAX_STREAMS); + n += 1; + + // Maximum Streams (i) + QUICTypeUtil::write_QUICStreamId(this->_maximum_streams, block_start + n, &written_len); + n += written_len; + + block->fill(n); + return block; } uint64_t @@ -1653,9 +1775,9 @@ QUICMaxStreamsFrame::maximum_streams() const // // DATA_BLOCKED frame // -QUICDataBlockedFrame::QUICDataBlockedFrame(const uint8_t *buf, size_t len) +QUICDataBlockedFrame::QUICDataBlockedFrame(const uint8_t *buf, size_t len, const QUICPacket *packet) : QUICFrame(0, nullptr, packet) { - this->parse(buf, len); + this->parse(buf, len, packet); } void @@ -1670,11 +1792,12 @@ QUICDataBlockedFrame::_reset() } void -QUICDataBlockedFrame::parse(const uint8_t *buf, size_t len) +QUICDataBlockedFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet) { ink_assert(len >= 1); this->_reset(); - uint8_t *pos = const_cast(buf) + 1; + this->_packet = packet; + uint8_t *pos = const_cast(buf) + 1; size_t field_len = 0; if (!read_varint(pos, LEFT_SPACE(pos), this->_offset, field_len)) { @@ -1707,24 +1830,31 @@ QUICDataBlockedFrame::size() const return sizeof(QUICFrameType) + QUICVariableInt::size(this->offset()); } -size_t -QUICDataBlockedFrame::store(uint8_t *buf, size_t *len, size_t limit) const +Ptr +QUICDataBlockedFrame::to_io_buffer_block(size_t limit) const { + Ptr block; + size_t n = 0; + if (limit < this->size()) { - return 0; + return block; } - size_t n; - uint8_t *p = buf; + size_t written_len = 0; + block = make_ptr(new_IOBufferBlock()); + block->alloc(iobuffer_size_to_index(1 + sizeof(size_t))); + uint8_t *block_start = reinterpret_cast(block->start()); - *p = static_cast(QUICFrameType::DATA_BLOCKED); - ++p; - QUICTypeUtil::write_QUICOffset(this->_offset, p, &n); - p += n; + // Type + block_start[0] = static_cast(QUICFrameType::DATA_BLOCKED); + n += 1; - *len = p - buf; + // Data Limit (i) + QUICTypeUtil::write_QUICOffset(this->_offset, block_start + n, &written_len); + n += written_len; - return *len; + block->fill(n); + return block; } QUICOffset @@ -1736,9 +1866,10 @@ QUICDataBlockedFrame::offset() const // // STREAM_DATA_BLOCKED frame // -QUICStreamDataBlockedFrame::QUICStreamDataBlockedFrame(const uint8_t *buf, size_t len) +QUICStreamDataBlockedFrame::QUICStreamDataBlockedFrame(const uint8_t *buf, size_t len, const QUICPacket *packet) + : QUICFrame(0, nullptr, packet) { - this->parse(buf, len); + this->parse(buf, len, packet); } void @@ -1754,11 +1885,12 @@ QUICStreamDataBlockedFrame::_reset() } void -QUICStreamDataBlockedFrame::parse(const uint8_t *buf, size_t len) +QUICStreamDataBlockedFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet) { ink_assert(len >= 1); this->_reset(); - uint8_t *pos = const_cast(buf) + 1; + this->_packet = packet; + uint8_t *pos = const_cast(buf) + 1; size_t field_len = 0; if (!read_varint(pos, LEFT_SPACE(pos), this->_stream_id, field_len)) { @@ -1796,25 +1928,35 @@ QUICStreamDataBlockedFrame::size() const return sizeof(QUICFrameType) + QUICVariableInt::size(this->_offset) + QUICVariableInt::size(this->_stream_id); } -size_t -QUICStreamDataBlockedFrame::store(uint8_t *buf, size_t *len, size_t limit) const +Ptr +QUICStreamDataBlockedFrame::to_io_buffer_block(size_t limit) const { + Ptr block; + size_t n = 0; + if (limit < this->size()) { - return 0; + return block; } - size_t n; - uint8_t *p = buf; - *p = static_cast(QUICFrameType::STREAM_DATA_BLOCKED); - ++p; - QUICTypeUtil::write_QUICStreamId(this->_stream_id, p, &n); - p += n; - QUICTypeUtil::write_QUICOffset(this->_offset, p, &n); - p += n; + size_t written_len = 0; + block = make_ptr(new_IOBufferBlock()); + block->alloc(iobuffer_size_to_index(1 + sizeof(size_t))); + uint8_t *block_start = reinterpret_cast(block->start()); - *len = p - buf; + // Type + block_start[0] = static_cast(QUICFrameType::STREAM_DATA_BLOCKED); + n += 1; - return *len; + // Stream ID (i) + QUICTypeUtil::write_QUICStreamId(this->_stream_id, block_start + n, &written_len); + n += written_len; + + // Data Limit (i) + QUICTypeUtil::write_QUICOffset(this->_offset, block_start + n, &written_len); + n += written_len; + + block->fill(n); + return block; } QUICStreamId @@ -1832,9 +1974,10 @@ QUICStreamDataBlockedFrame::offset() const // // STREAMS_BLOCKED frame // -QUICStreamIdBlockedFrame::QUICStreamIdBlockedFrame(const uint8_t *buf, size_t len) +QUICStreamIdBlockedFrame::QUICStreamIdBlockedFrame(const uint8_t *buf, size_t len, const QUICPacket *packet) + : QUICFrame(0, nullptr, packet) { - this->parse(buf, len); + this->parse(buf, len, packet); } void @@ -1849,11 +1992,12 @@ QUICStreamIdBlockedFrame::_reset() } void -QUICStreamIdBlockedFrame::parse(const uint8_t *buf, size_t len) +QUICStreamIdBlockedFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet) { ink_assert(len >= 1); this->_reset(); - uint8_t *pos = const_cast(buf) + 1; + this->_packet = packet; + uint8_t *pos = const_cast(buf) + 1; size_t field_len = 0; if (!read_varint(pos, LEFT_SPACE(pos), this->_stream_id, field_len)) { @@ -1880,23 +2024,31 @@ QUICStreamIdBlockedFrame::size() const return sizeof(QUICFrameType) + QUICVariableInt::size(this->_stream_id); } -size_t -QUICStreamIdBlockedFrame::store(uint8_t *buf, size_t *len, size_t limit) const +Ptr +QUICStreamIdBlockedFrame::to_io_buffer_block(size_t limit) const { + Ptr block; + size_t n = 0; + if (limit < this->size()) { - return 0; + return block; } - size_t n; - uint8_t *p = buf; + size_t written_len = 0; + block = make_ptr(new_IOBufferBlock()); + block->alloc(iobuffer_size_to_index(1 + sizeof(size_t))); + uint8_t *block_start = reinterpret_cast(block->start()); - *p = static_cast(QUICFrameType::STREAMS_BLOCKED); - ++p; - QUICTypeUtil::write_QUICStreamId(this->_stream_id, p, &n); - p += n; + // Type + block_start[0] = static_cast(QUICFrameType::STREAMS_BLOCKED); + n += 1; - *len = p - buf; - return *len; + // Stream Limit (i) + QUICTypeUtil::write_QUICStreamId(this->_stream_id, block_start + n, &written_len); + n += written_len; + + block->fill(n); + return block; } QUICStreamId @@ -1908,16 +2060,18 @@ QUICStreamIdBlockedFrame::stream_id() const // // NEW_CONNECTION_ID frame // -QUICNewConnectionIdFrame::QUICNewConnectionIdFrame(const uint8_t *buf, size_t len) +QUICNewConnectionIdFrame::QUICNewConnectionIdFrame(const uint8_t *buf, size_t len, const QUICPacket *packet) + : QUICFrame(0, nullptr, packet) { - this->parse(buf, len); + this->parse(buf, len, packet); } void QUICNewConnectionIdFrame::_reset() { - this->_sequence = 0; - this->_connection_id = QUICConnectionId::ZERO(); + this->_sequence = 0; + this->_retire_prior_to = 0; + this->_connection_id = QUICConnectionId::ZERO(); this->_owner = nullptr; this->_id = 0; @@ -1926,38 +2080,49 @@ QUICNewConnectionIdFrame::_reset() } void -QUICNewConnectionIdFrame::parse(const uint8_t *buf, size_t len) +QUICNewConnectionIdFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet) { ink_assert(len >= 1); this->_reset(); - uint8_t *pos = const_cast(buf) + 1; + this->_packet = packet; + uint8_t *pos = const_cast(buf) + 1; + // Sequence Number (i) size_t field_len = 0; if (!read_varint(pos, LEFT_SPACE(pos), this->_sequence, field_len)) { return; } + // Retire Prior To (i) if (LEFT_SPACE(pos) < 1) { return; } + if (!read_varint(pos, LEFT_SPACE(pos), this->_retire_prior_to, field_len)) { + return; + } + // Length (8) + if (LEFT_SPACE(pos) < 1) { + return; + } size_t cid_len = *pos; pos += 1; + // Connection ID (8..160) if (LEFT_SPACE(pos) < cid_len) { return; } - this->_connection_id = QUICTypeUtil::read_QUICConnectionId(pos, cid_len); pos += cid_len; - if (LEFT_SPACE(pos) < 16) { + // Stateless Reset Token (128) + if (LEFT_SPACE(pos) < QUICStatelessResetToken::LEN) { return; } this->_stateless_reset_token = QUICStatelessResetToken(pos); this->_valid = true; - this->_size = FRAME_SIZE(pos) + 16; + this->_size = FRAME_SIZE(pos) + QUICStatelessResetToken::LEN; } QUICFrameType @@ -1973,31 +2138,52 @@ QUICNewConnectionIdFrame::size() const return this->_size; } - return sizeof(QUICFrameType) + QUICVariableInt::size(this->_sequence) + 1 + this->_connection_id.length() + 16; + return sizeof(QUICFrameType) + QUICVariableInt::size(this->_sequence) + QUICVariableInt::size(this->_retire_prior_to) + 1 + + this->_connection_id.length() + QUICStatelessResetToken::LEN; } -size_t -QUICNewConnectionIdFrame::store(uint8_t *buf, size_t *len, size_t limit) const +Ptr +QUICNewConnectionIdFrame::to_io_buffer_block(size_t limit) const { + Ptr block; + size_t n = 0; + if (limit < this->size()) { - return 0; + return block; } - size_t n; - uint8_t *p = buf; - *p = static_cast(QUICFrameType::NEW_CONNECTION_ID); - ++p; - QUICIntUtil::write_QUICVariableInt(this->_sequence, p, &n); - p += n; - *p = this->_connection_id.length(); - p += 1; - QUICTypeUtil::write_QUICConnectionId(this->_connection_id, p, &n); - p += n; - memcpy(p, this->_stateless_reset_token.buf(), QUICStatelessResetToken::LEN); - p += QUICStatelessResetToken::LEN; - - *len = p - buf; - return *len; + size_t written_len = 0; + block = make_ptr(new_IOBufferBlock()); + block->alloc(iobuffer_size_to_index(1 + sizeof(uint64_t) + sizeof(uint64_t) + 1 + QUICConnectionId::MAX_LENGTH + + QUICStatelessResetToken::LEN)); + uint8_t *block_start = reinterpret_cast(block->start()); + + // Type + block_start[0] = static_cast(QUICFrameType::NEW_CONNECTION_ID); + n += 1; + + // Sequence Number (i) + QUICIntUtil::write_QUICVariableInt(this->_sequence, block_start + n, &written_len); + n += written_len; + + // Retire Prior To (i) + QUICIntUtil::write_QUICVariableInt(this->_retire_prior_to, block_start + n, &written_len); + n += written_len; + + // Length (8) + *(block_start + n) = this->_connection_id.length(); + n += 1; + + // Connection ID (8..160) + QUICTypeUtil::write_QUICConnectionId(this->_connection_id, block_start + n, &written_len); + n += written_len; + + // Stateless Reset Token (128) + memcpy(block_start + n, this->_stateless_reset_token.buf(), QUICStatelessResetToken::LEN); + n += QUICStatelessResetToken::LEN; + + block->fill(n); + return block; } int @@ -2006,7 +2192,8 @@ QUICNewConnectionIdFrame::debug_msg(char *msg, size_t msg_len) const char cid_str[QUICConnectionId::MAX_HEX_STR_LENGTH]; this->connection_id().hex(cid_str, QUICConnectionId::MAX_HEX_STR_LENGTH); - return snprintf(msg, msg_len, "NEW_CONNECTION_ID size=%zu seq=%" PRIu64 " cid=0x%s", this->size(), this->sequence(), cid_str); + return snprintf(msg, msg_len, "NEW_CONNECTION_ID size=%zu seq=%" PRIu64 " rpt=%" PRIu64 " cid=0x%s", this->size(), + this->sequence(), this->retire_prior_to(), cid_str); } uint64_t @@ -2015,6 +2202,12 @@ QUICNewConnectionIdFrame::sequence() const return this->_sequence; } +uint64_t +QUICNewConnectionIdFrame::retire_prior_to() const +{ + return this->_retire_prior_to; +} + QUICConnectionId QUICNewConnectionIdFrame::connection_id() const { @@ -2049,30 +2242,35 @@ QUICStopSendingFrame::_reset() this->_size = 0; } -QUICStopSendingFrame::QUICStopSendingFrame(const uint8_t *buf, size_t len) +QUICStopSendingFrame::QUICStopSendingFrame(const uint8_t *buf, size_t len, const QUICPacket *packet) : QUICFrame(0, nullptr, packet) { - this->parse(buf, len); + this->parse(buf, len, packet); } void -QUICStopSendingFrame::parse(const uint8_t *buf, size_t len) +QUICStopSendingFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet) { ink_assert(len >= 1); this->_reset(); - uint8_t *pos = const_cast(buf) + 1; + this->_packet = packet; + uint8_t *pos = const_cast(buf) + 1; + // Stream ID (i) size_t field_len = 0; if (!read_varint(pos, LEFT_SPACE(pos), this->_stream_id, field_len)) { return; } - if (LEFT_SPACE(pos) < 2) { + // Error Code (i) + if (LEFT_SPACE(pos) < 1) { + return; + } + if (!read_varint(pos, LEFT_SPACE(pos), this->_error_code, field_len)) { return; } - this->_error_code = static_cast(QUICIntUtil::read_nbytes_as_uint(pos, 2)); - this->_valid = true; - this->_size = FRAME_SIZE(pos) + 2; + this->_valid = true; + this->_size = FRAME_SIZE(pos); } QUICFrameType @@ -2088,27 +2286,38 @@ QUICStopSendingFrame::size() const return this->_size; } - return sizeof(QUICFrameType) + QUICVariableInt::size(this->_stream_id) + sizeof(QUICAppErrorCode); + return sizeof(QUICFrameType) + QUICVariableInt::size(this->_stream_id) + QUICVariableInt::size(sizeof(QUICAppErrorCode)); } -size_t -QUICStopSendingFrame::store(uint8_t *buf, size_t *len, size_t limit) const +Ptr +QUICStopSendingFrame::to_io_buffer_block(size_t limit) const { + Ptr block; + size_t n = 0; + if (limit < this->size()) { - return 0; + return block; } - size_t n; - uint8_t *p = buf; - *p = static_cast(QUICFrameType::STOP_SENDING); - ++p; - QUICTypeUtil::write_QUICStreamId(this->_stream_id, p, &n); - p += n; - QUICTypeUtil::write_QUICAppErrorCode(this->_error_code, p, &n); - p += n; - - *len = p - buf; - return *len; + size_t written_len = 0; + block = make_ptr(new_IOBufferBlock()); + block->alloc(iobuffer_size_to_index(1 + 24)); + uint8_t *block_start = reinterpret_cast(block->start()); + + // Type + block_start[0] = static_cast(QUICFrameType::STOP_SENDING); + n += 1; + + // Stream ID (i) + QUICTypeUtil::write_QUICStreamId(this->_stream_id, block_start + n, &written_len); + n += written_len; + + // Application Error Code (i) + QUICTypeUtil::write_QUICAppErrorCode(this->_error_code, block_start + n, &written_len); + n += written_len; + + block->fill(n); + return block; } QUICAppErrorCode @@ -2126,9 +2335,10 @@ QUICStopSendingFrame::stream_id() const // // PATH_CHALLENGE frame // -QUICPathChallengeFrame::QUICPathChallengeFrame(const uint8_t *buf, size_t len) +QUICPathChallengeFrame::QUICPathChallengeFrame(const uint8_t *buf, size_t len, const QUICPacket *packet) + : QUICFrame(0, nullptr, packet) { - this->parse(buf, len); + this->parse(buf, len, packet); } void @@ -2142,11 +2352,12 @@ QUICPathChallengeFrame::_reset() } void -QUICPathChallengeFrame::parse(const uint8_t *buf, size_t len) +QUICPathChallengeFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet) { ink_assert(len >= 1); this->_reset(); - uint8_t *pos = const_cast(buf) + 1; + this->_packet = packet; + uint8_t *pos = const_cast(buf) + 1; if (LEFT_SPACE(pos) < QUICPathChallengeFrame::DATA_LEN) { return; @@ -2180,19 +2391,38 @@ QUICPathChallengeFrame::is_probing_frame() const return true; } -size_t -QUICPathChallengeFrame::store(uint8_t *buf, size_t *len, size_t limit) const +Ptr +QUICPathChallengeFrame::to_io_buffer_block(size_t limit) const { + Ptr block; + size_t n = 0; + if (limit < this->size()) { - return 0; + return block; } - *len = this->size(); + block = make_ptr(new_IOBufferBlock()); + block->alloc(iobuffer_size_to_index(1 + QUICPathChallengeFrame::DATA_LEN)); + uint8_t *block_start = reinterpret_cast(block->start()); - buf[0] = static_cast(QUICFrameType::PATH_CHALLENGE); - memcpy(buf + 1, this->data(), QUICPathChallengeFrame::DATA_LEN); + // Type + block_start[0] = static_cast(QUICFrameType::PATH_CHALLENGE); + n += 1; - return *len; + // Data (64) + memcpy(block_start + n, this->data(), QUICPathChallengeFrame::DATA_LEN); + n += QUICPathChallengeFrame::DATA_LEN; + + block->fill(n); + return block; +} + +int +QUICPathChallengeFrame::debug_msg(char *msg, size_t msg_len) const +{ + auto data = this->data(); + return snprintf(msg, msg_len, "PATH_CHALLENGE size=%zu data=0x%02x%02x%02x%02x%02x%02x%02x%02x", this->size(), data[0], data[1], + data[2], data[3], data[4], data[5], data[6], data[7]); } const uint8_t * @@ -2204,9 +2434,10 @@ QUICPathChallengeFrame::data() const // // PATH_RESPONSE frame // -QUICPathResponseFrame::QUICPathResponseFrame(const uint8_t *buf, size_t len) +QUICPathResponseFrame::QUICPathResponseFrame(const uint8_t *buf, size_t len, const QUICPacket *packet) + : QUICFrame(0, nullptr, packet) { - this->parse(buf, len); + this->parse(buf, len, packet); } void @@ -2219,12 +2450,39 @@ QUICPathResponseFrame::_reset() this->_size = 0; } +Ptr +QUICPathResponseFrame::to_io_buffer_block(size_t limit) const +{ + Ptr block; + size_t n = 0; + + if (limit < this->size()) { + return block; + } + + block = make_ptr(new_IOBufferBlock()); + block->alloc(iobuffer_size_to_index(1 + QUICPathResponseFrame::DATA_LEN)); + uint8_t *block_start = reinterpret_cast(block->start()); + + // Type + block_start[0] = static_cast(QUICFrameType::PATH_RESPONSE); + n += 1; + + // Data (64) + memcpy(block_start + n, this->data(), QUICPathChallengeFrame::DATA_LEN); + n += QUICPathChallengeFrame::DATA_LEN; + + block->fill(n); + return block; +} + void -QUICPathResponseFrame::parse(const uint8_t *buf, size_t len) +QUICPathResponseFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet) { ink_assert(len >= 1); this->_reset(); - uint8_t *pos = const_cast(buf) + 1; + this->_packet = packet; + uint8_t *pos = const_cast(buf) + 1; if (LEFT_SPACE(pos) < QUICPathChallengeFrame::DATA_LEN) { return; @@ -2254,19 +2512,12 @@ QUICPathResponseFrame::is_probing_frame() const return true; } -size_t -QUICPathResponseFrame::store(uint8_t *buf, size_t *len, size_t limit) const +int +QUICPathResponseFrame::debug_msg(char *msg, size_t msg_len) const { - if (limit < this->size()) { - return 0; - } - - *len = this->size(); - - buf[0] = static_cast(QUICFrameType::PATH_RESPONSE); - memcpy(buf + 1, this->data(), QUICPathResponseFrame::DATA_LEN); - - return *len; + auto data = this->data(); + return snprintf(msg, msg_len, "PATH_RESPONSE size=%zu data=0x%02x%02x%02x%02x%02x%02x%02x%02x", this->size(), data[0], data[1], + data[2], data[3], data[4], data[5], data[6], data[7]); } const uint8_t * @@ -2278,9 +2529,9 @@ QUICPathResponseFrame::data() const // // QUICNewTokenFrame // -QUICNewTokenFrame::QUICNewTokenFrame(const uint8_t *buf, size_t len) +QUICNewTokenFrame::QUICNewTokenFrame(const uint8_t *buf, size_t len, const QUICPacket *packet) : QUICFrame(0, nullptr, packet) { - this->parse(buf, len); + this->parse(buf, len, packet); } void @@ -2296,11 +2547,12 @@ QUICNewTokenFrame::_reset() } void -QUICNewTokenFrame::parse(const uint8_t *buf, size_t len) +QUICNewTokenFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet) { ink_assert(len >= 1); this->_reset(); - uint8_t *pos = const_cast(buf) + 1; + this->_packet = packet; + uint8_t *pos = const_cast(buf) + 1; size_t field_len = 0; if (!read_varint(pos, LEFT_SPACE(pos), this->_token_length, field_len)) { @@ -2333,30 +2585,35 @@ QUICNewTokenFrame::size() const return 1 + QUICVariableInt::size(this->_token_length) + this->token_length(); } -size_t -QUICNewTokenFrame::store(uint8_t *buf, size_t *len, size_t limit) const +Ptr +QUICNewTokenFrame::to_io_buffer_block(size_t limit) const { + Ptr block; + size_t n = 0; + if (limit < this->size()) { - return 0; + return block; } - uint8_t *p = buf; + size_t written_len = 0; + block = make_ptr(new_IOBufferBlock()); + block->alloc(iobuffer_size_to_index(1 + 24)); + uint8_t *block_start = reinterpret_cast(block->start()); - // Type (i) - *p = static_cast(QUICFrameType::NEW_TOKEN); - ++p; + // Type + block_start[0] = static_cast(QUICFrameType::NEW_TOKEN); + n += 1; // Token Length (i) - size_t n; - QUICIntUtil::write_QUICVariableInt(this->_token_length, p, &n); - p += n; + QUICIntUtil::write_QUICVariableInt(this->_token_length, block_start + n, &written_len); + n += written_len; // Token (*) - memcpy(p, this->token(), this->token_length()); - p += this->token_length(); + memcpy(block_start + n, this->token(), this->token_length()); + n += this->token_length(); - *len = p - buf; - return *len; + block->fill(n); + return block; } uint64_t @@ -2374,9 +2631,10 @@ QUICNewTokenFrame::token() const // // RETIRE_CONNECTION_ID frame // -QUICRetireConnectionIdFrame::QUICRetireConnectionIdFrame(const uint8_t *buf, size_t len) +QUICRetireConnectionIdFrame::QUICRetireConnectionIdFrame(const uint8_t *buf, size_t len, const QUICPacket *packet) + : QUICFrame(0, nullptr, packet) { - this->parse(buf, len); + this->parse(buf, len, packet); } void @@ -2392,11 +2650,12 @@ QUICRetireConnectionIdFrame::_reset() } void -QUICRetireConnectionIdFrame::parse(const uint8_t *buf, size_t len) +QUICRetireConnectionIdFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet) { ink_assert(len >= 1); this->_reset(); - uint8_t *pos = const_cast(buf) + 1; + this->_packet = packet; + uint8_t *pos = const_cast(buf) + 1; size_t field_len = 0; if (!read_varint(pos, LEFT_SPACE(pos), this->_seq_num, field_len)) { @@ -2423,23 +2682,31 @@ QUICRetireConnectionIdFrame::size() const return sizeof(QUICFrameType) + QUICVariableInt::size(this->_seq_num); } -size_t -QUICRetireConnectionIdFrame::store(uint8_t *buf, size_t *len, size_t limit) const +Ptr +QUICRetireConnectionIdFrame::to_io_buffer_block(size_t limit) const { + Ptr block; + size_t n = 0; + if (limit < this->size()) { - return 0; + return block; } - size_t n; - uint8_t *p = buf; - *p = static_cast(QUICFrameType::RETIRE_CONNECTION_ID); - ++p; - QUICIntUtil::write_QUICVariableInt(this->_seq_num, p, &n); - p += n; + size_t written_len = 0; + block = make_ptr(new_IOBufferBlock()); + block->alloc(iobuffer_size_to_index(1 + sizeof(uint64_t))); + uint8_t *block_start = reinterpret_cast(block->start()); - *len = p - buf; + // Type + block_start[0] = static_cast(QUICFrameType::RETIRE_CONNECTION_ID); + n += 1; - return *len; + // Sequence Number (i) + QUICIntUtil::write_QUICVariableInt(this->_seq_num, block_start + n, &written_len); + n += written_len; + + block->fill(n); + return block; } int @@ -2470,15 +2737,17 @@ QUICUnknownFrame::size() const return 0; } -size_t -QUICUnknownFrame::store(uint8_t *buf, size_t *len, size_t limit) const +Ptr +QUICUnknownFrame::to_io_buffer_block(size_t limit) const { - return 0; + Ptr block; + return block; } void -QUICUnknownFrame::parse(const uint8_t *buf, size_t len) +QUICUnknownFrame::parse(const uint8_t *buf, size_t len, const QUICPacket *packet) { + this->_packet = packet; } int @@ -2492,65 +2761,65 @@ QUICUnknownFrame::debug_msg(char *msg, size_t msg_len) const // QUICFrame * -QUICFrameFactory::create(uint8_t *buf, const uint8_t *src, size_t len) +QUICFrameFactory::create(uint8_t *buf, const uint8_t *src, size_t len, const QUICPacket *packet) { switch (QUICFrame::type(src)) { case QUICFrameType::STREAM: - new (buf) QUICStreamFrame(src, len); + new (buf) QUICStreamFrame(src, len, packet); return reinterpret_cast(buf); case QUICFrameType::CRYPTO: - new (buf) QUICCryptoFrame(src, len); + new (buf) QUICCryptoFrame(src, len, packet); return reinterpret_cast(buf); case QUICFrameType::ACK: - new (buf) QUICAckFrame(src, len); + new (buf) QUICAckFrame(src, len, packet); return reinterpret_cast(buf); case QUICFrameType::PADDING: - new (buf) QUICPaddingFrame(src, len); + new (buf) QUICPaddingFrame(src, len, packet); return reinterpret_cast(buf); case QUICFrameType::RESET_STREAM: - new (buf) QUICRstStreamFrame(src, len); + new (buf) QUICRstStreamFrame(src, len, packet); return reinterpret_cast(buf); case QUICFrameType::CONNECTION_CLOSE: - new (buf) QUICConnectionCloseFrame(src, len); + new (buf) QUICConnectionCloseFrame(src, len, packet); return reinterpret_cast(buf); case QUICFrameType::MAX_DATA: - new (buf) QUICMaxDataFrame(src, len); + new (buf) QUICMaxDataFrame(src, len, packet); return reinterpret_cast(buf); case QUICFrameType::MAX_STREAM_DATA: - new (buf) QUICMaxStreamDataFrame(src, len); + new (buf) QUICMaxStreamDataFrame(src, len, packet); return reinterpret_cast(buf); case QUICFrameType::MAX_STREAMS: - new (buf) QUICMaxStreamsFrame(src, len); + new (buf) QUICMaxStreamsFrame(src, len, packet); return reinterpret_cast(buf); case QUICFrameType::PING: - new (buf) QUICPingFrame(src, len); + new (buf) QUICPingFrame(src, len, packet); return reinterpret_cast(buf); case QUICFrameType::DATA_BLOCKED: - new (buf) QUICDataBlockedFrame(src, len); + new (buf) QUICDataBlockedFrame(src, len, packet); return reinterpret_cast(buf); case QUICFrameType::STREAM_DATA_BLOCKED: - new (buf) QUICStreamDataBlockedFrame(src, len); + new (buf) QUICStreamDataBlockedFrame(src, len, packet); return reinterpret_cast(buf); case QUICFrameType::STREAMS_BLOCKED: - new (buf) QUICStreamIdBlockedFrame(src, len); + new (buf) QUICStreamIdBlockedFrame(src, len, packet); return reinterpret_cast(buf); case QUICFrameType::NEW_CONNECTION_ID: - new (buf) QUICNewConnectionIdFrame(src, len); + new (buf) QUICNewConnectionIdFrame(src, len, packet); return reinterpret_cast(buf); case QUICFrameType::STOP_SENDING: - new (buf) QUICStopSendingFrame(src, len); + new (buf) QUICStopSendingFrame(src, len, packet); return reinterpret_cast(buf); case QUICFrameType::PATH_CHALLENGE: - new (buf) QUICPathChallengeFrame(src, len); + new (buf) QUICPathChallengeFrame(src, len, packet); return reinterpret_cast(buf); case QUICFrameType::PATH_RESPONSE: - new (buf) QUICPathResponseFrame(src, len); + new (buf) QUICPathResponseFrame(src, len, packet); return reinterpret_cast(buf); case QUICFrameType::NEW_TOKEN: - new (buf) QUICNewTokenFrame(src, len); + new (buf) QUICNewTokenFrame(src, len, packet); return reinterpret_cast(buf); case QUICFrameType::RETIRE_CONNECTION_ID: - new (buf) QUICRetireConnectionIdFrame(src, len); + new (buf) QUICRetireConnectionIdFrame(src, len, packet); return reinterpret_cast(buf); default: // Unknown frame @@ -2560,7 +2829,7 @@ QUICFrameFactory::create(uint8_t *buf, const uint8_t *src, size_t len) } const QUICFrame & -QUICFrameFactory::fast_create(const uint8_t *buf, size_t len) +QUICFrameFactory::fast_create(const uint8_t *buf, size_t len, const QUICPacket *packet) { if (QUICFrame::type(buf) == QUICFrameType::UNKNOWN) { return this->_unknown_frame; @@ -2570,12 +2839,12 @@ QUICFrameFactory::fast_create(const uint8_t *buf, size_t len) QUICFrame *frame = this->_reusable_frames[type_index]; if (frame == nullptr) { - frame = QUICFrameFactory::create(this->_buf_for_fast_create + (type_index * QUICFrame::MAX_INSTANCE_SIZE), buf, len); + frame = QUICFrameFactory::create(this->_buf_for_fast_create + (type_index * QUICFrame::MAX_INSTANCE_SIZE), buf, len, packet); if (frame != nullptr) { this->_reusable_frames[static_cast(QUICFrame::type(buf))] = frame; } } else { - frame->parse(buf, len); + frame->parse(buf, len, packet); } return *frame; @@ -2656,6 +2925,13 @@ QUICFrameFactory::create_ping_frame(uint8_t *buf, QUICFrameId id, QUICFrameGener return reinterpret_cast(buf); } +QUICPaddingFrame * +QUICFrameFactory::create_padding_frame(uint8_t *buf, size_t size, QUICFrameId id, QUICFrameGenerator *owner) +{ + new (buf) QUICPaddingFrame(size); + return reinterpret_cast(buf); +} + QUICPathChallengeFrame * QUICFrameFactory::create_path_challenge_frame(uint8_t *buf, const uint8_t *data, QUICFrameId id, QUICFrameGenerator *owner) { @@ -2721,11 +2997,11 @@ QUICFrameFactory::create_stop_sending_frame(uint8_t *buf, QUICStreamId stream_id } QUICNewConnectionIdFrame * -QUICFrameFactory::create_new_connection_id_frame(uint8_t *buf, uint32_t sequence, QUICConnectionId connectoin_id, - QUICStatelessResetToken stateless_reset_token, QUICFrameId id, - QUICFrameGenerator *owner) +QUICFrameFactory::create_new_connection_id_frame(uint8_t *buf, uint64_t sequence, uint64_t retire_prior_to, + QUICConnectionId connectoin_id, QUICStatelessResetToken stateless_reset_token, + QUICFrameId id, QUICFrameGenerator *owner) { - new (buf) QUICNewConnectionIdFrame(sequence, connectoin_id, stateless_reset_token, id, owner); + new (buf) QUICNewConnectionIdFrame(sequence, retire_prior_to, connectoin_id, stateless_reset_token, id, owner); return reinterpret_cast(buf); } diff --git a/iocore/net/quic/QUICFrame.h b/iocore/net/quic/QUICFrame.h index 20f1bfe035d..ab21b17ce63 100644 --- a/iocore/net/quic/QUICFrame.h +++ b/iocore/net/quic/QUICFrame.h @@ -55,21 +55,26 @@ class QUICFrame virtual size_t size() const = 0; virtual bool is_probing_frame() const; virtual bool is_flow_controlled() const; - virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const = 0; - virtual Ptr to_io_buffer_block(size_t limit) const; + virtual Ptr to_io_buffer_block(size_t limit) const = 0; virtual int debug_msg(char *msg, size_t msg_len) const; - virtual void parse(const uint8_t *buf, size_t len){}; + virtual void parse(const uint8_t *buf, size_t len, const QUICPacket *packet){}; virtual QUICFrameGenerator *generated_by(); bool valid() const; + bool ack_eliciting() const; + const QUICPacket *packet() const; LINK(QUICFrame, link); protected: virtual void _reset(){}; - QUICFrame(QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : _id(id), _owner(owner) {} + QUICFrame(QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr, const QUICPacket *packet = nullptr) + : _id(id), _owner(owner), _packet(packet) + { + } size_t _size = 0; bool _valid = false; QUICFrameId _id = 0; QUICFrameGenerator *_owner = nullptr; + const QUICPacket *_packet = nullptr; }; // @@ -80,7 +85,7 @@ class QUICStreamFrame : public QUICFrame { public: QUICStreamFrame(QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner) {} - QUICStreamFrame(const uint8_t *buf, size_t len); + QUICStreamFrame(const uint8_t *buf, size_t len, const QUICPacket *packet = nullptr); QUICStreamFrame(Ptr &block, QUICStreamId streamid, QUICOffset offset, bool last = false, bool has_offset_field = true, bool has_length_field = true, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr); @@ -89,12 +94,10 @@ class QUICStreamFrame : public QUICFrame virtual QUICFrameType type() const override; virtual size_t size() const override; virtual bool is_flow_controlled() const override; - virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override; virtual Ptr to_io_buffer_block(size_t limit) const override; virtual int debug_msg(char *msg, size_t msg_len) const override; - virtual void parse(const uint8_t *buf, size_t len) override; + virtual void parse(const uint8_t *buf, size_t len, const QUICPacket *packet) override; - size_t store(uint8_t *buf, size_t *len, size_t limit, bool include_length_field) const; QUICStreamId stream_id() const; QUICOffset offset() const; IOBufferBlock *data() const; @@ -128,15 +131,15 @@ class QUICCryptoFrame : public QUICFrame { public: QUICCryptoFrame(QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner) {} - QUICCryptoFrame(const uint8_t *buf, size_t len); + QUICCryptoFrame(const uint8_t *buf, size_t len, const QUICPacket *packet = nullptr); QUICCryptoFrame(Ptr &block, QUICOffset offset, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr); QUICCryptoFrame(const QUICCryptoFrame &o); virtual QUICFrameType type() const override; virtual size_t size() const override; - virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override; + virtual Ptr to_io_buffer_block(size_t limit) const override; virtual int debug_msg(char *msg, size_t msg_len) const override; - virtual void parse(const uint8_t *buf, size_t len) override; + virtual void parse(const uint8_t *buf, size_t len, const QUICPacket *packet) override; QUICOffset offset() const; uint64_t data_length() const; @@ -145,8 +148,12 @@ class QUICCryptoFrame : public QUICFrame LINK(QUICCryptoFrame, link); private: + static constexpr uint8_t MAX_HEADER_SIZE = 16; + virtual void _reset() override; + size_t _store_header(uint8_t *buf, size_t *len) const; + QUICOffset _offset = 0; Ptr _block; }; @@ -218,7 +225,7 @@ class QUICAckFrame : public QUICFrame AckBlockSection(uint64_t first_ack_block) : _first_ack_block(first_ack_block) {} uint8_t count() const; size_t size() const; - size_t store(uint8_t *buf, size_t *len, size_t limit) const; + Ptr to_io_buffer_block(size_t limit) const; uint64_t first_ack_block() const; void add_ack_block(const AckBlock block); const_iterator begin() const; @@ -250,7 +257,7 @@ class QUICAckFrame : public QUICFrame }; QUICAckFrame(QUICFrameId id = 0) : QUICFrame(id) {} - QUICAckFrame(const uint8_t *buf, size_t len); + QUICAckFrame(const uint8_t *buf, size_t len, const QUICPacket *packet = nullptr); QUICAckFrame(QUICPacketNumber largest_acknowledged, uint64_t ack_delay, uint64_t first_ack_block, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr); @@ -260,8 +267,8 @@ class QUICAckFrame : public QUICFrame virtual ~QUICAckFrame(); virtual QUICFrameType type() const override; virtual size_t size() const override; - virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override; - virtual void parse(const uint8_t *buf, size_t len) override; + virtual Ptr to_io_buffer_block(size_t limit) const override; + virtual void parse(const uint8_t *buf, size_t len, const QUICPacket *packet) override; virtual int debug_msg(char *msg, size_t msg_len) const override; QUICPacketNumber largest_acknowledged() const; @@ -289,15 +296,15 @@ class QUICRstStreamFrame : public QUICFrame { public: QUICRstStreamFrame(QUICFrameId id = 0) : QUICFrame(id) {} - QUICRstStreamFrame(const uint8_t *buf, size_t len); + QUICRstStreamFrame(const uint8_t *buf, size_t len, const QUICPacket *packet = nullptr); QUICRstStreamFrame(QUICStreamId stream_id, QUICAppErrorCode error_code, QUICOffset final_offset, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr); virtual QUICFrameType type() const override; virtual size_t size() const override; - virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override; + virtual Ptr to_io_buffer_block(size_t limit) const override; virtual int debug_msg(char *msg, size_t msg_len) const override; - virtual void parse(const uint8_t *buf, size_t len) override; + virtual void parse(const uint8_t *buf, size_t len, const QUICPacket *packet) override; QUICStreamId stream_id() const; QUICAppErrorCode error_code() const; @@ -319,11 +326,11 @@ class QUICPingFrame : public QUICFrame { public: QUICPingFrame(QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner) {} - QUICPingFrame(const uint8_t *buf, size_t len); + QUICPingFrame(const uint8_t *buf, size_t len, const QUICPacket *packet = nullptr); virtual QUICFrameType type() const override; virtual size_t size() const override; - virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override; - virtual void parse(const uint8_t *buf, size_t len) override; + virtual Ptr to_io_buffer_block(size_t limit) const override; + virtual void parse(const uint8_t *buf, size_t len, const QUICPacket *packet) override; private: }; @@ -335,13 +342,18 @@ class QUICPingFrame : public QUICFrame class QUICPaddingFrame : public QUICFrame { public: - QUICPaddingFrame() {} - QUICPaddingFrame(const uint8_t *buf, size_t len); + QUICPaddingFrame(size_t size) : _size(size) {} + QUICPaddingFrame(const uint8_t *buf, size_t len, const QUICPacket *packet = nullptr); virtual QUICFrameType type() const override; virtual size_t size() const override; virtual bool is_probing_frame() const override; - virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override; - virtual void parse(const uint8_t *buf, size_t len) override; + virtual Ptr to_io_buffer_block(size_t limit) const override; + virtual void parse(const uint8_t *buf, size_t len, const QUICPacket *packet) override; + +private: + // padding frame is a resident of padding frames + // size indicate how many padding frames in this QUICPaddingFrame + size_t _size = 0; }; // @@ -352,18 +364,18 @@ class QUICConnectionCloseFrame : public QUICFrame { public: QUICConnectionCloseFrame(QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner) {} - QUICConnectionCloseFrame(const uint8_t *buf, size_t len); + QUICConnectionCloseFrame(const uint8_t *buf, size_t len, const QUICPacket *packet = nullptr); // Constructor for transport error codes - QUICConnectionCloseFrame(uint16_t error_code, QUICFrameType frame_type, uint64_t reason_phrase_length, const char *reason_phrase, + QUICConnectionCloseFrame(uint64_t error_code, QUICFrameType frame_type, uint64_t reason_phrase_length, const char *reason_phrase, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr); // Constructor for application protocol error codes - QUICConnectionCloseFrame(uint16_t error_code, uint64_t reason_phrase_length, const char *reason_phrase, QUICFrameId id = 0, + QUICConnectionCloseFrame(uint64_t error_code, uint64_t reason_phrase_length, const char *reason_phrase, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr); virtual QUICFrameType type() const override; virtual size_t size() const override; - virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override; + virtual Ptr to_io_buffer_block(size_t limit) const override; virtual int debug_msg(char *msg, size_t msg_len) const override; - virtual void parse(const uint8_t *buf, size_t len) override; + virtual void parse(const uint8_t *buf, size_t len, const QUICPacket *packet) override; uint16_t error_code() const; QUICFrameType frame_type() const; @@ -374,7 +386,7 @@ class QUICConnectionCloseFrame : public QUICFrame virtual void _reset() override; uint8_t _type = 0; - uint16_t _error_code; + uint64_t _error_code; QUICFrameType _frame_type = QUICFrameType::UNKNOWN; uint64_t _reason_phrase_length = 0; const char *_reason_phrase = nullptr; @@ -388,13 +400,13 @@ class QUICMaxDataFrame : public QUICFrame { public: QUICMaxDataFrame(QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner) {} - QUICMaxDataFrame(const uint8_t *buf, size_t len); + QUICMaxDataFrame(const uint8_t *buf, size_t len, const QUICPacket *packet = nullptr); QUICMaxDataFrame(uint64_t maximum_data, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr); virtual QUICFrameType type() const override; virtual size_t size() const override; - virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override; + virtual Ptr to_io_buffer_block(size_t limit) const override; virtual int debug_msg(char *msg, size_t msg_len) const override; - virtual void parse(const uint8_t *buf, size_t len) override; + virtual void parse(const uint8_t *buf, size_t len, const QUICPacket *packet) override; uint64_t maximum_data() const; @@ -412,13 +424,13 @@ class QUICMaxStreamDataFrame : public QUICFrame { public: QUICMaxStreamDataFrame(QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner) {} - QUICMaxStreamDataFrame(const uint8_t *buf, size_t len); + QUICMaxStreamDataFrame(const uint8_t *buf, size_t len, const QUICPacket *packet = nullptr); QUICMaxStreamDataFrame(QUICStreamId stream_id, uint64_t maximum_stream_data, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr); virtual QUICFrameType type() const override; virtual size_t size() const override; - virtual void parse(const uint8_t *buf, size_t len) override; - virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override; + virtual void parse(const uint8_t *buf, size_t len, const QUICPacket *packet) override; + virtual Ptr to_io_buffer_block(size_t limit) const override; virtual int debug_msg(char *msg, size_t msg_len) const override; QUICStreamId stream_id() const; @@ -439,12 +451,12 @@ class QUICMaxStreamsFrame : public QUICFrame { public: QUICMaxStreamsFrame(QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner) {} - QUICMaxStreamsFrame(const uint8_t *buf, size_t len); + QUICMaxStreamsFrame(const uint8_t *buf, size_t len, const QUICPacket *packet = nullptr); QUICMaxStreamsFrame(QUICStreamId maximum_streams, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr); virtual QUICFrameType type() const override; virtual size_t size() const override; - virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override; - virtual void parse(const uint8_t *buf, size_t len) override; + virtual Ptr to_io_buffer_block(size_t limit) const override; + virtual void parse(const uint8_t *buf, size_t len, const QUICPacket *packet) override; uint64_t maximum_streams() const; private: @@ -460,15 +472,15 @@ class QUICDataBlockedFrame : public QUICFrame { public: QUICDataBlockedFrame(QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner) {} - QUICDataBlockedFrame(const uint8_t *buf, size_t len); + QUICDataBlockedFrame(const uint8_t *buf, size_t len, const QUICPacket *packet = nullptr); QUICDataBlockedFrame(QUICOffset offset, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner), _offset(offset){}; virtual QUICFrameType type() const override; virtual size_t size() const override; - virtual void parse(const uint8_t *buf, size_t len) override; + virtual void parse(const uint8_t *buf, size_t len, const QUICPacket *packet) override; virtual int debug_msg(char *msg, size_t msg_len) const override; - virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override; + virtual Ptr to_io_buffer_block(size_t limit) const override; QUICOffset offset() const; @@ -486,14 +498,14 @@ class QUICStreamDataBlockedFrame : public QUICFrame { public: QUICStreamDataBlockedFrame(QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner) {} - QUICStreamDataBlockedFrame(const uint8_t *buf, size_t len); + QUICStreamDataBlockedFrame(const uint8_t *buf, size_t len, const QUICPacket *packet = nullptr); QUICStreamDataBlockedFrame(QUICStreamId s, QUICOffset o, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner), _stream_id(s), _offset(o){}; virtual QUICFrameType type() const override; virtual size_t size() const override; - virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override; - virtual void parse(const uint8_t *buf, size_t len) override; + virtual Ptr to_io_buffer_block(size_t limit) const override; + virtual void parse(const uint8_t *buf, size_t len, const QUICPacket *packet) override; virtual int debug_msg(char *msg, size_t msg_len) const override; QUICStreamId stream_id() const; @@ -513,15 +525,15 @@ class QUICStreamIdBlockedFrame : public QUICFrame { public: QUICStreamIdBlockedFrame(QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner) {} - QUICStreamIdBlockedFrame(const uint8_t *buf, size_t len); + QUICStreamIdBlockedFrame(const uint8_t *buf, size_t len, const QUICPacket *packet = nullptr); QUICStreamIdBlockedFrame(QUICStreamId s, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner), _stream_id(s) { } virtual QUICFrameType type() const override; virtual size_t size() const override; - virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override; - virtual void parse(const uint8_t *buf, size_t len) override; + virtual Ptr to_io_buffer_block(size_t limit) const override; + virtual void parse(const uint8_t *buf, size_t len, const QUICPacket *packet) override; QUICStreamId stream_id() const; @@ -539,18 +551,19 @@ class QUICNewConnectionIdFrame : public QUICFrame { public: QUICNewConnectionIdFrame(QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner) {} - QUICNewConnectionIdFrame(const uint8_t *buf, size_t len); - QUICNewConnectionIdFrame(uint64_t seq, const QUICConnectionId &cid, QUICStatelessResetToken token, QUICFrameId id = 0, - QUICFrameGenerator *owner = nullptr) - : QUICFrame(id, owner), _sequence(seq), _connection_id(cid), _stateless_reset_token(token){}; + QUICNewConnectionIdFrame(const uint8_t *buf, size_t len, const QUICPacket *packet = nullptr); + QUICNewConnectionIdFrame(uint64_t seq, uint64_t ret, const QUICConnectionId &cid, QUICStatelessResetToken token, + QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) + : QUICFrame(id, owner), _sequence(seq), _retire_prior_to(ret), _connection_id(cid), _stateless_reset_token(token){}; virtual QUICFrameType type() const override; virtual size_t size() const override; - virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override; - virtual void parse(const uint8_t *buf, size_t len) override; + virtual Ptr to_io_buffer_block(size_t limit) const override; + virtual void parse(const uint8_t *buf, size_t len, const QUICPacket *packet) override; virtual int debug_msg(char *msg, size_t msg_len) const override; uint64_t sequence() const; + uint64_t retire_prior_to() const; QUICConnectionId connection_id() const; QUICStatelessResetToken stateless_reset_token() const; @@ -558,6 +571,7 @@ class QUICNewConnectionIdFrame : public QUICFrame virtual void _reset() override; uint64_t _sequence = 0; + uint64_t _retire_prior_to = 0; QUICConnectionId _connection_id = QUICConnectionId::ZERO(); QUICStatelessResetToken _stateless_reset_token; }; @@ -570,14 +584,14 @@ class QUICStopSendingFrame : public QUICFrame { public: QUICStopSendingFrame(QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner) {} - QUICStopSendingFrame(const uint8_t *buf, size_t len); + QUICStopSendingFrame(const uint8_t *buf, size_t len, const QUICPacket *packet = nullptr); QUICStopSendingFrame(QUICStreamId stream_id, QUICAppErrorCode error_code, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr); virtual QUICFrameType type() const override; virtual size_t size() const override; - virtual void parse(const uint8_t *buf, size_t len) override; - virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override; + virtual void parse(const uint8_t *buf, size_t len, const QUICPacket *packet) override; + virtual Ptr to_io_buffer_block(size_t limit) const override; QUICStreamId stream_id() const; QUICAppErrorCode error_code() const; @@ -598,7 +612,7 @@ class QUICPathChallengeFrame : public QUICFrame public: static constexpr uint8_t DATA_LEN = 8; QUICPathChallengeFrame(QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner) {} - QUICPathChallengeFrame(const uint8_t *buf, size_t len); + QUICPathChallengeFrame(const uint8_t *buf, size_t len, const QUICPacket *packet = nullptr); QUICPathChallengeFrame(ats_unique_buf data, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner), _data(std::move(data)) { @@ -606,8 +620,9 @@ class QUICPathChallengeFrame : public QUICFrame virtual QUICFrameType type() const override; virtual size_t size() const override; virtual bool is_probing_frame() const override; - virtual void parse(const uint8_t *buf, size_t len) override; - virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override; + virtual void parse(const uint8_t *buf, size_t len, const QUICPacket *packet) override; + virtual Ptr to_io_buffer_block(size_t limit) const override; + virtual int debug_msg(char *msg, size_t msg_len) const override; const uint8_t *data() const; @@ -626,7 +641,7 @@ class QUICPathResponseFrame : public QUICFrame public: static constexpr uint8_t DATA_LEN = 8; QUICPathResponseFrame(QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner) {} - QUICPathResponseFrame(const uint8_t *buf, size_t len); + QUICPathResponseFrame(const uint8_t *buf, size_t len, const QUICPacket *packet = nullptr); QUICPathResponseFrame(ats_unique_buf data, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner), _data(std::move(data)) { @@ -634,8 +649,9 @@ class QUICPathResponseFrame : public QUICFrame virtual QUICFrameType type() const override; virtual size_t size() const override; virtual bool is_probing_frame() const override; - virtual void parse(const uint8_t *buf, size_t len) override; - virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override; + virtual void parse(const uint8_t *buf, size_t len, const QUICPacket *packet) override; + virtual Ptr to_io_buffer_block(size_t limit) const override; + virtual int debug_msg(char *msg, size_t msg_len) const override; const uint8_t *data() const; @@ -653,15 +669,15 @@ class QUICNewTokenFrame : public QUICFrame { public: QUICNewTokenFrame(QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner) {} - QUICNewTokenFrame(const uint8_t *buf, size_t len); + QUICNewTokenFrame(const uint8_t *buf, size_t len, const QUICPacket *packet = nullptr); QUICNewTokenFrame(ats_unique_buf token, size_t token_length, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner), _token_length(token_length), _token(std::move(token)) { } virtual QUICFrameType type() const override; virtual size_t size() const override; - virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override; - virtual void parse(const uint8_t *buf, size_t len) override; + virtual Ptr to_io_buffer_block(size_t limit) const override; + virtual void parse(const uint8_t *buf, size_t len, const QUICPacket *packet) override; uint64_t token_length() const; const uint8_t *token() const; @@ -681,15 +697,15 @@ class QUICRetireConnectionIdFrame : public QUICFrame { public: QUICRetireConnectionIdFrame(QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner) {} - QUICRetireConnectionIdFrame(const uint8_t *buf, size_t len); + QUICRetireConnectionIdFrame(const uint8_t *buf, size_t len, const QUICPacket *packet = nullptr); QUICRetireConnectionIdFrame(uint64_t seq_num, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner), _seq_num(seq_num) { } virtual QUICFrameType type() const override; virtual size_t size() const override; - virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override; - virtual void parse(const uint8_t *buf, size_t len) override; + virtual Ptr to_io_buffer_block(size_t limit) const override; + virtual void parse(const uint8_t *buf, size_t len, const QUICPacket *packet) override; virtual int debug_msg(char *msg, size_t msg_len) const override; uint64_t seq_num() const; @@ -708,8 +724,8 @@ class QUICUnknownFrame : public QUICFrame { QUICFrameType type() const override; size_t size() const override; - size_t store(uint8_t *buf, size_t *len, size_t limit) const override; - void parse(const uint8_t *buf, size_t len) override; + virtual Ptr to_io_buffer_block(size_t limit) const override; + void parse(const uint8_t *buf, size_t len, const QUICPacket *packet) override; int debug_msg(char *msg, size_t msg_len) const override; }; @@ -722,13 +738,13 @@ class QUICFrameFactory /* * This is used for creating a QUICFrame object based on received data. */ - static QUICFrame *create(uint8_t *buf, const uint8_t *src, size_t len); + static QUICFrame *create(uint8_t *buf, const uint8_t *src, size_t len, const QUICPacket *packet); /* * This works almost the same as create() but it reuses created objects for performance. * If you create a frame object which has the same frame type that you created before, the object will be reset by new data. */ - const QUICFrame &fast_create(const uint8_t *buf, size_t len); + const QUICFrame &fast_create(const uint8_t *buf, size_t len, const QUICPacket *packet); /* * Creates a STREAM frame. @@ -833,7 +849,8 @@ class QUICFrameFactory /* * Creates a NEW_CONNECTION_ID frame. */ - static QUICNewConnectionIdFrame *create_new_connection_id_frame(uint8_t *buf, uint32_t sequence, QUICConnectionId connectoin_id, + static QUICNewConnectionIdFrame *create_new_connection_id_frame(uint8_t *buf, uint64_t sequence, uint64_t retire_prior_to, + QUICConnectionId connectoin_id, QUICStatelessResetToken stateless_reset_token, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr); @@ -849,6 +866,11 @@ class QUICFrameFactory static QUICRetireConnectionIdFrame *create_retire_connection_id_frame(uint8_t *buf, uint64_t seq_num, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr); + /* + * Creates a PADDING frame + */ + static QUICPaddingFrame *create_padding_frame(uint8_t *buf, size_t size, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr); + private: // FIXME Actual number of frame types is several but some of the values are not sequential. QUICFrame *_reusable_frames[256] = {nullptr}; diff --git a/iocore/net/quic/QUICFrameDispatcher.cc b/iocore/net/quic/QUICFrameDispatcher.cc index c2f3d1f7757..b807ff516e0 100644 --- a/iocore/net/quic/QUICFrameDispatcher.cc +++ b/iocore/net/quic/QUICFrameDispatcher.cc @@ -43,7 +43,7 @@ QUICFrameDispatcher::add_handler(QUICFrameHandler *handler) QUICConnectionErrorUPtr QUICFrameDispatcher::receive_frames(QUICEncryptionLevel level, const uint8_t *payload, uint16_t size, bool &ack_only, - bool &is_flow_controlled, bool *has_non_probing_frame) + bool &is_flow_controlled, bool *has_non_probing_frame, const QUICPacket *packet) { uint16_t cursor = 0; ack_only = true; @@ -51,7 +51,7 @@ QUICFrameDispatcher::receive_frames(QUICEncryptionLevel level, const uint8_t *pa QUICConnectionErrorUPtr error = nullptr; while (cursor < size) { - const QUICFrame &frame = this->_frame_factory.fast_create(payload + cursor, size - cursor); + const QUICFrame &frame = this->_frame_factory.fast_create(payload + cursor, size - cursor, packet); if (frame.type() == QUICFrameType::UNKNOWN) { QUICDebug("Failed to create a frame (%u bytes skipped)", size - cursor); break; diff --git a/iocore/net/quic/QUICFrameDispatcher.h b/iocore/net/quic/QUICFrameDispatcher.h index 79d71316c41..e7ce785b49e 100644 --- a/iocore/net/quic/QUICFrameDispatcher.h +++ b/iocore/net/quic/QUICFrameDispatcher.h @@ -35,7 +35,8 @@ class QUICFrameDispatcher QUICFrameDispatcher(QUICConnectionInfoProvider *info); QUICConnectionErrorUPtr receive_frames(QUICEncryptionLevel level, const uint8_t *payload, uint16_t size, - bool &should_send_ackbool, bool &is_flow_controlled, bool *has_non_probing_frame); + bool &should_send_ackbool, bool &is_flow_controlled, bool *has_non_probing_frame, + const QUICPacket *packet); void add_handler(QUICFrameHandler *handler); diff --git a/iocore/net/quic/QUICFrameGenerator.cc b/iocore/net/quic/QUICFrameGenerator.cc index 3dce9665d4a..908374e67fb 100644 --- a/iocore/net/quic/QUICFrameGenerator.cc +++ b/iocore/net/quic/QUICFrameGenerator.cc @@ -23,6 +23,7 @@ #include "QUICFrameGenerator.h" +// QUICFrameGenerator void QUICFrameGenerator::_records_frame(QUICFrameId id, QUICFrameInformationUPtr info) { @@ -58,3 +59,31 @@ QUICFrameGenerator::on_frame_lost(QUICFrameId id) this->_info.erase(it); } } + +void +QUICFrameGeneratorManager::add_generator(QUICFrameGenerator &generator, int weight) +{ + auto it = this->_inline_vector.begin(); + for (; it != this->_inline_vector.end(); ++it) { + if (it->first >= weight) { + break; + } + } + this->_inline_vector.emplace(it, weight, &generator); +} + +const std::vector & +QUICFrameGeneratorManager::generators() +{ + // Because we don't remove generators. So The size changed means new generators is coming + if (!this->_generators.empty() && this->_generators.size() == this->_inline_vector.size()) { + return this->_generators; + } + + this->_generators.clear(); + for (auto it : this->_inline_vector) { + this->_generators.emplace_back(it.second); + } + + return this->_generators; +} diff --git a/iocore/net/quic/QUICFrameGenerator.h b/iocore/net/quic/QUICFrameGenerator.h index 2298de597d0..f415ff7aaf5 100644 --- a/iocore/net/quic/QUICFrameGenerator.h +++ b/iocore/net/quic/QUICFrameGenerator.h @@ -30,14 +30,14 @@ class QUICFrameGenerator { public: virtual ~QUICFrameGenerator(){}; - virtual bool will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) = 0; + virtual bool will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) = 0; /* * This function constructs an instance of QUICFrame on buf. * It returns a pointer for the frame if it succeeded, and returns nullptr if it failed. */ virtual QUICFrame *generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, - uint16_t maximum_frame_size, ink_hrtime timestamp) = 0; + uint16_t maximum_frame_size, size_t current_packet_size, uint32_t seq_num) = 0; void on_frame_acked(QUICFrameId id); void on_frame_lost(QUICFrameId id); @@ -67,3 +67,55 @@ class QUICFrameGenerator QUICEncryptionLevel _encryption_level_filter = QUICEncryptionLevel::ONE_RTT; std::map _info; }; + +// only generate one frame per loop +class QUICFrameOnceGenerator : public QUICFrameGenerator +{ +public: + bool + will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) override + { + if (this->_seq_num == seq_num) { + return false; + } + + this->_seq_num = seq_num; + return this->_will_generate_frame(level, current_packet_size, ack_eliciting); + } + + QUICFrame * + generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, + size_t current_packet_size, uint32_t seq_num) override + { + this->_seq_num = seq_num; + return this->_generate_frame(buf, level, connection_credit, maximum_frame_size, current_packet_size); + } + +protected: + virtual bool _will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting) = 0; + virtual QUICFrame *_generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, + uint16_t maximum_frame_size, size_t current_packet_size) = 0; + +private: + uint32_t _seq_num = UINT32_MAX; +}; + +enum QUICFrameGeneratorWeight { + EARLY = 100, + BEFORE_DATA = 200, + AFTER_DATA = 300, + LATE = 400, +}; + +class QUICFrameGeneratorManager +{ +public: + void add_generator(QUICFrameGenerator &generator, int weight); + const std::vector &generators(); + +private: + using QUICActiveFrameGenerator = std::pair; + + std::vector _generators; + std::vector _inline_vector; +}; diff --git a/iocore/net/quic/QUICHandshake.cc b/iocore/net/quic/QUICHandshake.cc index 6042d26a67c..c88377f16dd 100644 --- a/iocore/net/quic/QUICHandshake.cc +++ b/iocore/net/quic/QUICHandshake.cc @@ -166,7 +166,7 @@ QUICHandshake::negotiate_version(const QUICPacket &vn, QUICPacketFactory *packet packet_factory->set_version(version); } else { QUICHSDebug("Version negotiation failed"); - return std::make_unique(QUICTransErrorCode::VERSION_NEGOTIATION_ERROR); + return std::make_unique(QUICTransErrorCode::PROTOCOL_VIOLATION); } return nullptr; @@ -322,24 +322,24 @@ QUICHandshake::handle_frame(QUICEncryptionLevel level, const QUICFrame &frame) } bool -QUICHandshake::will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) +QUICHandshake::will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) { if (!this->_is_level_matched(level)) { return false; } - return this->_crypto_streams[static_cast(level)].will_generate_frame(level, timestamp); + return this->_crypto_streams[static_cast(level)].will_generate_frame(level, current_packet_size, ack_eliciting, seq_num); } QUICFrame * QUICHandshake::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, - ink_hrtime timestamp) + size_t current_packet_size, uint32_t seq_num) { QUICFrame *frame = nullptr; if (this->_is_level_matched(level)) { - frame = - this->_crypto_streams[static_cast(level)].generate_frame(buf, level, connection_credit, maximum_frame_size, timestamp); + frame = this->_crypto_streams[static_cast(level)].generate_frame(buf, level, connection_credit, maximum_frame_size, + current_packet_size, seq_num); } return frame; @@ -382,6 +382,9 @@ QUICHandshake::_load_local_server_transport_parameters(const QUICTPConfig &tp_co pref_addr->store(pref_addr_buf, len); tp->set(QUICTransportParameterId::PREFERRED_ADDRESS, pref_addr_buf, len); } + if (tp_config.active_cid_limit() != 0) { + tp->set(QUICTransportParameterId::ACTIVE_CONNECTION_ID_LIMIT, tp_config.active_cid_limit()); + } // MAYs (server) tp->set(QUICTransportParameterId::STATELESS_RESET_TOKEN, this->_reset_token.buf(), QUICStatelessResetToken::LEN); @@ -421,6 +424,9 @@ QUICHandshake::_load_local_client_transport_parameters(const QUICTPConfig &tp_co tp->set(QUICTransportParameterId::INITIAL_MAX_STREAM_DATA_UNI, tp_config.initial_max_stream_data_uni()); } tp->set(QUICTransportParameterId::ACK_DELAY_EXPONENT, tp_config.ack_delay_exponent()); + if (tp_config.active_cid_limit() != 0) { + tp->set(QUICTransportParameterId::ACTIVE_CONNECTION_ID_LIMIT, tp_config.active_cid_limit()); + } this->_local_transport_parameters = std::shared_ptr(tp); this->_hs_protocol->set_local_transport_parameters(std::unique_ptr(tp)); diff --git a/iocore/net/quic/QUICHandshake.h b/iocore/net/quic/QUICHandshake.h index 4dda103616a..49ef4379ff2 100644 --- a/iocore/net/quic/QUICHandshake.h +++ b/iocore/net/quic/QUICHandshake.h @@ -51,9 +51,9 @@ class QUICHandshake : public QUICFrameHandler, public QUICFrameGenerator virtual QUICConnectionErrorUPtr handle_frame(QUICEncryptionLevel level, const QUICFrame &frame) override; // QUICFrameGenerator - bool will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) override; + bool will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) override; QUICFrame *generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, - ink_hrtime timestamp) override; + size_t current_packet_size, uint32_t seq_num) override; // for client side QUICConnectionErrorUPtr start(const QUICTPConfig &tp_config, QUICPacketFactory *packet_factory, bool vn_exercise_enabled); diff --git a/iocore/net/quic/QUICIncomingFrameBuffer.cc b/iocore/net/quic/QUICIncomingFrameBuffer.cc index 154563f4278..373d0093123 100644 --- a/iocore/net/quic/QUICIncomingFrameBuffer.cc +++ b/iocore/net/quic/QUICIncomingFrameBuffer.cc @@ -113,7 +113,11 @@ QUICIncomingStreamFrameBuffer::insert(const QUICFrame *frame) this->_recv_offset = offset + len; this->_recv_buffer.push(stream_frame); } else { - this->_out_of_order_queue.insert(std::make_pair(offset, stream_frame)); + auto result = this->_out_of_order_queue.insert(std::make_pair(offset, stream_frame)); + if (!result.second) { + // Duplicate frame doesn't need to be inserted + delete stream_frame; + } } return nullptr; @@ -134,30 +138,30 @@ QUICIncomingStreamFrameBuffer::_check_and_set_fin_flag(QUICOffset offset, size_t // stream with fin flag {11.3. Stream Final Offset} // Once a final offset for a stream is known, it cannot change. // If a RESET_STREAM or STREAM frame causes the final offset to change for a stream, - // an endpoint SHOULD respond with a FINAL_OFFSET_ERROR error (see Section 12). + // an endpoint SHOULD respond with a FINAL_SIZE_ERROR error (see Section 12). // A receiver SHOULD treat receipt of data at or beyond the final offset as a - // FINAL_OFFSET_ERROR error, even after a stream is closed. + // FINAL_SIZE_ERROR error, even after a stream is closed. // {11.3. Stream Final Offset} // A receiver SHOULD treat receipt of data at or beyond the final offset as a - // FINAL_OFFSET_ERROR error, even after a stream is closed. + // FINAL_SIZE_ERROR error, even after a stream is closed. if (fin_flag) { if (this->_fin_offset != UINT64_MAX) { if (this->_fin_offset == offset + len) { // dup fin frame return nullptr; } - return std::make_unique(QUICTransErrorCode::FINAL_OFFSET_ERROR); + return std::make_unique(QUICTransErrorCode::FINAL_SIZE_ERROR); } this->_fin_offset = offset + len; if (this->_max_offset > this->_fin_offset) { - return std::make_unique(QUICTransErrorCode::FINAL_OFFSET_ERROR); + return std::make_unique(QUICTransErrorCode::FINAL_SIZE_ERROR); } } else if (this->_fin_offset != UINT64_MAX && this->_fin_offset <= offset) { - return std::make_unique(QUICTransErrorCode::FINAL_OFFSET_ERROR); + return std::make_unique(QUICTransErrorCode::FINAL_SIZE_ERROR); } this->_max_offset = std::max(offset + len, this->_max_offset); @@ -242,7 +246,11 @@ QUICIncomingCryptoFrameBuffer::insert(const QUICFrame *frame) this->_recv_offset = offset + len; this->_recv_buffer.push(crypto_frame); } else { - this->_out_of_order_queue.insert(std::make_pair(offset, crypto_frame)); + auto result = this->_out_of_order_queue.insert(std::make_pair(offset, crypto_frame)); + if (!result.second) { + // Duplicate frame doesn't need to be inserted + delete crypto_frame; + } } return nullptr; diff --git a/iocore/net/quic/QUICKeyGenerator.cc b/iocore/net/quic/QUICKeyGenerator.cc index 05c1796f950..98d091d8725 100644 --- a/iocore/net/quic/QUICKeyGenerator.cc +++ b/iocore/net/quic/QUICKeyGenerator.cc @@ -34,7 +34,7 @@ using namespace std::literals; constexpr static uint8_t QUIC_VERSION_1_SALT[] = { - 0xef, 0x4f, 0xb0, 0xab, 0xb4, 0x74, 0x70, 0xc4, 0x1b, 0xef, 0xcf, 0x80, 0x31, 0x33, 0x4f, 0xae, 0x48, 0x5e, 0x09, 0xa0, + 0xc3, 0xee, 0xf7, 0x12, 0xc7, 0x2e, 0xbb, 0x5a, 0x11, 0xa7, 0xd2, 0x43, 0x2b, 0xb4, 0x63, 0x65, 0xbe, 0xf9, 0xf5, 0x02, }; constexpr static std::string_view LABEL_FOR_CLIENT_INITIAL_SECRET("client in"sv); constexpr static std::string_view LABEL_FOR_SERVER_INITIAL_SECRET("server in"sv); diff --git a/iocore/net/quic/QUICLossDetector.cc b/iocore/net/quic/QUICLossDetector.cc index 7cd94c0f394..4d6397bbfab 100644 --- a/iocore/net/quic/QUICLossDetector.cc +++ b/iocore/net/quic/QUICLossDetector.cc @@ -29,14 +29,20 @@ #include "QUICEvents.h" #include "QUICDebugNames.h" #include "QUICFrameGenerator.h" +#include "QUICPinger.h" +#include "QUICPadder.h" +#include "QUICPacketProtectionKeyInfo.h" -#define QUICLDDebug(fmt, ...) Debug("quic_loss_detector", "[%s] " fmt, this->_info->cids().data(), ##__VA_ARGS__) -#define QUICLDVDebug(fmt, ...) Debug("v_quic_loss_detector", "[%s] " fmt, this->_info->cids().data(), ##__VA_ARGS__) +#define QUICLDDebug(fmt, ...) \ + Debug("quic_loss_detector", "[%s] " fmt, this->_context.connection_info()->cids().data(), ##__VA_ARGS__) +#define QUICLDVDebug(fmt, ...) \ + Debug("v_quic_loss_detector", "[%s] " fmt, this->_context.connection_info()->cids().data(), ##__VA_ARGS__) -QUICLossDetector::QUICLossDetector(QUICConnectionInfoProvider *info, QUICCongestionController *cc, QUICRTTMeasure *rtt_measure, - const QUICLDConfig &ld_config) - : _info(info), _rtt_measure(rtt_measure), _cc(cc) +QUICLossDetector::QUICLossDetector(QUICLDContext &context, QUICCongestionController *cc, QUICRTTMeasure *rtt_measure, + QUICPinger *pinger, QUICPadder *padder) + : _rtt_measure(rtt_measure), _pinger(pinger), _padder(padder), _cc(cc), _context(context) { + auto &ld_config = _context.ld_config(); this->mutex = new_ProxyMutex(); this->_loss_detection_mutex = new_ProxyMutex(); @@ -133,6 +139,9 @@ QUICLossDetector::on_packet_sent(QUICPacketInfoUPtr packet_info, bool in_flight) ink_hrtime now = packet_info->time_sent; size_t sent_bytes = packet_info->sent_bytes; + QUICLDDebug("%s packet sent : %" PRIu64 " bytes: %lu ack_eliciting: %d", QUICDebugNames::pn_space(packet_info->pn_space), + packet_number, sent_bytes, ack_eliciting); + this->_add_to_sent_packet_list(packet_number, std::move(packet_info)); if (in_flight) { @@ -178,6 +187,21 @@ QUICLossDetector::update_ack_delay_exponent(uint8_t ack_delay_exponent) this->_ack_delay_exponent = ack_delay_exponent; } +bool +QUICLossDetector::_include_ack_eliciting(const std::vector &acked_packets, int index) const +{ + // Find out ack_elicting packet. + // FIXME: this loop is the same as _on_ack_received's loop it would better + // to combine it. + for (auto packet : acked_packets) { + if (packet->ack_eliciting) { + return true; + } + } + + return false; +} + void QUICLossDetector::_on_ack_received(const QUICAckFrame &ack_frame, QUICPacketNumberSpace pn_space) { @@ -185,10 +209,17 @@ QUICLossDetector::_on_ack_received(const QUICAckFrame &ack_frame, QUICPacketNumb int index = static_cast(pn_space); this->_largest_acked_packet[index] = std::max(this->_largest_acked_packet[index], ack_frame.largest_acknowledged()); + + auto newly_acked_packets = this->_determine_newly_acked_packets(ack_frame, index); + if (newly_acked_packets.empty()) { + return; + } + // If the largest acknowledged is newly acked and // ack-eliciting, update the RTT. auto pi = this->_sent_packets[index].find(ack_frame.largest_acknowledged()); - if (pi != this->_sent_packets[index].end() && pi->second->ack_eliciting) { + if (pi != this->_sent_packets[index].end() && + (pi->second->ack_eliciting || this->_include_ack_eliciting(newly_acked_packets, index))) { ink_hrtime latest_rtt = Thread::get_hrtime() - pi->second->time_sent; // _latest_rtt is nanosecond but ack_frame.ack_delay is microsecond and scaled ink_hrtime delay = HRTIME_USECONDS(ack_frame.ack_delay() << this->_ack_delay_exponent); @@ -205,21 +236,8 @@ QUICLossDetector::_on_ack_received(const QUICAckFrame &ack_frame, QUICPacketNumb } // Find all newly acked packets. - bool newly_acked_packets = false; - for (auto &&range : this->_determine_newly_acked_packets(ack_frame)) { - for (auto ite = this->_sent_packets[index].begin(); ite != this->_sent_packets[index].end(); /* no increment here*/) { - auto tmp_ite = ite; - tmp_ite++; - if (range.contains(ite->first)) { - newly_acked_packets = true; - this->_on_packet_acked(*(ite->second)); - } - ite = tmp_ite; - } - } - - if (!newly_acked_packets) { - return; + for (auto info : newly_acked_packets) { + this->_on_packet_acked(*info); } QUICLDVDebug("[%s] Unacked packets %lu (retransmittable %u, includes %u handshake packets)", QUICDebugNames::pn_space(pn_space), @@ -240,9 +258,10 @@ void QUICLossDetector::_on_packet_acked(const QUICPacketInfo &acked_packet) { SCOPED_MUTEX_LOCK(lock, this->_loss_detection_mutex, this_ethread()); - // QUICLDDebug("Packet number %" PRIu64 " has been acked", acked_packet_number); + QUICLDDebug("[%s] Packet number %" PRIu64 " has been acked", QUICDebugNames::pn_space(acked_packet.pn_space), + acked_packet.packet_number); - if (acked_packet.ack_eliciting) { + if (acked_packet.in_flight) { this->_cc->on_packet_acked(acked_packet); } @@ -276,6 +295,31 @@ QUICLossDetector::_get_earliest_loss_time(QUICPacketNumberSpace &pn_space) void QUICLossDetector::_set_loss_detection_timer() { + std::function update_timer = [this](ink_hrtime time) { + this->_loss_detection_alarm_at = time; + if (!this->_loss_detection_timer) { + this->_loss_detection_timer = eventProcessor.schedule_every(this, HRTIME_MSECONDS(25)); + } + }; + + QUICPacketNumberSpace pn_space; + ink_hrtime alarm = this->_get_earliest_loss_time(pn_space); + if (alarm != 0) { + update_timer(alarm); + QUICLDDebug("[%s] time threshold loss detection timer: %" PRId64 "ms", QUICDebugNames::pn_space(pn_space), + (this->_loss_detection_alarm_at - Thread::get_hrtime()) / HRTIME_MSECOND); + return; + } + + if (this->_crypto_outstanding > 0 || this->_is_client_without_one_rtt_key()) { + // Crypto retransmission timer. + alarm = this->_time_of_last_sent_crypto_packet + this->_rtt_measure->handshake_retransmit_timeout(); + update_timer(alarm); + QUICLDDebug("%s crypto packet alarm will be set: %" PRId64 "ms", QUICDebugNames::pn_space(pn_space), + (alarm - this->_time_of_last_sent_crypto_packet) / HRTIME_MSECOND); + return; + } + // Don't arm the alarm if there are no packets with retransmittable data in flight. // -- MODIFIED CODE -- // In psuedocode, `bytes_in_flight` is used, but we're tracking "retransmittable data in flight" by `_ack_eliciting_outstanding` @@ -291,29 +335,11 @@ QUICLossDetector::_set_loss_detection_timer() } // -- END OF MODIFIED CODE -- - QUICPacketNumberSpace pn_space; - ink_hrtime loss_time = this->_get_earliest_loss_time(pn_space); - if (loss_time != 0) { - // Time threshold loss detection. - this->_loss_detection_alarm_at = loss_time; - QUICLDDebug("[%s] time threshold loss detection timer: %" PRId64, QUICDebugNames::pn_space(pn_space), - this->_loss_detection_alarm_at); - } else if (this->_crypto_outstanding) { - // Handshake retransmission alarm. - this->_loss_detection_alarm_at = this->_time_of_last_sent_crypto_packet + this->_rtt_measure->handshake_retransmit_timeout(); - QUICLDDebug("%s crypto packet alarm will be set: %" PRId64, QUICDebugNames::pn_space(pn_space), this->_loss_detection_alarm_at); - // -- ADDITIONAL CODE -- - // In psudocode returning here, but we don't do for scheduling _loss_detection_alarm event. - // -- END OF ADDITIONAL CODE -- - } else { - // PTO Duration - this->_loss_detection_alarm_at = this->_time_of_last_sent_ack_eliciting_packet + this->_rtt_measure->current_pto_period(); - QUICLDDebug("[%s] PTO timeout will be set: %" PRId64, QUICDebugNames::pn_space(pn_space), this->_loss_detection_alarm_at); - } - - if (!this->_loss_detection_timer) { - this->_loss_detection_timer = eventProcessor.schedule_every(this, HRTIME_MSECONDS(25)); - } + // PTO Duration + alarm = this->_time_of_last_sent_ack_eliciting_packet + this->_rtt_measure->current_pto_period(); + update_timer(alarm); + QUICLDDebug("[%s] PTO timeout will be set: %" PRId64 "ms", QUICDebugNames::pn_space(pn_space), + (alarm - this->_time_of_last_sent_ack_eliciting_packet) / HRTIME_MSECOND); } void @@ -326,11 +352,23 @@ QUICLossDetector::_on_loss_detection_timeout() this->_detect_lost_packets(pn_space); } else if (this->_crypto_outstanding) { // Handshake retransmission alarm. + QUICLDVDebug("Crypto Retranmission"); this->_retransmit_all_unacked_crypto_data(); + this->_rtt_measure->set_crypto_count(this->_rtt_measure->crypto_count() + 1); + } else if (this->_is_client_without_one_rtt_key()) { + // Client sends an anti-deadlock packet: Initial is padded + // to earn more anti-amplification credit, + // a Handshake packet proves address ownership. + if (this->_context.key_info()->is_encryption_key_available(QUICKeyPhase::HANDSHAKE)) { + this->_send_one_handshake_packets(); + } else { + this->_send_one_padded_packets(); + } + this->_rtt_measure->set_crypto_count(this->_rtt_measure->crypto_count() + 1); } else { QUICLDVDebug("PTO"); - this->_send_two_packets(); + this->_send_one_or_two_packet(); this->_rtt_measure->set_pto_count(this->_rtt_measure->pto_count() + 1); } @@ -358,6 +396,8 @@ QUICLossDetector::_detect_lost_packets(QUICPacketNumberSpace pn_space) SCOPED_MUTEX_LOCK(lock, this->_loss_detection_mutex, this_ethread()); this->_loss_time[static_cast(pn_space)] = 0; ink_hrtime loss_delay = this->_k_time_threshold * std::max(this->_rtt_measure->latest_rtt(), this->_rtt_measure->smoothed_rtt()); + loss_delay = std::min(loss_delay, this->_rtt_measure->k_granularity()); + std::map lost_packets; // Packets sent before this time are deemed lost. @@ -390,12 +430,12 @@ QUICLossDetector::_detect_lost_packets(QUICPacketNumberSpace pn_space) if (unacked->in_flight) { lost_packets.insert({it->first, it->second.get()}); - } else if (this->_loss_time[static_cast(pn_space)] == 0) { - this->_loss_time[static_cast(pn_space)] = unacked->time_sent + loss_delay; - } else { - this->_loss_time[static_cast(pn_space)] = - std::min(this->_loss_time[static_cast(pn_space)], unacked->time_sent + loss_delay); } + } else if (this->_loss_time[static_cast(pn_space)] == 0) { + this->_loss_time[static_cast(pn_space)] = unacked->time_sent + loss_delay; + } else { + this->_loss_time[static_cast(pn_space)] = + std::min(this->_loss_time[static_cast(pn_space)], unacked->time_sent + loss_delay); } } @@ -442,10 +482,38 @@ QUICLossDetector::_retransmit_all_unacked_crypto_data() } void -QUICLossDetector::_send_two_packets() +QUICLossDetector::_send_packet(QUICEncryptionLevel level, bool padded) { - SCOPED_MUTEX_LOCK(lock, this->_loss_detection_mutex, this_ethread()); - // TODO sent ping + if (padded) { + this->_padder->request(level); + } else { + this->_pinger->request(); + } + this->_cc->add_extra_credit(); +} + +void +QUICLossDetector::_send_one_or_two_packet() +{ + this->_send_packet(QUICEncryptionLevel::ONE_RTT); + this->_send_packet(QUICEncryptionLevel::ONE_RTT); + ink_assert(this->_pinger->count() >= 2); + QUICLDDebug("[%s] send ping frame %" PRIu64, QUICDebugNames::encryption_level(QUICEncryptionLevel::ONE_RTT), + this->_pinger->count()); +} + +void +QUICLossDetector::_send_one_handshake_packets() +{ + this->_send_packet(QUICEncryptionLevel::HANDSHAKE); + QUICLDDebug("[%s] send handshake packet", QUICDebugNames::encryption_level(QUICEncryptionLevel::HANDSHAKE)); +} + +void +QUICLossDetector::_send_one_padded_packets() +{ + this->_send_packet(QUICEncryptionLevel::INITIAL, true); + QUICLDDebug("[%s] send PADDING frame", QUICDebugNames::encryption_level(QUICEncryptionLevel::INITIAL)); } // ===== Functions below are helper functions ===== @@ -466,9 +534,10 @@ QUICLossDetector::_retransmit_lost_packet(QUICPacketInfo &packet_info) } } -std::set -QUICLossDetector::_determine_newly_acked_packets(const QUICAckFrame &ack_frame) +std::vector +QUICLossDetector::_determine_newly_acked_packets(const QUICAckFrame &ack_frame, int pn_space) { + std::vector packets; std::set numbers; QUICPacketNumber x = ack_frame.largest_acknowledged(); numbers.insert({x, static_cast(x) - ack_frame.ack_block_section()->first_ack_block()}); @@ -479,7 +548,15 @@ QUICLossDetector::_determine_newly_acked_packets(const QUICAckFrame &ack_frame) x -= block.length() + 1; } - return numbers; + for (auto &&range : numbers) { + for (auto ite = this->_sent_packets[pn_space].rbegin(); ite != this->_sent_packets[pn_space].rend(); ite++) { + if (range.contains(ite->first)) { + packets.push_back(ite->second.get()); + } + } + } + + return packets; } void @@ -542,6 +619,16 @@ QUICLossDetector::_decrement_outstanding_counters(std::map_context.connection_info()->direction() == NET_VCONNECTION_OUT && + !((this->_context.key_info()->is_encryption_key_available(QUICKeyPhase::PHASE_1) && + this->_context.key_info()->is_decryption_key_available(QUICKeyPhase::PHASE_1)) || + (this->_context.key_info()->is_encryption_key_available(QUICKeyPhase::PHASE_0) && + this->_context.key_info()->is_decryption_key_available(QUICKeyPhase::PHASE_0))); +} + // // QUICRTTMeasure // @@ -566,30 +653,28 @@ QUICRTTMeasure::smoothed_rtt() const void QUICRTTMeasure::update_rtt(ink_hrtime latest_rtt, ink_hrtime ack_delay) { - // additional code this->_latest_rtt = latest_rtt; + if (this->_smoothed_rtt == 0) { + this->_min_rtt = 0; + this->_smoothed_rtt = this->_latest_rtt; + this->_rttvar = this->_latest_rtt / 2; + return; + } + // min_rtt ignores ack delay. this->_min_rtt = std::min(this->_min_rtt, latest_rtt); // Limit ack_delay by max_ack_delay ack_delay = std::min(ack_delay, this->_max_ack_delay); // Adjust for ack delay if it's plausible. - if (this->_latest_rtt - this->_min_rtt > ack_delay) { - this->_latest_rtt -= ack_delay; - - // the newest spec has removed the max_ack_delay assignment. but we need to assign it in somewhere - // this code is from draft-19 - this->_max_ack_delay = std::max(ack_delay, this->_max_ack_delay); + auto adjusted_rtt = this->_latest_rtt; + if (adjusted_rtt > this->_min_rtt + ack_delay) { + adjusted_rtt -= ack_delay; } + // Based on {{RFC6298}}. - if (this->_smoothed_rtt == 0) { - this->_smoothed_rtt = latest_rtt; - this->_rttvar = latest_rtt / 2.0; - } else { - double rttvar_sample = ABS(this->_smoothed_rtt - latest_rtt); - this->_rttvar = 3.0 / 4.0 * this->_rttvar + 1.0 / 4.0 * rttvar_sample; - this->_smoothed_rtt = 7.0 / 8.0 * this->_smoothed_rtt + 1.0 / 8.0 * latest_rtt; - } + this->_rttvar = 3.0 / 4.0 * this->_rttvar + 1.0 / 4.0 * ABS(this->_smoothed_rtt - adjusted_rtt); + this->_smoothed_rtt = 7.0 / 8.0 * this->_smoothed_rtt + 1.0 / 8.0 * adjusted_rtt; } ink_hrtime @@ -607,7 +692,7 @@ ink_hrtime QUICRTTMeasure::congestion_period(uint32_t threshold) const { ink_hrtime pto = this->_smoothed_rtt + std::max(this->_rttvar * 4, this->_k_granularity); - return pto * (1 << (threshold - 1)); + return pto * threshold; } ink_hrtime @@ -662,6 +747,12 @@ QUICRTTMeasure::pto_count() const return this->_pto_count; } +ink_hrtime +QUICRTTMeasure::k_granularity() const +{ + return this->_k_granularity; +} + void QUICRTTMeasure::reset() { @@ -669,5 +760,6 @@ QUICRTTMeasure::reset() this->_pto_count = 0; this->_smoothed_rtt = 0; this->_rttvar = 0; - this->_min_rtt = INT64_MAX; + this->_min_rtt = 0; + this->_latest_rtt = 0; } diff --git a/iocore/net/quic/QUICLossDetector.h b/iocore/net/quic/QUICLossDetector.h index 1b7a536a7c6..5e4005b8546 100644 --- a/iocore/net/quic/QUICLossDetector.h +++ b/iocore/net/quic/QUICLossDetector.h @@ -36,26 +36,14 @@ #include "QUICFrame.h" #include "QUICFrameHandler.h" #include "QUICConnection.h" +#include "QUICContext.h" +#include "QUICCongestionController.h" +class QUICPadder; +class QUICPinger; class QUICLossDetector; class QUICRTTMeasure; -struct QUICPacketInfo { - // 6.3.1. Sent Packet Fields - QUICPacketNumber packet_number; - ink_hrtime time_sent; - bool ack_eliciting; - bool is_crypto_packet; - bool in_flight; - size_t sent_bytes; - - // addition - QUICPacketType type; - std::vector frames; - QUICPacketNumberSpace pn_space; - // end -}; - using QUICPacketInfoUPtr = std::unique_ptr; class QUICRTTProvider @@ -68,19 +56,18 @@ class QUICRTTProvider virtual ink_hrtime congestion_period(uint32_t threshold) const = 0; }; -class QUICCongestionController +class QUICNewRenoCongestionController : public QUICCongestionController { public: - QUICCongestionController(const QUICRTTProvider &rtt_provider, QUICConnectionInfoProvider *info, const QUICCCConfig &cc_config); - virtual ~QUICCongestionController() {} - void on_packet_sent(size_t bytes_sent); - void on_packet_acked(const QUICPacketInfo &acked_packet); - virtual void on_packets_lost(const std::map &packets); - void on_retransmission_timeout_verified(); - void process_ecn(const QUICPacketInfo &acked_largest_packet, const QUICAckFrame::EcnSection *ecn_section); + QUICNewRenoCongestionController(QUICCCContext &context); + virtual ~QUICNewRenoCongestionController() {} + void on_packet_sent(size_t bytes_sent) override; + void on_packet_acked(const QUICPacketInfo &acked_packet) override; + virtual void on_packets_lost(const std::map &packets) override; + void process_ecn(const QUICPacketInfo &acked_largest_packet, const QUICAckFrame::EcnSection *ecn_section) override; bool check_credit() const; - uint32_t open_window() const; - void reset(); + uint32_t credit() const override; + void reset() override; bool is_app_limited(); // Debug @@ -88,6 +75,8 @@ class QUICCongestionController uint32_t congestion_window() const; uint32_t current_ssthresh() const; + void add_extra_credit() override; + private: Ptr _cc_mutex; @@ -97,32 +86,33 @@ class QUICCongestionController bool _in_window_lost(const std::map &lost_packets, QUICPacketInfo *largest_lost_packet, ink_hrtime period) const; + uint32_t _extra_packets_count = 0; + // [draft-17 recovery] 7.9.1. Constants of interest // Values will be loaded from records.config via QUICConfig at constructor uint32_t _k_max_datagram_size = 0; uint32_t _k_initial_window = 0; uint32_t _k_minimum_window = 0; float _k_loss_reduction_factor = 0.0; - uint32_t _k_persistent_congestion_threshold = 0; + uint32_t _k_persistent_congestion_threshold = 3; // [draft-17 recovery] 7.9.2. Variables of interest - uint32_t _ecn_ce_counter = 0; - uint32_t _bytes_in_flight = 0; - uint32_t _congestion_window = 0; - ink_hrtime _recovery_start_time = 0; - uint32_t _ssthresh = UINT32_MAX; + uint32_t _ecn_ce_counter = 0; + uint32_t _bytes_in_flight = 0; + uint32_t _congestion_window = 0; + ink_hrtime _congestion_recovery_start_time = 0; + uint32_t _ssthresh = UINT32_MAX; - QUICConnectionInfoProvider *_info = nullptr; - const QUICRTTProvider &_rtt_provider; + bool _in_congestion_recovery(ink_hrtime sent_time); - bool _in_recovery(ink_hrtime sent_time); + QUICCCContext &_context; }; class QUICLossDetector : public Continuation, public QUICFrameHandler { public: - QUICLossDetector(QUICConnectionInfoProvider *info, QUICCongestionController *cc, QUICRTTMeasure *rtt_measure, - const QUICLDConfig &ld_config); + QUICLossDetector(QUICLDContext &context, QUICCongestionController *cc, QUICRTTMeasure *rtt_measure, QUICPinger *pinger, + QUICPadder *padder); ~QUICLossDetector(); int event_handler(int event, Event *edata); @@ -178,15 +168,24 @@ class QUICLossDetector : public Continuation, public QUICFrameHandler ink_hrtime _get_earliest_loss_time(QUICPacketNumberSpace &pn_space); - std::set _determine_newly_acked_packets(const QUICAckFrame &ack_frame); + std::vector _determine_newly_acked_packets(const QUICAckFrame &ack_frame, int pn_space); + bool _include_ack_eliciting(const std::vector &acked_packets, int index) const; void _retransmit_all_unacked_crypto_data(); - void _send_one_packet(); - void _send_two_packets(); + void _send_one_or_two_packet(); + void _send_one_handshake_packets(); + void _send_one_padded_packets(); - QUICConnectionInfoProvider *_info = nullptr; - QUICRTTMeasure *_rtt_measure = nullptr; - QUICCongestionController *_cc = nullptr; + void _send_packet(QUICEncryptionLevel level, bool padded = false); + + bool _is_client_without_one_rtt_key() const; + + QUICRTTMeasure *_rtt_measure = nullptr; + QUICPinger *_pinger = nullptr; + QUICPadder *_padder = nullptr; + QUICCongestionController *_cc = nullptr; + + QUICLDContext &_context; }; class QUICRTTMeasure : public QUICRTTProvider @@ -219,11 +218,14 @@ class QUICRTTMeasure : public QUICRTTProvider void update_rtt(ink_hrtime latest_rtt, ink_hrtime ack_delay); void reset(); + ink_hrtime k_granularity() const; + private: // related to rtt calculate - uint32_t _crypto_count = 0; - uint32_t _pto_count = 0; - ink_hrtime _max_ack_delay = 0; + uint32_t _crypto_count = 0; + uint32_t _pto_count = 0; + // FIXME should be set by transport parameters + ink_hrtime _max_ack_delay = HRTIME_MSECONDS(25); // rtt vars ink_hrtime _latest_rtt = 0; @@ -233,5 +235,5 @@ class QUICRTTMeasure : public QUICRTTProvider // config ink_hrtime _k_granularity = 0; - ink_hrtime _k_initial_rtt = 0; + ink_hrtime _k_initial_rtt = HRTIME_MSECONDS(500); }; diff --git a/iocore/net/quic/QUICCongestionController.cc b/iocore/net/quic/QUICNewRenoCongestionController.cc similarity index 62% rename from iocore/net/quic/QUICCongestionController.cc rename to iocore/net/quic/QUICNewRenoCongestionController.cc index 79d8fd8df18..080c910ed4c 100644 --- a/iocore/net/quic/QUICCongestionController.cc +++ b/iocore/net/quic/QUICNewRenoCongestionController.cc @@ -24,22 +24,24 @@ #include #include -#define QUICCCDebug(fmt, ...) \ - Debug("quic_cc", \ - "[%s] " \ - "window: %" PRIu32 " bytes: %" PRIu32 " ssthresh: %" PRIu32 " " fmt, \ - this->_info->cids().data(), this->_congestion_window, this->_bytes_in_flight, this->_ssthresh, ##__VA_ARGS__) - -#define QUICCCError(fmt, ...) \ - Error("quic_cc", \ - "[%s] " \ - "window: %" PRIu32 " bytes: %" PRIu32 " ssthresh: %" PRIu32 " " fmt, \ - this->_info->cids().data(), this->_congestion_window, this->_bytes_in_flight, this->_ssthresh, ##__VA_ARGS__) - -QUICCongestionController::QUICCongestionController(const QUICRTTProvider &rtt_provider, QUICConnectionInfoProvider *info, - const QUICCCConfig &cc_config) - : _cc_mutex(new_ProxyMutex()), _info(info), _rtt_provider(rtt_provider) +#define QUICCCDebug(fmt, ...) \ + Debug("quic_cc", \ + "[%s] " \ + "window: %" PRIu32 " bytes: %" PRIu32 " ssthresh: %" PRIu32 " extra: %" PRIu32 " " fmt, \ + this->_context.connection_info()->cids().data(), this->_congestion_window, this->_bytes_in_flight, this->_ssthresh, \ + this->_extra_packets_count, ##__VA_ARGS__) + +#define QUICCCError(fmt, ...) \ + Error("quic_cc", \ + "[%s] " \ + "window: %" PRIu32 " bytes: %" PRIu32 " ssthresh: %" PRIu32 " extra %" PRIu32 " " fmt, \ + this->_context.connection_info()->cids().data(), this->_congestion_window, this->_bytes_in_flight, this->_ssthresh, \ + this->_extra_packets_count, ##__VA_ARGS__) + +QUICNewRenoCongestionController::QUICNewRenoCongestionController(QUICCCContext &context) + : _cc_mutex(new_ProxyMutex()), _context(context) { + auto &cc_config = context.cc_config(); this->_k_max_datagram_size = cc_config.max_datagram_size(); this->_k_initial_window = cc_config.initial_window(); this->_k_minimum_window = cc_config.minimum_window(); @@ -50,32 +52,36 @@ QUICCongestionController::QUICCongestionController(const QUICRTTProvider &rtt_pr } void -QUICCongestionController::on_packet_sent(size_t bytes_sent) +QUICNewRenoCongestionController::on_packet_sent(size_t bytes_sent) { SCOPED_MUTEX_LOCK(lock, this->_cc_mutex, this_ethread()); + if (this->_extra_packets_count > 0) { + --this->_extra_packets_count; + } + this->_bytes_in_flight += bytes_sent; } bool -QUICCongestionController::_in_recovery(ink_hrtime sent_time) +QUICNewRenoCongestionController::_in_congestion_recovery(ink_hrtime sent_time) { - return sent_time <= this->_recovery_start_time; + return sent_time <= this->_congestion_recovery_start_time; } bool -QUICCongestionController::is_app_limited() +QUICNewRenoCongestionController::is_app_limited() { // FIXME : don't known how does app worked here return false; } void -QUICCongestionController::on_packet_acked(const QUICPacketInfo &acked_packet) +QUICNewRenoCongestionController::on_packet_acked(const QUICPacketInfo &acked_packet) { // Remove from bytes_in_flight. SCOPED_MUTEX_LOCK(lock, this->_cc_mutex, this_ethread()); this->_bytes_in_flight -= acked_packet.sent_bytes; - if (this->_in_recovery(acked_packet.time_sent)) { + if (this->_in_congestion_recovery(acked_packet.time_sent)) { // Do not increase congestion window in recovery period. return; } @@ -101,12 +107,12 @@ QUICCongestionController::on_packet_acked(const QUICPacketInfo &acked_packet) // the original one is: // CongestionEvent(sent_time): void -QUICCongestionController::_congestion_event(ink_hrtime sent_time) +QUICNewRenoCongestionController::_congestion_event(ink_hrtime sent_time) { - // Start a new congestion event if the sent time is larger - // than the start time of the previous recovery epoch. - if (!this->_in_recovery(sent_time)) { - this->_recovery_start_time = Thread::get_hrtime(); + // Start a new congestion event if packet was sent after the + // start of the previous congestion recovery period. + if (!this->_in_congestion_recovery(sent_time)) { + this->_congestion_recovery_start_time = Thread::get_hrtime(); this->_congestion_window *= this->_k_loss_reduction_factor; this->_congestion_window = std::max(this->_congestion_window, this->_k_minimum_window); this->_ssthresh = this->_congestion_window; @@ -117,7 +123,8 @@ QUICCongestionController::_congestion_event(ink_hrtime sent_time) // the original one is: // ProcessECN(ack): void -QUICCongestionController::process_ecn(const QUICPacketInfo &acked_largest_packet, const QUICAckFrame::EcnSection *ecn_section) +QUICNewRenoCongestionController::process_ecn(const QUICPacketInfo &acked_largest_packet, + const QUICAckFrame::EcnSection *ecn_section) { // If the ECN-CE counter reported by the peer has increased, // this could be a new congestion event. @@ -131,10 +138,10 @@ QUICCongestionController::process_ecn(const QUICPacketInfo &acked_largest_packet } bool -QUICCongestionController::_in_persistent_congestion(const std::map &lost_packets, - QUICPacketInfo *largest_lost_packet) +QUICNewRenoCongestionController::_in_persistent_congestion(const std::map &lost_packets, + QUICPacketInfo *largest_lost_packet) { - ink_hrtime period = this->_rtt_provider.congestion_period(this->_k_persistent_congestion_threshold); + ink_hrtime period = this->_context.rtt_provider()->congestion_period(this->_k_persistent_congestion_threshold); // Determine if all packets in the window before the // newest lost packet, including the edges, are marked // lost @@ -145,7 +152,7 @@ QUICCongestionController::_in_persistent_congestion(const std::map &lost_packets) +QUICNewRenoCongestionController::on_packets_lost(const std::map &lost_packets) { if (lost_packets.empty()) { return; @@ -157,8 +164,6 @@ QUICCongestionController::on_packets_lost(const std::map_bytes_in_flight -= lost_packet.second->sent_bytes; } QUICPacketInfo *largest_lost_packet = lost_packets.rbegin()->second; - // Start a new recovery epoch if the lost packet is larger - // than the end of the previous recovery epoch. this->_congestion_event(largest_lost_packet->time_sent); // Collapse congestion window if persistent congestion @@ -168,7 +173,7 @@ QUICCongestionController::on_packets_lost(const std::map_bytes_in_flight >= this->_congestion_window) { QUICCCDebug("Congestion control pending"); @@ -178,8 +183,12 @@ QUICCongestionController::check_credit() const } uint32_t -QUICCongestionController::open_window() const +QUICNewRenoCongestionController::credit() const { + if (this->_extra_packets_count) { + return UINT32_MAX; + } + if (this->check_credit()) { return this->_congestion_window - this->_bytes_in_flight; } else { @@ -188,38 +197,38 @@ QUICCongestionController::open_window() const } uint32_t -QUICCongestionController::bytes_in_flight() const +QUICNewRenoCongestionController::bytes_in_flight() const { return this->_bytes_in_flight; } uint32_t -QUICCongestionController::congestion_window() const +QUICNewRenoCongestionController::congestion_window() const { return this->_congestion_window; } uint32_t -QUICCongestionController::current_ssthresh() const +QUICNewRenoCongestionController::current_ssthresh() const { return this->_ssthresh; } // [draft-17 recovery] 7.9.3. Initialization void -QUICCongestionController::reset() +QUICNewRenoCongestionController::reset() { SCOPED_MUTEX_LOCK(lock, this->_cc_mutex, this_ethread()); - this->_bytes_in_flight = 0; - this->_congestion_window = this->_k_initial_window; - this->_recovery_start_time = 0; - this->_ssthresh = UINT32_MAX; + this->_bytes_in_flight = 0; + this->_congestion_window = this->_k_initial_window; + this->_congestion_recovery_start_time = 0; + this->_ssthresh = UINT32_MAX; } bool -QUICCongestionController::_in_window_lost(const std::map &lost_packets, - QUICPacketInfo *largest_lost_packet, ink_hrtime period) const +QUICNewRenoCongestionController::_in_window_lost(const std::map &lost_packets, + QUICPacketInfo *largest_lost_packet, ink_hrtime period) const { // check whether packets are continuous. return true if all continuous packets are in period QUICPacketNumber next_expected = UINT64_MAX; @@ -240,3 +249,9 @@ QUICCongestionController::_in_window_lost(const std::map_extra_packets_count; +} diff --git a/iocore/net/quic/QUICPacket.cc b/iocore/net/quic/QUICPacket.cc index ec8ac37c6ba..534ed2770f7 100644 --- a/iocore/net/quic/QUICPacket.cc +++ b/iocore/net/quic/QUICPacket.cc @@ -69,6 +69,12 @@ QUICPacketHeader::from() const return this->_from; } +const IpEndpoint & +QUICPacketHeader::to() const +{ + return this->_to; +} + bool QUICPacketHeader::is_crypto_packet() const { @@ -82,16 +88,16 @@ QUICPacketHeader::packet_size() const } QUICPacketHeaderUPtr -QUICPacketHeader::load(const IpEndpoint from, ats_unique_buf buf, size_t len, QUICPacketNumber base) +QUICPacketHeader::load(const IpEndpoint from, const IpEndpoint to, ats_unique_buf buf, size_t len, QUICPacketNumber base) { QUICPacketHeaderUPtr header = QUICPacketHeaderUPtr(nullptr, &QUICPacketHeaderDeleter::delete_null_header); if (QUICInvariants::is_long_header(buf.get())) { QUICPacketLongHeader *long_header = quicPacketLongHeaderAllocator.alloc(); - new (long_header) QUICPacketLongHeader(from, std::move(buf), len, base); + new (long_header) QUICPacketLongHeader(from, to, std::move(buf), len, base); header = QUICPacketHeaderUPtr(long_header, &QUICPacketHeaderDeleter::delete_long_header); } else { QUICPacketShortHeader *short_header = quicPacketShortHeaderAllocator.alloc(); - new (short_header) QUICPacketShortHeader(from, std::move(buf), len, base); + new (short_header) QUICPacketShortHeader(from, to, std::move(buf), len, base); header = QUICPacketHeaderUPtr(short_header, &QUICPacketHeaderDeleter::delete_short_header); } return header; @@ -159,8 +165,9 @@ QUICPacketHeader::clone() const // QUICPacketLongHeader // -QUICPacketLongHeader::QUICPacketLongHeader(const IpEndpoint from, ats_unique_buf buf, size_t len, QUICPacketNumber base) - : QUICPacketHeader(from, std::move(buf), len, base) +QUICPacketLongHeader::QUICPacketLongHeader(const IpEndpoint from, const IpEndpoint to, ats_unique_buf buf, size_t len, + QUICPacketNumber base) + : QUICPacketHeader(from, to, std::move(buf), len, base) { this->_key_phase = QUICTypeUtil::key_phase(this->type()); uint8_t *raw_buf = this->_buf.get(); @@ -172,13 +179,15 @@ QUICPacketLongHeader::QUICPacketLongHeader(const IpEndpoint from, ats_unique_buf size_t offset = LONG_HDR_OFFSET_CONNECTION_ID; this->_destination_cid = {raw_buf + offset, dcil}; - offset += dcil; + offset += dcil + 1; this->_source_cid = {raw_buf + offset, scil}; offset += scil; if (this->type() != QUICPacketType::VERSION_NEGOTIATION) { if (this->type() == QUICPacketType::RETRY) { - uint8_t odcil = (raw_buf[0] & 0x0f) + 3; + uint8_t odcil = raw_buf[offset]; + offset += 1; + this->_original_dcid = {raw_buf + offset, odcil}; offset += odcil; } else { @@ -219,7 +228,7 @@ QUICPacketLongHeader::QUICPacketLongHeader(QUICPacketType type, QUICKeyPhase key { if (this->_type == QUICPacketType::VERSION_NEGOTIATION) { this->_buf_len = - LONG_HDR_OFFSET_CONNECTION_ID + this->_destination_cid.length() + this->_source_cid.length() + this->_payload_length; + LONG_HDR_OFFSET_CONNECTION_ID + this->_destination_cid.length() + 1 + this->_source_cid.length() + this->_payload_length; } else { this->buf(); } @@ -289,9 +298,6 @@ bool QUICPacketLongHeader::dcil(uint8_t &dcil, const uint8_t *packet, size_t packet_len) { if (QUICInvariants::dcil(dcil, packet, packet_len)) { - if (dcil != 0) { - dcil += 3; - } return true; } else { return false; @@ -302,9 +308,6 @@ bool QUICPacketLongHeader::scil(uint8_t &scil, const uint8_t *packet, size_t packet_len) { if (QUICInvariants::scil(scil, packet, packet_len)) { - if (scil != 0) { - scil += 3; - } return true; } else { return false; @@ -312,16 +315,16 @@ QUICPacketLongHeader::scil(uint8_t &scil, const uint8_t *packet, size_t packet_l } bool -QUICPacketLongHeader::token_length(size_t &token_length, uint8_t *field_len, const uint8_t *packet, size_t packet_len) +QUICPacketLongHeader::token_length(size_t &token_length, uint8_t &field_len, size_t &token_length_filed_offset, + const uint8_t *packet, size_t packet_len) { QUICPacketType type = QUICPacketType::UNINITIALIZED; QUICPacketLongHeader::type(type, packet, packet_len); if (type != QUICPacketType::INITIAL) { token_length = 0; - if (field_len) { - *field_len = 0; - } + field_len = 0; + return true; } @@ -329,66 +332,85 @@ QUICPacketLongHeader::token_length(size_t &token_length, uint8_t *field_len, con QUICPacketLongHeader::dcil(dcil, packet, packet_len); QUICPacketLongHeader::scil(scil, packet, packet_len); - size_t offset = LONG_HDR_OFFSET_CONNECTION_ID + dcil + scil; - if (offset >= packet_len) { + token_length_filed_offset = LONG_HDR_OFFSET_CONNECTION_ID + dcil + 1 + scil; + if (token_length_filed_offset >= packet_len) { return false; } - if (offset > packet_len) { + token_length = QUICIntUtil::read_QUICVariableInt(packet + token_length_filed_offset); + field_len = QUICVariableInt::size(packet + token_length_filed_offset); + + return true; +} + +bool +QUICPacketLongHeader::length(size_t &length, uint8_t &length_field_len, size_t &length_field_offset, const uint8_t *packet, + size_t packet_len) +{ + uint8_t dcil; + if (!QUICPacketLongHeader::dcil(dcil, packet, packet_len)) { return false; } - token_length = QUICIntUtil::read_QUICVariableInt(packet + offset); - if (field_len) { - *field_len = QUICVariableInt::size(packet + offset); + uint8_t scil; + if (!QUICPacketLongHeader::scil(scil, packet, packet_len)) { + return false; } + // Token Length (i) + Token (*) (for INITIAL packet) + size_t token_length = 0; + uint8_t token_length_field_len = 0; + size_t token_length_field_offset = 0; + if (!QUICPacketLongHeader::token_length(token_length, token_length_field_len, token_length_field_offset, packet, packet_len)) { + return false; + } + + // Length (i) + length_field_offset = LONG_HDR_OFFSET_CONNECTION_ID + dcil + 1 + scil + token_length_field_len + token_length; + if (length_field_offset >= packet_len) { + return false; + } + + length_field_len = QUICVariableInt::size(packet + length_field_offset); + length = QUICIntUtil::read_QUICVariableInt(packet + length_field_offset); + return true; } bool -QUICPacketLongHeader::length(size_t &length, uint8_t *field_len, const uint8_t *packet, size_t packet_len) +QUICPacketLongHeader::packet_number_offset(size_t &pn_offset, const uint8_t *packet, size_t packet_len) { - uint8_t dcil, scil; - QUICPacketLongHeader::dcil(dcil, packet, packet_len); - QUICPacketLongHeader::scil(scil, packet, packet_len); + size_t length; + uint8_t length_field_len; + size_t length_field_offset; - // Token Length (i) + Token (*) (for INITIAL packet) - size_t token_length = 0; - uint8_t token_length_field_len = 0; - if (!QUICPacketLongHeader::token_length(token_length, &token_length_field_len, packet, packet_len)) { + if (!QUICPacketLongHeader::length(length, length_field_len, length_field_offset, packet, packet_len)) { return false; } + pn_offset = length_field_offset + length_field_len; - // Length (i) - size_t length_offset = LONG_HDR_OFFSET_CONNECTION_ID + dcil + scil + token_length_field_len + token_length; - if (length_offset >= packet_len) { + if (pn_offset >= packet_len) { return false; } - length = QUICIntUtil::read_QUICVariableInt(packet + length_offset); - if (field_len) { - *field_len = QUICVariableInt::size(packet + length_offset); - } + return true; } bool -QUICPacketLongHeader::packet_number_offset(uint8_t &pn_offset, const uint8_t *packet, size_t packet_len) +QUICPacketLongHeader::packet_length(size_t &packet_len, const uint8_t *buf, size_t buf_len) { - QUICPacketType type; - QUICPacketLongHeader::type(type, packet, packet_len); - - uint8_t dcil, scil; - size_t token_length; - uint8_t token_length_field_len; size_t length; uint8_t length_field_len; - if (!QUICPacketLongHeader::dcil(dcil, packet, packet_len) || !QUICPacketLongHeader::scil(scil, packet, packet_len) || - !QUICPacketLongHeader::token_length(token_length, &token_length_field_len, packet, packet_len) || - !QUICPacketLongHeader::length(length, &length_field_len, packet, packet_len)) { + size_t length_field_offset; + + if (!QUICPacketLongHeader::length(length, length_field_len, length_field_offset, buf, buf_len)) { + return false; + } + packet_len = length + length_field_offset + length_field_len; + + if (packet_len > buf_len) { return false; } - pn_offset = 6 + dcil + scil + token_length_field_len + token_length + length_field_len; return true; } @@ -521,28 +543,49 @@ QUICPacketLongHeader::store(uint8_t *buf, size_t *len) const QUICTypeUtil::write_QUICVersion(this->_version, buf + *len, &n); *len += n; - buf[*len] = this->_destination_cid == QUICConnectionId::ZERO() ? 0 : (this->_destination_cid.length() - 3) << 4; - buf[*len] += this->_source_cid == QUICConnectionId::ZERO() ? 0 : this->_source_cid.length() - 3; - *len += 1; - + // DICD if (this->_destination_cid != QUICConnectionId::ZERO()) { + // Len + buf[*len] = this->_destination_cid.length(); + *len += 1; + + // ID QUICTypeUtil::write_QUICConnectionId(this->_destination_cid, buf + *len, &n); *len += n; + } else { + buf[*len] = 0; + *len += 1; } + + // SCID if (this->_source_cid != QUICConnectionId::ZERO()) { + // Len + buf[*len] = this->_source_cid.length(); + *len += 1; + + // ID QUICTypeUtil::write_QUICConnectionId(this->_source_cid, buf + *len, &n); *len += n; + } else { + buf[*len] = 0; + *len += 1; } if (this->_type != QUICPacketType::VERSION_NEGOTIATION) { if (this->_type == QUICPacketType::RETRY) { // Original Destination Connection ID if (this->_original_dcid != QUICConnectionId::ZERO()) { + // Len + buf[*len] = this->_original_dcid.length(); + *len += 1; + + // ID QUICTypeUtil::write_QUICConnectionId(this->_original_dcid, buf + *len, &n); *len += n; + } else { + buf[*len] = 0; + *len += 1; } - // ODCIL - buf[0] |= this->_original_dcid.length() - 3; } else { if (this->_type == QUICPacketType::INITIAL) { // Token Length Field @@ -590,8 +633,9 @@ QUICPacketLongHeader::store(uint8_t *buf, size_t *len) const // QUICPacketShortHeader // -QUICPacketShortHeader::QUICPacketShortHeader(const IpEndpoint from, ats_unique_buf buf, size_t len, QUICPacketNumber base) - : QUICPacketHeader(from, std::move(buf), len, base) +QUICPacketShortHeader::QUICPacketShortHeader(const IpEndpoint from, const IpEndpoint to, ats_unique_buf buf, size_t len, + QUICPacketNumber base) + : QUICPacketHeader(from, to, std::move(buf), len, base) { QUICInvariants::dcid(this->_connection_id, this->_buf.get(), len); @@ -718,7 +762,7 @@ QUICPacketShortHeader::key_phase(QUICKeyPhase &phase, const uint8_t *packet, siz } bool -QUICPacketShortHeader::packet_number_offset(uint8_t &pn_offset, const uint8_t *packet, size_t packet_len, int dcil) +QUICPacketShortHeader::packet_number_offset(size_t &pn_offset, const uint8_t *packet, size_t packet_len, int dcil) { pn_offset = 1 + dcil; return true; @@ -795,6 +839,12 @@ QUICPacket::from() const return this->_header->from(); } +const IpEndpoint & +QUICPacket::to() const +{ + return this->_header->to(); +} + UDPConnection * QUICPacket::udp_con() const { diff --git a/iocore/net/quic/QUICPacket.h b/iocore/net/quic/QUICPacket.h index dd9c9bcdb90..5fc834f45c1 100644 --- a/iocore/net/quic/QUICPacket.h +++ b/iocore/net/quic/QUICPacket.h @@ -55,8 +55,8 @@ using QUICPacketHeaderUPtr = std::unique_ptr &frames); - ~QUICPacket(); + virtual ~QUICPacket(); UDPConnection *udp_con() const; - const IpEndpoint &from() const; + virtual const IpEndpoint &from() const; + virtual const IpEndpoint &to() const; QUICPacketType type() const; QUICConnectionId destination_cid() const; QUICConnectionId source_cid() const; diff --git a/iocore/net/quic/QUICPacketFactory.cc b/iocore/net/quic/QUICPacketFactory.cc index 4c88c1b3151..ea82f4400c9 100644 --- a/iocore/net/quic/QUICPacketFactory.cc +++ b/iocore/net/quic/QUICPacketFactory.cc @@ -62,14 +62,14 @@ QUICPacketFactory::create_null_packet() } QUICPacketUPtr -QUICPacketFactory::create(UDPConnection *udp_con, IpEndpoint from, ats_unique_buf buf, size_t len, +QUICPacketFactory::create(UDPConnection *udp_con, IpEndpoint from, IpEndpoint to, ats_unique_buf buf, size_t len, QUICPacketNumber base_packet_number, QUICPacketCreationResult &result) { size_t max_plain_txt_len = 2048; ats_unique_buf plain_txt = ats_unique_malloc(max_plain_txt_len); size_t plain_txt_len = 0; - QUICPacketHeaderUPtr header = QUICPacketHeader::load(from, std::move(buf), len, base_packet_number); + QUICPacketHeaderUPtr header = QUICPacketHeader::load(from, to, std::move(buf), len, base_packet_number); QUICConnectionId dcid = header->destination_cid(); QUICConnectionId scid = header->source_cid(); @@ -238,7 +238,7 @@ QUICPacketFactory::create_handshake_packet(QUICConnectionId destination_cid, QUI QUICPacketNumber base_packet_number, ats_unique_buf payload, size_t len, bool retransmittable, bool probing, bool crypto) { - QUICPacketNumberSpace index = QUICTypeUtil::pn_space(QUICEncryptionLevel::INITIAL); + QUICPacketNumberSpace index = QUICTypeUtil::pn_space(QUICEncryptionLevel::HANDSHAKE); QUICPacketNumber pn = this->_packet_number_generator[static_cast(index)].next(); QUICPacketHeaderUPtr header = QUICPacketHeader::build(QUICPacketType::HANDSHAKE, QUICKeyPhase::HANDSHAKE, destination_cid, source_cid, pn, base_packet_number, @@ -251,7 +251,7 @@ QUICPacketFactory::create_zero_rtt_packet(QUICConnectionId destination_cid, QUIC QUICPacketNumber base_packet_number, ats_unique_buf payload, size_t len, bool retransmittable, bool probing) { - QUICPacketNumberSpace index = QUICTypeUtil::pn_space(QUICEncryptionLevel::INITIAL); + QUICPacketNumberSpace index = QUICTypeUtil::pn_space(QUICEncryptionLevel::ZERO_RTT); QUICPacketNumber pn = this->_packet_number_generator[static_cast(index)].next(); QUICPacketHeaderUPtr header = QUICPacketHeader::build(QUICPacketType::ZERO_RTT_PROTECTED, QUICKeyPhase::ZERO_RTT, destination_cid, source_cid, pn, @@ -263,7 +263,7 @@ QUICPacketUPtr QUICPacketFactory::create_protected_packet(QUICConnectionId connection_id, QUICPacketNumber base_packet_number, ats_unique_buf payload, size_t len, bool retransmittable, bool probing) { - QUICPacketNumberSpace index = QUICTypeUtil::pn_space(QUICEncryptionLevel::INITIAL); + QUICPacketNumberSpace index = QUICTypeUtil::pn_space(QUICEncryptionLevel::ONE_RTT); QUICPacketNumber pn = this->_packet_number_generator[static_cast(index)].next(); // TODO Key phase should be picked up from QUICHandshakeProtocol, probably QUICPacketHeaderUPtr header = QUICPacketHeader::build(QUICPacketType::PROTECTED, QUICKeyPhase::PHASE_0, connection_id, pn, @@ -274,19 +274,20 @@ QUICPacketFactory::create_protected_packet(QUICConnectionId connection_id, QUICP QUICPacketUPtr QUICPacketFactory::create_stateless_reset_packet(QUICConnectionId connection_id, QUICStatelessResetToken stateless_reset_token) { + constexpr uint8_t MIN_UNPREDICTABLE_FIELD_LEN = 5; std::random_device rnd; uint8_t random_packet_number = static_cast(rnd() & 0xFF); - size_t payload_len = static_cast((rnd() & 0xFF) | 16); // Mimimum length has to be 16 - ats_unique_buf payload = ats_unique_malloc(payload_len + 16); - uint8_t *naked_payload = payload.get(); + size_t payload_len = static_cast((rnd() & 0xFF) | (MIN_UNPREDICTABLE_FIELD_LEN + QUICStatelessResetToken::LEN)); + ats_unique_buf payload = ats_unique_malloc(payload_len); + uint8_t *naked_payload = payload.get(); // Generate random octets for (int i = payload_len - 1; i >= 0; --i) { naked_payload[i] = static_cast(rnd() & 0xFF); } // Copy stateless reset token into payload - memcpy(naked_payload + payload_len - 16, stateless_reset_token.buf(), 16); + memcpy(naked_payload + payload_len - QUICStatelessResetToken::LEN, stateless_reset_token.buf(), QUICStatelessResetToken::LEN); // KeyPhase won't be used QUICPacketHeaderUPtr header = QUICPacketHeader::build(QUICPacketType::STATELESS_RESET, QUICKeyPhase::INITIAL, connection_id, diff --git a/iocore/net/quic/QUICPacketFactory.h b/iocore/net/quic/QUICPacketFactory.h index a00639dfda4..732ad35514d 100644 --- a/iocore/net/quic/QUICPacketFactory.h +++ b/iocore/net/quic/QUICPacketFactory.h @@ -52,7 +52,7 @@ class QUICPacketFactory QUICPacketFactory(const QUICPacketProtectionKeyInfo &pp_key_info) : _pp_key_info(pp_key_info), _pp_protector(pp_key_info) {} - QUICPacketUPtr create(UDPConnection *udp_con, IpEndpoint from, ats_unique_buf buf, size_t len, + QUICPacketUPtr create(UDPConnection *udp_con, IpEndpoint from, IpEndpoint to, ats_unique_buf buf, size_t len, QUICPacketNumber base_packet_number, QUICPacketCreationResult &result); QUICPacketUPtr create_initial_packet(QUICConnectionId destination_cid, QUICConnectionId source_cid, QUICPacketNumber base_packet_number, ats_unique_buf payload, size_t len, bool ack_eliciting, diff --git a/iocore/net/quic/QUICPacketHeaderProtector.cc b/iocore/net/quic/QUICPacketHeaderProtector.cc index 49a29adb3ba..0dbfe8df2e7 100644 --- a/iocore/net/quic/QUICPacketHeaderProtector.cc +++ b/iocore/net/quic/QUICPacketHeaderProtector.cc @@ -152,25 +152,16 @@ QUICPacketHeaderProtector::_calc_sample_offset(uint8_t *sample_offset, const uin int dcil) const { if (QUICInvariants::is_long_header(protected_packet)) { - uint8_t dcil; - uint8_t scil; size_t dummy; uint8_t length_len; - QUICPacketLongHeader::dcil(dcil, protected_packet, protected_packet_len); - QUICPacketLongHeader::scil(scil, protected_packet, protected_packet_len); - QUICPacketLongHeader::length(dummy, &length_len, protected_packet, protected_packet_len); - *sample_offset = 6 + dcil + scil + length_len + 4; - - QUICPacketType type; - QUICPacketLongHeader::type(type, protected_packet, protected_packet_len); - if (type == QUICPacketType::INITIAL) { - size_t token_len; - uint8_t token_length_len; - QUICPacketLongHeader::token_length(token_len, &token_length_len, protected_packet, protected_packet_len); - *sample_offset += token_len + token_length_len; + size_t length_offset; + if (!QUICPacketLongHeader::length(dummy, length_len, length_offset, protected_packet, protected_packet_len)) { + return false; } + + *sample_offset = length_offset + length_len + 4; } else { - *sample_offset = 1 + dcil + 4; + *sample_offset = QUICInvariants::SH_DCID_OFFSET + dcil + 4; } return static_cast(*sample_offset + 16) <= protected_packet_len; @@ -179,7 +170,7 @@ QUICPacketHeaderProtector::_calc_sample_offset(uint8_t *sample_offset, const uin bool QUICPacketHeaderProtector::_unprotect(uint8_t *protected_packet, size_t protected_packet_len, const uint8_t *mask) const { - uint8_t pn_offset; + size_t pn_offset; // Unprotect packet number if (QUICInvariants::is_long_header(protected_packet)) { @@ -201,7 +192,7 @@ QUICPacketHeaderProtector::_unprotect(uint8_t *protected_packet, size_t protecte bool QUICPacketHeaderProtector::_protect(uint8_t *protected_packet, size_t protected_packet_len, const uint8_t *mask, int dcil) const { - uint8_t pn_offset; + size_t pn_offset; uint8_t pn_length = QUICTypeUtil::read_QUICPacketNumberLen(protected_packet); diff --git a/iocore/net/quic/QUICPacketProtectionKeyInfo.h b/iocore/net/quic/QUICPacketProtectionKeyInfo.h index 32a38d41383..71d077d8b10 100644 --- a/iocore/net/quic/QUICPacketProtectionKeyInfo.h +++ b/iocore/net/quic/QUICPacketProtectionKeyInfo.h @@ -26,11 +26,43 @@ #include "QUICTypes.h" #include "QUICKeyGenerator.h" -class QUICPacketProtectionKeyInfo +class QUICPacketProtectionKeyInfoProvider +{ +public: + virtual ~QUICPacketProtectionKeyInfoProvider() {} + // Payload Protection (common) + virtual const EVP_CIPHER *get_cipher(QUICKeyPhase phase) const = 0; + virtual size_t get_tag_len(QUICKeyPhase phase) const = 0; + + // Payload Protection (encryption) + virtual bool is_encryption_key_available(QUICKeyPhase phase) const = 0; + virtual const uint8_t *encryption_key(QUICKeyPhase phase) const = 0; + virtual size_t encryption_key_len(QUICKeyPhase phase) const = 0; + virtual const uint8_t *encryption_iv(QUICKeyPhase phase) const = 0; + virtual const size_t *encryption_iv_len(QUICKeyPhase phase) const = 0; + + // Payload Protection (decryption) + virtual bool is_decryption_key_available(QUICKeyPhase phase) const = 0; + virtual const uint8_t *decryption_key(QUICKeyPhase phase) const = 0; + virtual size_t decryption_key_len(QUICKeyPhase phase) const = 0; + virtual const uint8_t *decryption_iv(QUICKeyPhase phase) const = 0; + virtual const size_t *decryption_iv_len(QUICKeyPhase phase) const = 0; + + // Header Protection + virtual const EVP_CIPHER *get_cipher_for_hp(QUICKeyPhase phase) const = 0; + virtual const uint8_t *encryption_key_for_hp(QUICKeyPhase phase) const = 0; + virtual size_t encryption_key_for_hp_len(QUICKeyPhase phase) const = 0; + virtual const uint8_t *decryption_key_for_hp(QUICKeyPhase phase) const = 0; + virtual size_t decryption_key_for_hp_len(QUICKeyPhase phase) const = 0; +}; + +class QUICPacketProtectionKeyInfo : public QUICPacketProtectionKeyInfoProvider { public: enum class Context { SERVER, CLIENT }; + virtual ~QUICPacketProtectionKeyInfo() {} + // FIXME This should be passed to the constructor but NetVC cannot pass it because it has set_context too. void set_context(Context ctx); @@ -38,58 +70,58 @@ class QUICPacketProtectionKeyInfo // Payload Protection (common) - virtual const EVP_CIPHER *get_cipher(QUICKeyPhase phase) const; - virtual size_t get_tag_len(QUICKeyPhase phase) const; + virtual const EVP_CIPHER *get_cipher(QUICKeyPhase phase) const override; + virtual size_t get_tag_len(QUICKeyPhase phase) const override; virtual void set_cipher_initial(const EVP_CIPHER *cipher); virtual void set_cipher(const EVP_CIPHER *cipher, size_t tag_len); // Payload Protection (encryption) - virtual bool is_encryption_key_available(QUICKeyPhase phase) const; + virtual bool is_encryption_key_available(QUICKeyPhase phase) const override; virtual void set_encryption_key_available(QUICKeyPhase phase); - virtual const uint8_t *encryption_key(QUICKeyPhase phase) const; + virtual const uint8_t *encryption_key(QUICKeyPhase phase) const override; virtual uint8_t *encryption_key(QUICKeyPhase phase); - virtual size_t encryption_key_len(QUICKeyPhase phase) const; + virtual size_t encryption_key_len(QUICKeyPhase phase) const override; - virtual const uint8_t *encryption_iv(QUICKeyPhase phase) const; + virtual const uint8_t *encryption_iv(QUICKeyPhase phase) const override; virtual uint8_t *encryption_iv(QUICKeyPhase phase); - virtual const size_t *encryption_iv_len(QUICKeyPhase phase) const; + virtual const size_t *encryption_iv_len(QUICKeyPhase phase) const override; virtual size_t *encryption_iv_len(QUICKeyPhase phase); // Payload Protection (decryption) - virtual bool is_decryption_key_available(QUICKeyPhase phase) const; + virtual bool is_decryption_key_available(QUICKeyPhase phase) const override; virtual void set_decryption_key_available(QUICKeyPhase phase); - virtual const uint8_t *decryption_key(QUICKeyPhase phase) const; + virtual const uint8_t *decryption_key(QUICKeyPhase phase) const override; virtual uint8_t *decryption_key(QUICKeyPhase phase); - virtual size_t decryption_key_len(QUICKeyPhase phase) const; + virtual size_t decryption_key_len(QUICKeyPhase phase) const override; - virtual const uint8_t *decryption_iv(QUICKeyPhase phase) const; + virtual const uint8_t *decryption_iv(QUICKeyPhase phase) const override; virtual uint8_t *decryption_iv(QUICKeyPhase phase); - virtual const size_t *decryption_iv_len(QUICKeyPhase phase) const; + virtual const size_t *decryption_iv_len(QUICKeyPhase phase) const override; virtual size_t *decryption_iv_len(QUICKeyPhase phase); // Header Protection - virtual const EVP_CIPHER *get_cipher_for_hp(QUICKeyPhase phase) const; + virtual const EVP_CIPHER *get_cipher_for_hp(QUICKeyPhase phase) const override; virtual void set_cipher_for_hp_initial(const EVP_CIPHER *cipher); virtual void set_cipher_for_hp(const EVP_CIPHER *cipher); - virtual const uint8_t *encryption_key_for_hp(QUICKeyPhase phase) const; + virtual const uint8_t *encryption_key_for_hp(QUICKeyPhase phase) const override; virtual uint8_t *encryption_key_for_hp(QUICKeyPhase phase); - virtual size_t encryption_key_for_hp_len(QUICKeyPhase phase) const; + virtual size_t encryption_key_for_hp_len(QUICKeyPhase phase) const override; - virtual const uint8_t *decryption_key_for_hp(QUICKeyPhase phase) const; + virtual const uint8_t *decryption_key_for_hp(QUICKeyPhase phase) const override; virtual uint8_t *decryption_key_for_hp(QUICKeyPhase phase); - virtual size_t decryption_key_for_hp_len(QUICKeyPhase phase) const; + virtual size_t decryption_key_for_hp_len(QUICKeyPhase phase) const override; private: Context _ctx = Context::SERVER; diff --git a/iocore/net/quic/QUICPacketReceiveQueue.cc b/iocore/net/quic/QUICPacketReceiveQueue.cc index 405c29533de..c90385bcffc 100644 --- a/iocore/net/quic/QUICPacketReceiveQueue.cc +++ b/iocore/net/quic/QUICPacketReceiveQueue.cc @@ -26,42 +26,12 @@ #include "QUICIntUtil.h" -// FIXME: workaround for coalescing packets -static constexpr int LONG_HDR_OFFSET_CONNECTION_ID = 6; - static bool is_vn(QUICVersion v) { return v == 0x0; } -static bool -long_hdr_pkt_len(size_t &pkt_len, uint8_t *buf, size_t len) -{ - uint8_t dcil, scil; - QUICPacketLongHeader::dcil(dcil, buf, len); - QUICPacketLongHeader::scil(scil, buf, len); - - size_t offset = LONG_HDR_OFFSET_CONNECTION_ID + dcil + scil; - - // token_length and token_length_field_len should be 0 except INITIAL packet - size_t token_length = 0; - uint8_t token_length_field_len = 0; - if (!QUICPacketLongHeader::token_length(token_length, &token_length_field_len, buf, len)) { - return false; - } - - size_t length = 0; - uint8_t length_field_len = 0; - if (!QUICPacketLongHeader::length(length, &length_field_len, buf, len)) { - return false; - } - - pkt_len = offset + token_length + token_length_field_len + length_field_len + length; - - return true; -} - QUICPacketReceiveQueue::QUICPacketReceiveQueue(QUICPacketFactory &packet_factory, QUICPacketHeaderProtector &ph_protector) : _packet_factory(packet_factory), _ph_protector(ph_protector) { @@ -91,6 +61,7 @@ QUICPacketReceiveQueue::dequeue(QUICPacketCreationResult &result) // Create a QUIC packet this->_udp_con = udp_packet->getConnection(); this->_from = udp_packet->from; + this->_to = udp_packet->to; this->_payload_len = udp_packet->getPktLength(); this->_payload = ats_unique_malloc(this->_payload_len); IOBufferBlock *b = udp_packet->getIOBlockChain(); @@ -124,7 +95,7 @@ QUICPacketReceiveQueue::dequeue(QUICPacketCreationResult &result) if (type == QUICPacketType::RETRY) { pkt_len = remaining_len; } else { - if (!long_hdr_pkt_len(pkt_len, this->_payload.get() + this->_offset, remaining_len)) { + if (!QUICPacketLongHeader::packet_length(pkt_len, this->_payload.get() + this->_offset, remaining_len)) { this->_payload.release(); this->_payload = nullptr; this->_payload_len = 0; @@ -177,7 +148,7 @@ QUICPacketReceiveQueue::dequeue(QUICPacketCreationResult &result) } if (this->_ph_protector.unprotect(pkt.get(), pkt_len)) { - quic_packet = this->_packet_factory.create(this->_udp_con, this->_from, std::move(pkt), pkt_len, + quic_packet = this->_packet_factory.create(this->_udp_con, this->_from, this->_to, std::move(pkt), pkt_len, this->_largest_received_packet_number, result); } else { // ZERO_RTT might be rejected diff --git a/iocore/net/quic/QUICPacketReceiveQueue.h b/iocore/net/quic/QUICPacketReceiveQueue.h index 5027df37b9a..e4e3e297209 100644 --- a/iocore/net/quic/QUICPacketReceiveQueue.h +++ b/iocore/net/quic/QUICPacketReceiveQueue.h @@ -51,4 +51,5 @@ class QUICPacketReceiveQueue size_t _offset = 0; UDPConnection *_udp_con; IpEndpoint _from; + IpEndpoint _to; }; diff --git a/iocore/net/quic/QUICPadder.cc b/iocore/net/quic/QUICPadder.cc new file mode 100644 index 00000000000..0ae913ebb9a --- /dev/null +++ b/iocore/net/quic/QUICPadder.cc @@ -0,0 +1,109 @@ +/** @file + + A brief file description + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "QUICIntUtil.h" +#include "QUICPadder.h" + +static constexpr uint32_t MINIMUM_INITIAL_PACKET_SIZE = 1200; +static constexpr uint32_t MIN_PKT_PAYLOAD_LEN = 3; ///< Minimum payload length for sampling for header protection + +void +QUICPadder::request(QUICEncryptionLevel level) +{ + SCOPED_MUTEX_LOCK(lock, this->_mutex, this_ethread()); + ++this->_need_to_fire[static_cast(level)]; +} + +void +QUICPadder::cancel(QUICEncryptionLevel level) +{ + SCOPED_MUTEX_LOCK(lock, this->_mutex, this_ethread()); + this->_need_to_fire[static_cast(level)] = 0; +} + +uint64_t +QUICPadder::count(QUICEncryptionLevel level) +{ + SCOPED_MUTEX_LOCK(lock, this->_mutex, this_ethread()); + return this->_need_to_fire[static_cast(level)]; +} + +bool +QUICPadder::_will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting) +{ + SCOPED_MUTEX_LOCK(lock, this->_mutex, this_ethread()); + // no extre padding packet + if (current_packet_size == 0 && this->_need_to_fire[static_cast(level)] == 0) { + return false; + } + + // every packets need to be padded + return true; +} + +QUICFrame * +QUICPadder::_generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, + size_t current_packet_size) +{ + SCOPED_MUTEX_LOCK(lock, this->_mutex, this_ethread()); + QUICFrame *frame = nullptr; + + uint64_t min_size = 0; + if (level == QUICEncryptionLevel::INITIAL && this->_context == NET_VCONNECTION_OUT) { + min_size = this->_minimum_quic_packet_size(); + if (this->_av_token_len && min_size > (QUICVariableInt::size(this->_av_token_len) + this->_av_token_len)) { + min_size -= (QUICVariableInt::size(this->_av_token_len) + this->_av_token_len); + } + } else { + min_size = MIN_PKT_PAYLOAD_LEN; + } + + if (min_size > current_packet_size) { // ignore if we don't need to pad. + frame = QUICFrameFactory::create_padding_frame( + buf, std::min(min_size - current_packet_size, static_cast(maximum_frame_size))); + } + + this->_need_to_fire[static_cast(level)] = 0; + return frame; +} + +uint32_t +QUICPadder::_minimum_quic_packet_size() +{ + SCOPED_MUTEX_LOCK(lock, this->_mutex, this_ethread()); + if (this->_context == NET_VCONNECTION_OUT) { + // FIXME Only the first packet need to be 1200 bytes at least + return MINIMUM_INITIAL_PACKET_SIZE; + } else { + // FIXME This size should be configurable and should have some randomness + // This is just for providing protection against packet analysis for protected packets + return 32 + (this->_rnd() & 0x3f); // 32 to 96 + } +} + +void +QUICPadder::set_av_token_len(uint32_t len) +{ + SCOPED_MUTEX_LOCK(lock, this->_mutex, this_ethread()); + this->_av_token_len = len; +} diff --git a/iocore/net/quic/QUICPadder.h b/iocore/net/quic/QUICPadder.h new file mode 100644 index 00000000000..bba8dfc631b --- /dev/null +++ b/iocore/net/quic/QUICPadder.h @@ -0,0 +1,57 @@ +/** @file + * + * A brief file description + * + * @section license License + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "QUICTypes.h" +#include "QUICFrameHandler.h" +#include "QUICFrameGenerator.h" + +#include "I_Lock.h" + +class QUICPadder : public QUICFrameOnceGenerator +{ +public: + QUICPadder(NetVConnectionContext_t context) : _mutex(new_ProxyMutex()), _context(context) {} + + void request(QUICEncryptionLevel level); + void cancel(QUICEncryptionLevel level); + uint64_t count(QUICEncryptionLevel level); + void set_av_token_len(uint32_t len); + +private: + uint32_t _minimum_quic_packet_size(); + + // QUICFrameGenerator + bool _will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting) override; + QUICFrame *_generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, + size_t current_packet_size) override; + + Ptr _mutex; + std::random_device _rnd; + + uint32_t _av_token_len = 0; + // Initial, 0/1-RTT, and Handshake + uint64_t _need_to_fire[4] = {0}; + NetVConnectionContext_t _context = NET_VCONNECTION_OUT; +}; diff --git a/iocore/net/quic/QUICPathManager.cc b/iocore/net/quic/QUICPathManager.cc new file mode 100644 index 00000000000..613efecbe19 --- /dev/null +++ b/iocore/net/quic/QUICPathManager.cc @@ -0,0 +1,84 @@ +/** @file + * + * A brief file description + * + * @section license License + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "QUICPathManager.h" +#include "QUICPathValidator.h" +#include "QUICConnection.h" + +#define QUICDebug(fmt, ...) Debug("quic_path", "[%s] " fmt, this->_cinfo.cids().data(), ##__VA_ARGS__) + +void +QUICPathManager::open_new_path(const QUICPath &path, ink_hrtime timeout_in) +{ + if (this->_verify_timeout_at == 0) { + // Overwrite _previous_path only if _current_path is verified + // _previous_path should always have a verified path if available + this->_previous_path = this->_current_path; + } + this->_current_path = path; + this->_path_validator.validate(path); + this->_verify_timeout_at = Thread::get_hrtime() + timeout_in; +} + +void +QUICPathManager::set_trusted_path(const QUICPath &path) +{ + this->_current_path = path; + this->_previous_path = path; +} + +void +QUICPathManager::_check_verify_timeout() +{ + if (this->_verify_timeout_at != 0) { + if (this->_path_validator.is_validated(this->_current_path)) { + // Address validation succeeded + this->_verify_timeout_at = 0; + this->_previous_path = {{}, {}}; + } else if (this->_verify_timeout_at < Thread::get_hrtime()) { + // Address validation failed + QUICDebug("Switching back to the previous path"); + this->_current_path = this->_previous_path; + this->_verify_timeout_at = 0; + this->_previous_path = {{}, {}}; + } + } +} + +const QUICPath & +QUICPathManager::get_current_path() +{ + this->_check_verify_timeout(); + return this->_current_path; +} + +const QUICPath & +QUICPathManager::get_verified_path() +{ + this->_check_verify_timeout(); + if (this->_verify_timeout_at != 0) { + return this->_previous_path; + } else { + return this->_current_path; + } +} diff --git a/iocore/net/quic/QUICPathManager.h b/iocore/net/quic/QUICPathManager.h new file mode 100644 index 00000000000..9f9eb37b8eb --- /dev/null +++ b/iocore/net/quic/QUICPathManager.h @@ -0,0 +1,53 @@ +/** @file + * + * A brief file description + * + * @section license License + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "QUICTypes.h" + +class QUICConnectionInfoProvider; +class QUICPathValidator; + +class QUICPathManager +{ +public: + QUICPathManager(const QUICConnectionInfoProvider &info, QUICPathValidator &path_validator) + : _cinfo(info), _path_validator(path_validator) + { + } + + const QUICPath &get_current_path(); + const QUICPath &get_verified_path(); + void open_new_path(const QUICPath &path, ink_hrtime timeout_in); + void set_trusted_path(const QUICPath &path); + +private: + const QUICConnectionInfoProvider &_cinfo; + QUICPathValidator &_path_validator; + + ink_hrtime _verify_timeout_at = 0; + QUICPath _current_path = {{}, {}}; + QUICPath _previous_path = {{}, {}}; + + void _check_verify_timeout(); +}; diff --git a/iocore/net/quic/QUICPathValidator.cc b/iocore/net/quic/QUICPathValidator.cc index 40a23904886..21a97c91c5f 100644 --- a/iocore/net/quic/QUICPathValidator.cc +++ b/iocore/net/quic/QUICPathValidator.cc @@ -23,32 +23,85 @@ #include #include "QUICPathValidator.h" +#include "QUICPacket.h" + +#define QUICDebug(fmt, ...) Debug("quic_path", "[%s] " fmt, this->_cinfo.cids().data(), ##__VA_ARGS__) bool -QUICPathValidator::is_validating() +QUICPathValidator::ValidationJob::has_more_challenges() const { - return this->_state == ValidationState::VALIDATING; + return this->_has_outgoing_challenge; +} + +const uint8_t * +QUICPathValidator::ValidationJob::get_next_challenge() const +{ + if (this->_has_outgoing_challenge) { + return this->_outgoing_challenge + ((this->_has_outgoing_challenge - 1) * 8); + } else { + return nullptr; + } +} + +void +QUICPathValidator::ValidationJob::consume_challenge() +{ + --(this->_has_outgoing_challenge); } bool -QUICPathValidator::is_validated() +QUICPathValidator::is_validating(const QUICPath &path) { - return this->_state == ValidationState::VALIDATED; + if (auto j = this->_jobs.find(path); j != this->_jobs.end()) { + return j->second.is_validating(); + } else { + return false; + } +} + +bool +QUICPathValidator::is_validated(const QUICPath &path) +{ + if (auto j = this->_jobs.find(path); j != this->_jobs.end()) { + return j->second.is_validated(); + } else { + return false; + } } void -QUICPathValidator::validate() +QUICPathValidator::validate(const QUICPath &path) { - if (this->_state == ValidationState::VALIDATING) { + if (this->_jobs.find(path) != this->_jobs.end()) { // Do nothing } else { - this->_state = ValidationState::VALIDATING; - this->_generate_challenge(); + auto result = this->_jobs.emplace(std::piecewise_construct, std::forward_as_tuple(path), std::forward_as_tuple()); + result.first->second.start(); + // QUICDebug("Validating a path between %s and %s", path.local_ep(), path.remote_ep()); } } +bool +QUICPathValidator::ValidationJob::is_validating() +{ + return this->_state == ValidationState::VALIDATING; +} + +bool +QUICPathValidator::ValidationJob::is_validated() +{ + return this->_state == ValidationState::VALIDATED; +} + +void +QUICPathValidator::ValidationJob::start() +{ + this->_state = ValidationState::VALIDATING; + this->_generate_challenge(); +} + void -QUICPathValidator::_generate_challenge() +QUICPathValidator::ValidationJob::_generate_challenge() { size_t seed = std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); @@ -60,29 +113,17 @@ QUICPathValidator::_generate_challenge() this->_has_outgoing_challenge = 3; } -void -QUICPathValidator::_generate_response(const QUICPathChallengeFrame &frame) -{ - memcpy(this->_incoming_challenge, frame.data(), QUICPathChallengeFrame::DATA_LEN); - this->_has_outgoing_response = true; -} - -QUICConnectionErrorUPtr -QUICPathValidator::_validate_response(const QUICPathResponseFrame &frame) +bool +QUICPathValidator::ValidationJob::validate_response(const uint8_t *data) { - QUICConnectionErrorUPtr error = std::make_unique(QUICTransErrorCode::PROTOCOL_VIOLATION); - for (int i = 0; i < 3; ++i) { - if (memcmp(this->_outgoing_challenge + (QUICPathChallengeFrame::DATA_LEN * i), frame.data(), - QUICPathChallengeFrame::DATA_LEN) == 0) { + if (memcmp(this->_outgoing_challenge + (QUICPathChallengeFrame::DATA_LEN * i), data, QUICPathChallengeFrame::DATA_LEN) == 0) { this->_state = ValidationState::VALIDATED; this->_has_outgoing_challenge = 0; - error = nullptr; - break; + return true; } } - - return error; + return false; } // @@ -101,10 +142,21 @@ QUICPathValidator::handle_frame(QUICEncryptionLevel level, const QUICFrame &fram switch (frame.type()) { case QUICFrameType::PATH_CHALLENGE: - this->_generate_response(static_cast(frame)); + this->_incoming_challenges.emplace(this->_incoming_challenges.begin(), + static_cast(frame).data()); break; case QUICFrameType::PATH_RESPONSE: - error = this->_validate_response(static_cast(frame)); + if (auto item = this->_jobs.find({frame.packet()->to(), frame.packet()->from()}); item != this->_jobs.end()) { + if (item->second.validate_response(static_cast(frame).data())) { + QUICDebug("validation succeeded"); + this->_on_validation_callback(true); + } else { + QUICDebug("validation failed"); + this->_on_validation_callback(false); + } + } else { + error = std::make_unique(QUICTransErrorCode::PROTOCOL_VIOLATION); + } break; default: ink_assert(!"Can't happen"); @@ -117,17 +169,30 @@ QUICPathValidator::handle_frame(QUICEncryptionLevel level, const QUICFrame &fram // QUICFrameGenerator // bool -QUICPathValidator::will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) +QUICPathValidator::will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) { if (!this->_is_level_matched(level)) { return false; } - if (this->_last_sent_at == timestamp) { + if (this->_latest_seq_num == seq_num) { return false; } - return (this->_has_outgoing_challenge || this->_has_outgoing_response); + // Check challenges + for (auto &&item : this->_jobs) { + auto &j = item.second; + if (!j.is_validating() && !j.is_validated()) { + j.start(); + return true; + } + if (j.has_more_challenges()) { + return true; + } + } + + // Check responses + return !this->_incoming_challenges.empty(); } /** @@ -135,7 +200,7 @@ QUICPathValidator::will_generate_frame(QUICEncryptionLevel level, ink_hrtime tim */ QUICFrame * QUICPathValidator::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t /* connection_credit */, - uint16_t maximum_frame_size, ink_hrtime timestamp) + uint16_t maximum_frame_size, size_t current_packet_size, uint32_t seq_num) { QUICFrame *frame = nullptr; @@ -143,27 +208,31 @@ QUICPathValidator::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint6 return frame; } - if (this->_has_outgoing_response) { - frame = QUICFrameFactory::create_path_response_frame(buf, this->_incoming_challenge); + if (!this->_incoming_challenges.empty()) { + frame = QUICFrameFactory::create_path_response_frame(buf, this->_incoming_challenges.back()); if (frame && frame->size() > maximum_frame_size) { // Cancel generating frame frame = nullptr; } else { - this->_has_outgoing_response = false; + this->_incoming_challenges.pop_back(); } - } else if (this->_has_outgoing_challenge) { - frame = QUICFrameFactory::create_path_challenge_frame( - buf, this->_outgoing_challenge + (QUICPathChallengeFrame::DATA_LEN * (this->_has_outgoing_challenge - 1))); - if (frame && frame->size() > maximum_frame_size) { - // Cancel generating frame - frame = nullptr; - } else { - --this->_has_outgoing_challenge; - ink_assert(this->_has_outgoing_challenge >= 0); + } else { + for (auto &&item : this->_jobs) { + auto &j = item.second; + if (j.has_more_challenges()) { + frame = QUICFrameFactory::create_path_challenge_frame(buf, j.get_next_challenge()); + if (frame && frame->size() > maximum_frame_size) { + // Cancel generating frame + frame = nullptr; + } else { + j.consume_challenge(); + } + break; + } } } - this->_last_sent_at = timestamp; + this->_latest_seq_num = seq_num; return frame; } diff --git a/iocore/net/quic/QUICPathValidator.h b/iocore/net/quic/QUICPathValidator.h index 47a2975d108..c575f5a596e 100644 --- a/iocore/net/quic/QUICPathValidator.h +++ b/iocore/net/quic/QUICPathValidator.h @@ -24,26 +24,31 @@ #pragma once #include +#include #include "QUICTypes.h" #include "QUICFrameHandler.h" #include "QUICFrameGenerator.h" +#include "QUICConnection.h" class QUICPathValidator : public QUICFrameHandler, public QUICFrameGenerator { public: - QUICPathValidator() {} - bool is_validating(); - bool is_validated(); - void validate(); + QUICPathValidator(const QUICConnectionInfoProvider &info, std::function callback) + : _cinfo(info), _on_validation_callback(callback) + { + } + bool is_validating(const QUICPath &path); + bool is_validated(const QUICPath &path); + void validate(const QUICPath &path); // QUICFrameHandler std::vector interests() override; QUICConnectionErrorUPtr handle_frame(QUICEncryptionLevel level, const QUICFrame &frame) override; // QUICFrameGeneratro - bool will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) override; + bool will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) override; QUICFrame *generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, - ink_hrtime timestamp) override; + size_t current_packet_size, uint32_t seq_num) override; private: enum class ValidationState : int { @@ -51,14 +56,33 @@ class QUICPathValidator : public QUICFrameHandler, public QUICFrameGenerator VALIDATING, VALIDATED, }; - ValidationState _state = ValidationState::NOT_VALIDATED; - int _has_outgoing_challenge = 0; - bool _has_outgoing_response = false; - ink_hrtime _last_sent_at = 0; - uint8_t _incoming_challenge[QUICPathChallengeFrame::DATA_LEN]; - uint8_t _outgoing_challenge[QUICPathChallengeFrame::DATA_LEN * 3]; - void _generate_challenge(); - void _generate_response(const QUICPathChallengeFrame &frame); - QUICConnectionErrorUPtr _validate_response(const QUICPathResponseFrame &frame); + class ValidationJob + { + public: + ValidationJob(){}; + ~ValidationJob(){}; + bool is_validating(); + bool is_validated(); + void start(); + bool validate_response(const uint8_t *data); + bool has_more_challenges() const; + const uint8_t *get_next_challenge() const; + void consume_challenge(); + + private: + ValidationState _state = ValidationState::NOT_VALIDATED; + uint8_t _outgoing_challenge[QUICPathChallengeFrame::DATA_LEN * 3]; + int _has_outgoing_challenge = 0; + + void _generate_challenge(); + }; + + const QUICConnectionInfoProvider &_cinfo; + std::unordered_map _jobs; + + std::function _on_validation_callback; + + uint32_t _latest_seq_num = 0; + std::vector _incoming_challenges; }; diff --git a/iocore/net/quic/QUICPinger.cc b/iocore/net/quic/QUICPinger.cc index e6f69c69d5d..84454c8eb66 100644 --- a/iocore/net/quic/QUICPinger.cc +++ b/iocore/net/quic/QUICPinger.cc @@ -24,54 +24,72 @@ #include "QUICPinger.h" void -QUICPinger::request(QUICEncryptionLevel level) +QUICPinger::request() { - if (!this->_is_level_matched(level)) { - return; - } - ++this->_need_to_fire[static_cast(level)]; + SCOPED_MUTEX_LOCK(lock, this->_mutex, this_ethread()); + ++this->_need_to_fire; } void -QUICPinger::cancel(QUICEncryptionLevel level) +QUICPinger::cancel() { - if (!this->_is_level_matched(level)) { - return; - } - - if (this->_need_to_fire[static_cast(level)] > 0) { - --this->_need_to_fire[static_cast(level)]; + SCOPED_MUTEX_LOCK(lock, this->_mutex, this_ethread()); + if (this->_need_to_fire > 0) { + --this->_need_to_fire; } } bool -QUICPinger::will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) +QUICPinger::_will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting) { - if (!this->_is_level_matched(level)) { + SCOPED_MUTEX_LOCK(lock, this->_mutex, this_ethread()); + + if (level != QUICEncryptionLevel::ONE_RTT) { return false; } - return this->_need_to_fire[static_cast(QUICTypeUtil::pn_space(level))] > 0; + // PING Frame is meaningless for ack_eliciting packet. Cancel it. + if (ack_eliciting) { + this->_ack_eliciting_packet_out = true; + this->cancel(); + return false; + } + + if (this->_ack_eliciting_packet_out == false && !ack_eliciting && current_packet_size > 0 && this->_need_to_fire == 0) { + // force to send an PING Frame + this->request(); + } + + // only update `_ack_eliciting_packet_out` when we has something to send. + if (current_packet_size) { + this->_ack_eliciting_packet_out = ack_eliciting; + } + return this->_need_to_fire > 0; } /** * @param connection_credit This is not used. Because PING frame is not flow-controlled */ QUICFrame * -QUICPinger::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t /* connection_credit */, uint16_t maximum_frame_size, - ink_hrtime timestamp) +QUICPinger::_generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t /* connection_credit */, uint16_t maximum_frame_size, + size_t current_packet_size) { + SCOPED_MUTEX_LOCK(lock, this->_mutex, this_ethread()); QUICFrame *frame = nullptr; - if (!this->_is_level_matched(level)) { - return frame; - } - - if (this->_need_to_fire[static_cast(level)] > 0 && maximum_frame_size > 0) { + if (level == QUICEncryptionLevel::ONE_RTT && this->_need_to_fire > 0 && maximum_frame_size > 0) { // don't care ping frame lost or acked - frame = QUICFrameFactory::create_ping_frame(buf, 0, nullptr); - this->_need_to_fire[static_cast(level)] = 0; + frame = QUICFrameFactory::create_ping_frame(buf, 0, nullptr); + --this->_need_to_fire; + this->_ack_eliciting_packet_out = true; } return frame; } + +uint64_t +QUICPinger::count() +{ + SCOPED_MUTEX_LOCK(lock, this->_mutex, this_ethread()); + return this->_need_to_fire; +} diff --git a/iocore/net/quic/QUICPinger.h b/iocore/net/quic/QUICPinger.h index efa59a375d9..483cfb2cd0e 100644 --- a/iocore/net/quic/QUICPinger.h +++ b/iocore/net/quic/QUICPinger.h @@ -28,20 +28,25 @@ #include "QUICFrameHandler.h" #include "QUICFrameGenerator.h" -class QUICPinger : public QUICFrameGenerator +#include "I_Lock.h" + +class QUICPinger : public QUICFrameOnceGenerator { public: - QUICPinger() {} + QUICPinger() : _mutex(new_ProxyMutex()) {} - void request(QUICEncryptionLevel level); - void cancel(QUICEncryptionLevel level); + void request(); + void cancel(); + uint64_t count(); +private: // QUICFrameGenerator - bool will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) override; - QUICFrame *generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, - ink_hrtime timestamp) override; + bool _will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting) override; + QUICFrame *_generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, + size_t current_packet_size) override; -private: - // Initial, 0/1-RTT, and Handshake - uint64_t _need_to_fire[4] = {0}; + bool _ack_eliciting_packet_out = false; + + Ptr _mutex; + uint64_t _need_to_fire = 0; }; diff --git a/iocore/net/quic/QUICStreamManager.cc b/iocore/net/quic/QUICStreamManager.cc index 91edd1b7c8b..de4ffb9cd18 100644 --- a/iocore/net/quic/QUICStreamManager.cc +++ b/iocore/net/quic/QUICStreamManager.cc @@ -29,8 +29,6 @@ static constexpr char tag[] = "quic_stream_manager"; static constexpr QUICStreamId QUIC_STREAM_TYPES = 4; -ClassAllocator quicStreamManagerAllocator("quicStreamManagerAllocator"); - QUICStreamManager::QUICStreamManager(QUICConnectionInfoProvider *info, QUICRTTProvider *rtt_provider, QUICApplicationMap *app_map) : _stream_factory(rtt_provider, info), _info(info), _app_map(app_map) { @@ -92,7 +90,7 @@ QUICStreamManager::create_stream(QUICStreamId stream_id) QUICConnectionErrorUPtr error = nullptr; QUICStreamVConnection *stream_vc = this->_find_or_create_stream_vc(stream_id); if (!stream_vc) { - return std::make_unique(QUICTransErrorCode::STREAM_ID_ERROR); + return std::make_unique(QUICTransErrorCode::STREAM_LIMIT_ERROR); } QUICApplication *application = this->_app_map->get(stream_id); @@ -176,7 +174,7 @@ QUICStreamManager::_handle_frame(const QUICMaxStreamDataFrame &frame) if (stream) { return stream->recv(frame); } else { - return std::make_unique(QUICTransErrorCode::STREAM_ID_ERROR); + return std::make_unique(QUICTransErrorCode::STREAM_LIMIT_ERROR); } } @@ -187,7 +185,7 @@ QUICStreamManager::_handle_frame(const QUICStreamDataBlockedFrame &frame) if (stream) { return stream->recv(frame); } else { - return std::make_unique(QUICTransErrorCode::STREAM_ID_ERROR); + return std::make_unique(QUICTransErrorCode::STREAM_LIMIT_ERROR); } } @@ -196,7 +194,7 @@ QUICStreamManager::_handle_frame(const QUICStreamFrame &frame) { QUICStreamVConnection *stream = this->_find_or_create_stream_vc(frame.stream_id()); if (!stream) { - return std::make_unique(QUICTransErrorCode::STREAM_ID_ERROR); + return std::make_unique(QUICTransErrorCode::STREAM_LIMIT_ERROR); } QUICApplication *application = this->_app_map->get(frame.stream_id()); @@ -215,7 +213,7 @@ QUICStreamManager::_handle_frame(const QUICRstStreamFrame &frame) if (stream) { return stream->recv(frame); } else { - return std::make_unique(QUICTransErrorCode::STREAM_ID_ERROR); + return std::make_unique(QUICTransErrorCode::STREAM_LIMIT_ERROR); } } @@ -226,7 +224,7 @@ QUICStreamManager::_handle_frame(const QUICStopSendingFrame &frame) if (stream) { return stream->recv(frame); } else { - return std::make_unique(QUICTransErrorCode::STREAM_ID_ERROR); + return std::make_unique(QUICTransErrorCode::STREAM_LIMIT_ERROR); } } @@ -407,7 +405,7 @@ QUICStreamManager::set_default_application(QUICApplication *app) } bool -QUICStreamManager::will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) +QUICStreamManager::will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) { if (!this->_is_level_matched(level)) { return false; @@ -419,7 +417,7 @@ QUICStreamManager::will_generate_frame(QUICEncryptionLevel level, ink_hrtime tim } for (QUICStreamVConnection *s = this->stream_list.head; s; s = s->link.next) { - if (s->will_generate_frame(level, timestamp)) { + if (s->will_generate_frame(level, current_packet_size, ack_eliciting, seq_num)) { return true; } } @@ -429,7 +427,7 @@ QUICStreamManager::will_generate_frame(QUICEncryptionLevel level, ink_hrtime tim QUICFrame * QUICStreamManager::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, - ink_hrtime timestamp) + size_t current_packet_size, uint32_t seq_num) { QUICFrame *frame = nullptr; @@ -444,7 +442,7 @@ QUICStreamManager::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint6 // FIXME We should pick a stream based on priority for (QUICStreamVConnection *s = this->stream_list.head; s; s = s->link.next) { - frame = s->generate_frame(buf, level, connection_credit, maximum_frame_size, timestamp); + frame = s->generate_frame(buf, level, connection_credit, maximum_frame_size, current_packet_size, seq_num); if (frame) { break; } diff --git a/iocore/net/quic/QUICStreamManager.h b/iocore/net/quic/QUICStreamManager.h index fbdc49d78fd..fb38ecc1309 100644 --- a/iocore/net/quic/QUICStreamManager.h +++ b/iocore/net/quic/QUICStreamManager.h @@ -37,7 +37,6 @@ class QUICTransportParameters; class QUICStreamManager : public QUICFrameHandler, public QUICFrameGenerator { public: - QUICStreamManager() : _stream_factory(nullptr, nullptr){}; QUICStreamManager(QUICConnectionInfoProvider *info, QUICRTTProvider *rtt_provider, QUICApplicationMap *app_map); void init_flow_control_params(const std::shared_ptr &local_tp, @@ -63,9 +62,9 @@ class QUICStreamManager : public QUICFrameHandler, public QUICFrameGenerator virtual QUICConnectionErrorUPtr handle_frame(QUICEncryptionLevel level, const QUICFrame &frame) override; // QUICFrameGenerator - bool will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) override; + bool will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t timestamp) override; QUICFrame *generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, - ink_hrtime timestamp) override; + size_t current_packet_size, uint32_t timestamp) override; protected: virtual bool _is_level_matched(QUICEncryptionLevel level) override; diff --git a/iocore/net/quic/QUICTokenCreator.cc b/iocore/net/quic/QUICTokenCreator.cc new file mode 100644 index 00000000000..9d1ef622b2f --- /dev/null +++ b/iocore/net/quic/QUICTokenCreator.cc @@ -0,0 +1,71 @@ +/** @file + * + * A brief file description + * + * @section license License + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "QUICTokenCreator.h" + +bool +QUICTokenCreator::will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) +{ + if (!this->_is_level_matched(level)) { + return false; + } + + return !this->_is_resumption_token_sent; +} + +QUICFrame * +QUICTokenCreator::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, + size_t current_packet_size, uint32_t seq_num) +{ + QUICFrame *frame = nullptr; + + if (!this->_is_level_matched(level)) { + return frame; + } + + if (this->_is_resumption_token_sent) { + return frame; + } + + if (this->_context->connection_info()->direction() == NET_VCONNECTION_IN) { + // TODO Make expiration period configurable + QUICResumptionToken token(this->_context->connection_info()->five_tuple().source(), + this->_context->connection_info()->connection_id(), Thread::get_hrtime() + HRTIME_HOURS(24)); + frame = QUICFrameFactory::create_new_token_frame(buf, token, this->_issue_frame_id(), this); + if (frame) { + if (frame->size() < maximum_frame_size) { + this->_is_resumption_token_sent = true; + } else { + // Cancel generating frame + frame = nullptr; + } + } + } + + return frame; +} + +void +QUICTokenCreator::_on_frame_lost(QUICFrameInformationUPtr &info) +{ + this->_is_resumption_token_sent = false; +} diff --git a/iocore/net/quic/QUICTokenCreator.h b/iocore/net/quic/QUICTokenCreator.h new file mode 100644 index 00000000000..e107fb9d0f8 --- /dev/null +++ b/iocore/net/quic/QUICTokenCreator.h @@ -0,0 +1,42 @@ +/** @file + * + * A brief file description + * + * @section license License + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include "QUICFrameGenerator.h" +#include "QUICContext.h" + +class QUICTokenCreator final : public QUICFrameGenerator +{ +public: + QUICTokenCreator(QUICContext *context) : _context(context) {} + + bool will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) override; + QUICFrame *generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, + size_t current_packet_size, uint32_t seq_num) override; + +private: + void _on_frame_lost(QUICFrameInformationUPtr &info) override; + + bool _is_resumption_token_sent = false; + QUICContext *_context = nullptr; +}; diff --git a/iocore/net/quic/QUICTransportParameters.cc b/iocore/net/quic/QUICTransportParameters.cc index 04f0009930b..248cfcb6b9c 100644 --- a/iocore/net/quic/QUICTransportParameters.cc +++ b/iocore/net/quic/QUICTransportParameters.cc @@ -183,7 +183,7 @@ QUICTransportParameters::_validate_parameters() const if ((ite = this->_parameters.find(QUICTransportParameterId::INITIAL_MAX_STREAM_DATA_UNI)) != this->_parameters.end()) { } - if ((ite = this->_parameters.find(QUICTransportParameterId::DISABLE_MIGRATION)) != this->_parameters.end()) { + if ((ite = this->_parameters.find(QUICTransportParameterId::DISABLE_ACTIVE_MIGRATION)) != this->_parameters.end()) { } if ((ite = this->_parameters.find(QUICTransportParameterId::MAX_ACK_DELAY)) != this->_parameters.end()) { @@ -290,11 +290,12 @@ QUICTransportParameters::_print() const uint64_t int_value; size_t int_value_len; QUICVariableInt::decode(int_value, int_value_len, p.second->data(), p.second->len()); - Debug(tag, "%s: 0x%" PRIx64 " (%" PRIu64 ")", QUICDebugNames::transport_parameter_id(p.first), int_value, int_value); + Debug(tag, "%s (%" PRIu32 "): 0x%" PRIx64 " (%" PRIu64 ")", QUICDebugNames::transport_parameter_id(p.first), + static_cast(p.first), int_value, int_value); } else if (p.second->len() <= 24) { char hex_str[65]; to_hex_str(hex_str, sizeof(hex_str), p.second->data(), p.second->len()); - Debug(tag, "%s: %s", QUICDebugNames::transport_parameter_id(p.first), hex_str); + Debug(tag, "%s (%" PRIu32 "): %s", QUICDebugNames::transport_parameter_id(p.first), static_cast(p.first), hex_str); } else if (QUICTransportParameterId::PREFERRED_ADDRESS == p.first) { QUICPreferredAddress pref_addr(p.second->data(), p.second->len()); char cid_hex_str[QUICConnectionId::MAX_HEX_STR_LENGTH]; diff --git a/iocore/net/quic/QUICTransportParameters.h b/iocore/net/quic/QUICTransportParameters.h index 6886bd09af0..df46d9d3acd 100644 --- a/iocore/net/quic/QUICTransportParameters.h +++ b/iocore/net/quic/QUICTransportParameters.h @@ -46,8 +46,9 @@ class QUICTransportParameterId INITIAL_MAX_STREAMS_UNI, ACK_DELAY_EXPONENT, MAX_ACK_DELAY, - DISABLE_MIGRATION, + DISABLE_ACTIVE_MIGRATION, PREFERRED_ADDRESS, + ACTIVE_CONNECTION_ID_LIMIT, }; explicit operator bool() const { return true; } diff --git a/iocore/net/quic/QUICTypes.cc b/iocore/net/quic/QUICTypes.cc index 29e09d2de00..5c354a9c68d 100644 --- a/iocore/net/quic/QUICTypes.cc +++ b/iocore/net/quic/QUICTypes.cc @@ -252,15 +252,15 @@ QUICTypeUtil::write_QUICOffset(QUICOffset offset, uint8_t *buf, size_t *len) } void -QUICTypeUtil::write_QUICTransErrorCode(uint16_t error_code, uint8_t *buf, size_t *len) +QUICTypeUtil::write_QUICTransErrorCode(uint64_t error_code, uint8_t *buf, size_t *len) { - QUICIntUtil::write_uint_as_nbytes(static_cast(error_code), 2, buf, len); + QUICIntUtil::write_QUICVariableInt(static_cast(error_code), buf, len); } void QUICTypeUtil::write_QUICAppErrorCode(QUICAppErrorCode error_code, uint8_t *buf, size_t *len) { - QUICIntUtil::write_uint_as_nbytes(static_cast(error_code), 2, buf, len); + QUICIntUtil::write_QUICVariableInt(static_cast(error_code), buf, len); } void @@ -552,6 +552,24 @@ QUICFiveTuple::protocol() const return this->_protocol; } +// +// QUICPath +// + +QUICPath::QUICPath(IpEndpoint local_ep, IpEndpoint remote_ep) : _local_ep(local_ep), _remote_ep(remote_ep) {} + +const IpEndpoint & +QUICPath::local_ep() const +{ + return this->_local_ep; +} + +const IpEndpoint & +QUICPath::remote_ep() const +{ + return this->_remote_ep; +} + // // QUICConnectionId // @@ -660,7 +678,7 @@ QUICInvariants::dcil(uint8_t &dst, const uint8_t *buf, uint64_t buf_len) return false; } - dst = buf[QUICInvariants::LH_CIL_OFFSET] >> 4; + dst = buf[QUICInvariants::LH_CIL_OFFSET]; return true; } @@ -670,11 +688,12 @@ QUICInvariants::scil(uint8_t &dst, const uint8_t *buf, uint64_t buf_len) { ink_assert(QUICInvariants::is_long_header(buf)); - if (buf_len < QUICInvariants::LH_CIL_OFFSET) { + uint8_t dcil = 0; + if (!QUICInvariants::dcil(dcil, buf, buf_len)) { return false; } - dst = buf[QUICInvariants::LH_CIL_OFFSET] & 0x0F; + dst = buf[QUICInvariants::LH_CIL_OFFSET + 1 + dcil]; return true; } @@ -691,13 +710,12 @@ QUICInvariants::dcid(QUICConnectionId &dst, const uint8_t *buf, uint64_t buf_len return false; } - if (dcil) { - dcid_len = dcil + QUICInvariants::CIL_BASE; - } else { + if (dcil == 0) { dst = QUICConnectionId::ZERO(); return true; } + dcid_len = dcil; dcid_offset = QUICInvariants::LH_DCID_OFFSET; } else { // remote dcil is local scil @@ -724,34 +742,30 @@ QUICInvariants::scid(QUICConnectionId &dst, const uint8_t *buf, uint64_t buf_len } uint8_t scid_offset = QUICInvariants::LH_DCID_OFFSET; - uint8_t scid_len = 0; uint8_t dcil = 0; if (!QUICInvariants::dcil(dcil, buf, buf_len)) { return false; } - if (dcil) { - scid_offset += (dcil + QUICInvariants::CIL_BASE); - } + scid_offset += dcil; uint8_t scil = 0; if (!QUICInvariants::scil(scil, buf, buf_len)) { return false; } + scid_offset += 1; - if (scil) { - scid_len = scil + QUICInvariants::CIL_BASE; - } else { + if (scil == 0) { dst = QUICConnectionId::ZERO(); return true; } - if (scid_offset + scid_len > buf_len) { + if (scid_offset + scil > buf_len) { return false; } - dst = QUICTypeUtil::read_QUICConnectionId(buf + scid_offset, scid_len); + dst = QUICTypeUtil::read_QUICConnectionId(buf + scid_offset, scil); return true; } diff --git a/iocore/net/quic/QUICTypes.h b/iocore/net/quic/QUICTypes.h index ee19ab05d90..7c3a53796c7 100644 --- a/iocore/net/quic/QUICTypes.h +++ b/iocore/net/quic/QUICTypes.h @@ -51,7 +51,7 @@ static constexpr uint8_t kPacketNumberSpace = 3; // Note: Fix QUIC_ALPN_PROTO_LIST in QUICConfig.cc // Note: Change ExtensionType (QUICTransportParametersHandler::TRANSPORT_PARAMETER_ID) if it's changed constexpr QUICVersion QUIC_SUPPORTED_VERSIONS[] = { - 0xff000014, + 0xff000017, }; constexpr QUICVersion QUIC_EXERCISE_VERSION = 0x1a2a3a4a; @@ -75,9 +75,10 @@ constexpr QUICEncryptionLevel QUIC_ENCRYPTION_LEVELS[] = { // introduce by draft-19 kPacketNumberSpace enum class QUICPacketNumberSpace { - Initial, - Handshake, - ApplicationData, + None = -1, + Initial = 0, + Handshake = 1, + ApplicationData = 2, }; // Devide to QUICPacketType and QUICPacketLongHeaderType ? @@ -147,24 +148,23 @@ enum class QUICErrorClass { APPLICATION, }; -enum class QUICTransErrorCode : uint16_t { +enum class QUICTransErrorCode : uint64_t { NO_ERROR = 0x00, INTERNAL_ERROR, SERVER_BUSY, FLOW_CONTROL_ERROR, - STREAM_ID_ERROR, + STREAM_LIMIT_ERROR, STREAM_STATE_ERROR, - FINAL_OFFSET_ERROR, + FINAL_SIZE_ERROR, FRAME_ENCODING_ERROR, TRANSPORT_PARAMETER_ERROR, - VERSION_NEGOTIATION_ERROR, - PROTOCOL_VIOLATION, - INVALID_MIGRATION = 0x0C, - CRYPTO_ERROR = 0x0100, // 0x100 - 0x1FF + PROTOCOL_VIOLATION = 0x0A, + CRYPTO_BUFFER_EXCEEDED = 0x0D, + CRYPTO_ERROR = 0x0100, // 0x100 - 0x1FF }; // Application Protocol Error Codes defined in application -using QUICAppErrorCode = uint16_t; +using QUICAppErrorCode = uint64_t; constexpr uint16_t QUIC_APP_ERROR_CODE_STOPPING = 0; class QUICError @@ -225,7 +225,7 @@ class QUICConnectionId static uint8_t SCID_LEN; static const int MIN_LENGTH_FOR_INITIAL = 8; - static const int MAX_LENGTH = 18; + static const int MAX_LENGTH = 20; static const size_t MAX_HEX_STR_LENGTH = MAX_LENGTH * 2 + 1; static QUICConnectionId ZERO(); QUICConnectionId(); @@ -398,8 +398,8 @@ class QUICRetryToken : public QUICAddressValidationToken class QUICPreferredAddress { public: - constexpr static int16_t MIN_LEN = 26; - constexpr static int16_t MAX_LEN = 295; + constexpr static int16_t MIN_LEN = 41; + constexpr static int16_t MAX_LEN = 61; QUICPreferredAddress(IpEndpoint endpoint_ipv4, IpEndpoint endpoint_ipv6, const QUICConnectionId &cid, QUICStatelessResetToken token) @@ -419,8 +419,8 @@ class QUICPreferredAddress void store(uint8_t *buf, uint16_t &len) const; private: - IpEndpoint _endpoint_ipv4; - IpEndpoint _endpoint_ipv6; + IpEndpoint _endpoint_ipv4 = {}; + IpEndpoint _endpoint_ipv6 = {}; QUICConnectionId _cid; QUICStatelessResetToken _token; bool _valid = false; @@ -457,6 +457,61 @@ class QUICFiveTuple uint64_t _hash_code = 0; }; +class QUICPath +{ +public: + QUICPath(IpEndpoint local_ep, IpEndpoint remote_ep); + const IpEndpoint &local_ep() const; + const IpEndpoint &remote_ep() const; + + inline bool + operator==(const QUICPath &x) const + { + if ((this->_local_ep.port() != 0 && x._local_ep.port() != 0) && this->_local_ep.port() != x._local_ep.port()) { + return false; + } + + if ((this->_remote_ep.port() != 0 && x._remote_ep.port() != 0) && this->_remote_ep.port() != x._remote_ep.port()) { + return false; + } + + if ((!IpAddr(this->_local_ep).isAnyAddr() && !IpAddr(x._local_ep).isAnyAddr()) && this->_local_ep != x._local_ep) { + return false; + } + + if ((!IpAddr(this->_remote_ep).isAnyAddr() || !IpAddr(x._remote_ep).isAnyAddr()) && this->_remote_ep != x._remote_ep) { + return false; + } + + return true; + } + +private: + IpEndpoint _local_ep; + IpEndpoint _remote_ep; +}; + +class QUICPathHasher +{ +public: + std::size_t + operator()(const QUICPath &k) const + { + return k.remote_ep().port(); + } +}; + +class QUICPathValidationData +{ +public: + QUICPathValidationData(const uint8_t *data) { memcpy(this->_data, data, sizeof(this->_data)); } + + inline operator const uint8_t *() const { return this->_data; } + +private: + uint8_t _data[8]; +}; + class QUICTPConfig { public: @@ -471,11 +526,13 @@ class QUICTPConfig virtual uint64_t initial_max_streams_uni() const = 0; virtual uint8_t ack_delay_exponent() const = 0; virtual uint8_t max_ack_delay() const = 0; + virtual uint8_t active_cid_limit() const = 0; }; class QUICLDConfig { public: + virtual ~QUICLDConfig() {} virtual uint32_t packet_threshold() const = 0; virtual float time_threshold() const = 0; virtual ink_hrtime granularity() const = 0; @@ -485,6 +542,7 @@ class QUICLDConfig class QUICCCConfig { public: + virtual ~QUICCCConfig() {} virtual uint32_t max_datagram_size() const = 0; virtual uint32_t initial_window() const = 0; virtual uint32_t minimum_window() const = 0; @@ -520,7 +578,7 @@ class QUICTypeUtil static void write_QUICVersion(QUICVersion version, uint8_t *buf, size_t *len); static void write_QUICStreamId(QUICStreamId stream_id, uint8_t *buf, size_t *len); static void write_QUICOffset(QUICOffset offset, uint8_t *buf, size_t *len); - static void write_QUICTransErrorCode(uint16_t error_code, uint8_t *buf, size_t *len); + static void write_QUICTransErrorCode(uint64_t error_code, uint8_t *buf, size_t *len); static void write_QUICAppErrorCode(QUICAppErrorCode error_code, uint8_t *buf, size_t *len); static void write_QUICMaxData(uint64_t max_data, uint8_t *buf, size_t *len); @@ -533,18 +591,11 @@ class QUICInvariants static bool is_long_header(const uint8_t *buf); static bool is_version_negotiation(QUICVersion v); static bool version(QUICVersion &dst, const uint8_t *buf, uint64_t buf_len); - /** - * This function returns the raw value. You'll need to add 3 to the returned value to get the actual connection id length. - */ static bool dcil(uint8_t &dst, const uint8_t *buf, uint64_t buf_len); - /** - * This function returns the raw value. You'll need to add 3 to the returned value to get the actual connection id length. - */ static bool scil(uint8_t &dst, const uint8_t *buf, uint64_t buf_len); static bool dcid(QUICConnectionId &dst, const uint8_t *buf, uint64_t buf_len); static bool scid(QUICConnectionId &dst, const uint8_t *buf, uint64_t buf_len); - static const size_t CIL_BASE = 3; static const size_t LH_VERSION_OFFSET = 1; static const size_t LH_CIL_OFFSET = 5; static const size_t LH_DCID_OFFSET = 6; diff --git a/iocore/net/quic/QUICUnidirectionalStream.cc b/iocore/net/quic/QUICUnidirectionalStream.cc index b6dae8f6f0a..90bd1ddaa07 100644 --- a/iocore/net/quic/QUICUnidirectionalStream.cc +++ b/iocore/net/quic/QUICUnidirectionalStream.cc @@ -125,14 +125,14 @@ QUICSendStream::state_stream_closed(int event, void *data) } bool -QUICSendStream::will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) +QUICSendStream::will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) { return !this->is_retransmited_frame_queue_empty() || this->_write_vio.get_reader()->is_read_avail_more_than(0); } QUICFrame * QUICSendStream::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, - ink_hrtime timestamp) + size_t current_packet_size, uint32_t seq_num) { SCOPED_MUTEX_LOCK(lock, this->_write_vio.mutex, this_ethread()); @@ -183,7 +183,8 @@ QUICSendStream::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t uint64_t stream_credit = this->_remote_flow_controller.credit(); if (stream_credit == 0) { // STREAM_DATA_BLOCKED - frame = this->_remote_flow_controller.generate_frame(buf, level, UINT16_MAX, maximum_frame_size, timestamp); + frame = + this->_remote_flow_controller.generate_frame(buf, level, UINT16_MAX, maximum_frame_size, current_packet_size, seq_num); return frame; } @@ -526,15 +527,15 @@ QUICReceiveStream::is_cancelled() const } bool -QUICReceiveStream::will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) +QUICReceiveStream::will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) { - return this->_local_flow_controller.will_generate_frame(level, timestamp) || + return this->_local_flow_controller.will_generate_frame(level, current_packet_size, ack_eliciting, seq_num) || (this->_stop_sending_reason != nullptr && this->_is_stop_sending_sent == false); } QUICFrame * QUICReceiveStream::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, - ink_hrtime timestamp) + size_t current_packet_size, uint32_t seq_num) { QUICFrame *frame = nullptr; // STOP_SENDING @@ -548,7 +549,7 @@ QUICReceiveStream::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint6 } // MAX_STREAM_DATA - frame = this->_local_flow_controller.generate_frame(buf, level, UINT16_MAX, maximum_frame_size, timestamp); + frame = this->_local_flow_controller.generate_frame(buf, level, UINT16_MAX, maximum_frame_size, current_packet_size, seq_num); return frame; } diff --git a/iocore/net/quic/QUICUnidirectionalStream.h b/iocore/net/quic/QUICUnidirectionalStream.h index 0c7162742a6..5ebe5527c0b 100644 --- a/iocore/net/quic/QUICUnidirectionalStream.h +++ b/iocore/net/quic/QUICUnidirectionalStream.h @@ -37,9 +37,9 @@ class QUICSendStream : public QUICStreamVConnection int state_stream_closed(int event, void *data); // QUICFrameGenerator - bool will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) override; + bool will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) override; QUICFrame *generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, - ink_hrtime timestamp) override; + size_t current_packet_size, uint32_t seq_num) override; virtual QUICConnectionErrorUPtr recv(const QUICMaxStreamDataFrame &frame) override; virtual QUICConnectionErrorUPtr recv(const QUICStopSendingFrame &frame) override; @@ -86,9 +86,9 @@ class QUICReceiveStream : public QUICStreamVConnection, public QUICTransferProgr int state_stream_closed(int event, void *data); // QUICFrameGenerator - bool will_generate_frame(QUICEncryptionLevel level, ink_hrtime timestamp) override; + bool will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) override; QUICFrame *generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size, - ink_hrtime timestamp) override; + size_t current_packet_size, uint32_t seq_num) override; virtual QUICConnectionErrorUPtr recv(const QUICStreamFrame &frame) override; virtual QUICConnectionErrorUPtr recv(const QUICStreamDataBlockedFrame &frame) override; diff --git a/iocore/net/quic/test/test_QUICAckFrameCreator.cc b/iocore/net/quic/test/test_QUICAckFrameCreator.cc index 99b40e73555..39b7bc9db4d 100644 --- a/iocore/net/quic/test/test_QUICAckFrameCreator.cc +++ b/iocore/net/quic/test/test_QUICAckFrameCreator.cc @@ -32,63 +32,67 @@ TEST_CASE("QUICAckFrameManager", "[quic]") uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE]; // Initial state - QUICFrame *ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0); + QUICFrame *ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0, 0); QUICAckFrame *frame = static_cast(ack_frame); CHECK(frame == nullptr); // One packet ack_manager.update(level, 1, 1, false); - ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0); + ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0, 0); frame = static_cast(ack_frame); CHECK(frame != nullptr); CHECK(frame->ack_block_count() == 0); CHECK(frame->largest_acknowledged() == 1); CHECK(frame->ack_block_section()->first_ack_block() == 0); + ack_frame->~QUICFrame(); // retry - CHECK(ack_manager.will_generate_frame(level, 0) == false); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == false); // Not sequential ack_manager.update(level, 2, 1, false); ack_manager.update(level, 5, 1, false); ack_manager.update(level, 3, 1, false); ack_manager.update(level, 4, 1, false); - ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0); + ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0, 0); frame = static_cast(ack_frame); CHECK(frame != nullptr); CHECK(frame->ack_block_count() == 0); CHECK(frame->largest_acknowledged() == 5); CHECK(frame->ack_block_section()->first_ack_block() == 4); + ack_frame->~QUICFrame(); // Loss ack_manager.update(level, 6, 1, false); ack_manager.update(level, 7, 1, false); ack_manager.update(level, 10, 1, false); - ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0); + ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0, 0); frame = static_cast(ack_frame); CHECK(frame != nullptr); CHECK(frame->ack_block_count() == 1); CHECK(frame->largest_acknowledged() == 10); CHECK(frame->ack_block_section()->first_ack_block() == 0); CHECK(frame->ack_block_section()->begin()->gap() == 1); + ack_frame->~QUICFrame(); // on frame acked ack_manager.on_frame_acked(frame->id()); - CHECK(ack_manager.will_generate_frame(level, 0) == false); - ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == false); + ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0, 0); CHECK(ack_frame == nullptr); ack_manager.update(level, 11, 1, false); ack_manager.update(level, 12, 1, false); ack_manager.update(level, 13, 1, false); - ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0); + ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0, 0); frame = static_cast(ack_frame); CHECK(frame != nullptr); CHECK(frame->ack_block_count() == 0); CHECK(frame->largest_acknowledged() == 13); CHECK(frame->ack_block_section()->first_ack_block() == 2); CHECK(frame->ack_block_section()->begin()->gap() == 0); + ack_frame->~QUICFrame(); ack_manager.on_frame_acked(frame->id()); @@ -96,17 +100,18 @@ TEST_CASE("QUICAckFrameManager", "[quic]") ack_manager.update(level, 14, 1, true); ack_manager.update(level, 15, 1, true); ack_manager.update(level, 16, 1, true); - CHECK(ack_manager.will_generate_frame(level, 0) == false); - ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == false); + ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0, 0); ack_manager.update(level, 17, 1, false); - ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0); + ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0, 0); frame = static_cast(ack_frame); CHECK(frame != nullptr); CHECK(frame->ack_block_count() == 0); CHECK(frame->largest_acknowledged() == 17); CHECK(frame->ack_block_section()->first_ack_block() == 3); CHECK(frame->ack_block_section()->begin()->gap() == 0); + ack_frame->~QUICFrame(); } TEST_CASE("QUICAckFrameManager should send", "[quic]") @@ -117,7 +122,7 @@ TEST_CASE("QUICAckFrameManager should send", "[quic]") QUICEncryptionLevel level = QUICEncryptionLevel::ONE_RTT; ack_manager.update(level, 2, 1, false); - CHECK(ack_manager.will_generate_frame(level, 0) == true); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == true); } SECTION("QUIC delay ack and unorder packet", "[quic]") @@ -126,13 +131,13 @@ TEST_CASE("QUICAckFrameManager should send", "[quic]") QUICEncryptionLevel level = QUICEncryptionLevel::ONE_RTT; ack_manager.update(level, 0, 1, false); - CHECK(ack_manager.will_generate_frame(level, 0) == false); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == false); ack_manager.update(level, 1, 1, false); - CHECK(ack_manager.will_generate_frame(level, 0) == false); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == false); ack_manager.update(level, 3, 1, false); - CHECK(ack_manager.will_generate_frame(level, 0) == true); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == true); } SECTION("QUIC delay too much time", "[quic]") @@ -142,12 +147,12 @@ TEST_CASE("QUICAckFrameManager should send", "[quic]") QUICEncryptionLevel level = QUICEncryptionLevel::ONE_RTT; ack_manager.update(level, 0, 1, false); - CHECK(ack_manager.will_generate_frame(level, 0) == false); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == false); sleep(1); Thread::get_hrtime_updated(); ack_manager.update(level, 1, 1, false); - CHECK(ack_manager.will_generate_frame(level, 0) == true); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == true); } SECTION("QUIC intial packet", "[quic]") @@ -156,7 +161,7 @@ TEST_CASE("QUICAckFrameManager should send", "[quic]") QUICEncryptionLevel level = QUICEncryptionLevel::INITIAL; ack_manager.update(level, 0, 1, false); - CHECK(ack_manager.will_generate_frame(level, 0) == true); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == true); } SECTION("QUIC handshake packet", "[quic]") @@ -165,7 +170,7 @@ TEST_CASE("QUICAckFrameManager should send", "[quic]") QUICEncryptionLevel level = QUICEncryptionLevel::HANDSHAKE; ack_manager.update(level, 0, 1, false); - CHECK(ack_manager.will_generate_frame(level, 0) == true); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == true); } SECTION("QUIC frame fired", "[quic]") @@ -174,11 +179,11 @@ TEST_CASE("QUICAckFrameManager should send", "[quic]") QUICEncryptionLevel level = QUICEncryptionLevel::ONE_RTT; ack_manager.update(level, 0, 1, false); - CHECK(ack_manager.will_generate_frame(level, 0) == false); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == false); sleep(1); Thread::get_hrtime_updated(); - CHECK(ack_manager.will_generate_frame(level, 0) == true); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == true); } SECTION("QUIC refresh frame", "[quic]") @@ -187,27 +192,28 @@ TEST_CASE("QUICAckFrameManager should send", "[quic]") QUICEncryptionLevel level = QUICEncryptionLevel::ONE_RTT; uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE]; - QUICFrame *ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0); + QUICFrame *ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0, 0); QUICAckFrame *frame = static_cast(ack_frame); CHECK(frame == nullptr); // unorder frame should sent immediately ack_manager.update(level, 1, 1, false); - CHECK(ack_manager.will_generate_frame(level, 0) == true); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == true); ack_manager.update(level, 2, 1, false); // Delay due to some reason, the frame is not valued any more, but still valued sleep(1); Thread::get_hrtime_updated(); - CHECK(ack_manager.will_generate_frame(level, 0) == true); - ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == true); + ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0, 0); frame = static_cast(ack_frame); CHECK(frame->ack_block_count() == 0); CHECK(frame->largest_acknowledged() == 2); CHECK(frame->ack_block_section()->first_ack_block() == 1); CHECK(frame->ack_block_section()->begin()->gap() == 0); + ack_frame->~QUICFrame(); } } @@ -218,7 +224,7 @@ TEST_CASE("QUICAckFrameManager_loss_recover", "[quic]") // Initial state uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE]; - QUICFrame *ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0); + QUICFrame *ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0, 0); QUICAckFrame *frame = static_cast(ack_frame); CHECK(frame == nullptr); @@ -228,25 +234,27 @@ TEST_CASE("QUICAckFrameManager_loss_recover", "[quic]") ack_manager.update(level, 8, 1, false); ack_manager.update(level, 9, 1, false); - ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0); + ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0, 0); frame = static_cast(ack_frame); CHECK(frame != nullptr); CHECK(frame->ack_block_count() == 2); CHECK(frame->largest_acknowledged() == 9); CHECK(frame->ack_block_section()->first_ack_block() == 1); CHECK(frame->ack_block_section()->begin()->gap() == 0); + ack_frame->~QUICFrame(); - CHECK(ack_manager.will_generate_frame(level, 0) == false); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == false); ack_manager.update(level, 7, 1, false); ack_manager.update(level, 4, 1, false); - ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0); + ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0, 0); frame = static_cast(ack_frame); CHECK(frame != nullptr); CHECK(frame->ack_block_count() == 1); CHECK(frame->largest_acknowledged() == 9); CHECK(frame->ack_block_section()->first_ack_block() == 5); CHECK(frame->ack_block_section()->begin()->gap() == 0); + ack_frame->~QUICFrame(); } TEST_CASE("QUICAckFrameManager_QUICAckFrameCreator", "[quic]") @@ -296,7 +304,7 @@ TEST_CASE("QUICAckFrameManager lost_frame", "[quic]") uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE]; // Initial state - QUICFrame *ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0); + QUICFrame *ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0, 0); QUICAckFrame *frame = static_cast(ack_frame); CHECK(frame == nullptr); @@ -306,39 +314,42 @@ TEST_CASE("QUICAckFrameManager lost_frame", "[quic]") ack_manager.update(level, 8, 1, false); ack_manager.update(level, 9, 1, false); - ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0); + ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0, 0); frame = static_cast(ack_frame); CHECK(frame != nullptr); CHECK(frame->ack_block_count() == 2); CHECK(frame->largest_acknowledged() == 9); CHECK(frame->ack_block_section()->first_ack_block() == 1); CHECK(frame->ack_block_section()->begin()->gap() == 0); + ack_frame->~QUICFrame(); ack_manager.on_frame_lost(frame->id()); - CHECK(ack_manager.will_generate_frame(level, 0) == true); - ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == true); + ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0, 0); frame = static_cast(ack_frame); CHECK(frame != nullptr); CHECK(frame->ack_block_count() == 2); CHECK(frame->largest_acknowledged() == 9); CHECK(frame->ack_block_section()->first_ack_block() == 1); CHECK(frame->ack_block_section()->begin()->gap() == 0); + ack_frame->~QUICFrame(); - CHECK(ack_manager.will_generate_frame(level, 0) == false); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == false); ack_manager.on_frame_lost(frame->id()); - CHECK(ack_manager.will_generate_frame(level, 0) == true); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == true); ack_manager.update(level, 7, 1, false); ack_manager.update(level, 4, 1, false); - ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0); + ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0, 0); frame = static_cast(ack_frame); CHECK(frame != nullptr); CHECK(frame->ack_block_count() == 1); CHECK(frame->largest_acknowledged() == 9); CHECK(frame->ack_block_section()->first_ack_block() == 5); CHECK(frame->ack_block_section()->begin()->gap() == 0); + ack_frame->~QUICFrame(); - CHECK(ack_manager.will_generate_frame(level, 0) == false); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == false); } TEST_CASE("QUICAckFrameManager ack only packet", "[quic]") @@ -350,7 +361,7 @@ TEST_CASE("QUICAckFrameManager ack only packet", "[quic]") uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE]; // Initial state - QUICFrame *ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0); + QUICFrame *ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0, 0); QUICAckFrame *frame = static_cast(ack_frame); CHECK(frame == nullptr); @@ -360,19 +371,20 @@ TEST_CASE("QUICAckFrameManager ack only packet", "[quic]") ack_manager.update(level, 4, 1, false); ack_manager.update(level, 5, 1, false); - CHECK(ack_manager.will_generate_frame(level, 0) == true); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == true); - ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0); + ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0, 0); frame = static_cast(ack_frame); CHECK(frame != nullptr); CHECK(frame->ack_block_count() == 0); CHECK(frame->largest_acknowledged() == 5); CHECK(frame->ack_block_section()->first_ack_block() == 4); CHECK(frame->ack_block_section()->begin()->gap() == 0); + ack_frame->~QUICFrame(); ack_manager.update(level, 6, 1, true); ack_manager.update(level, 7, 1, true); - CHECK(ack_manager.will_generate_frame(level, 0) == false); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == false); } SECTION("ONE_RTT") @@ -382,7 +394,7 @@ TEST_CASE("QUICAckFrameManager ack only packet", "[quic]") uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE]; // Initial state - QUICFrame *ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0); + QUICFrame *ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0, 0); QUICAckFrame *frame = static_cast(ack_frame); CHECK(frame == nullptr); @@ -392,18 +404,19 @@ TEST_CASE("QUICAckFrameManager ack only packet", "[quic]") ack_manager.update(level, 4, 1, false); ack_manager.update(level, 5, 1, false); - CHECK(ack_manager.will_generate_frame(level, 0) == true); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == true); - ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0); + ack_frame = ack_manager.generate_frame(frame_buf, level, UINT16_MAX, UINT16_MAX, 0, 0); frame = static_cast(ack_frame); CHECK(frame != nullptr); CHECK(frame->ack_block_count() == 0); CHECK(frame->largest_acknowledged() == 5); CHECK(frame->ack_block_section()->first_ack_block() == 4); CHECK(frame->ack_block_section()->begin()->gap() == 0); + ack_frame->~QUICFrame(); ack_manager.update(level, 6, 1, true); ack_manager.update(level, 7, 1, true); - CHECK(ack_manager.will_generate_frame(level, 0) == false); + CHECK(ack_manager.will_generate_frame(level, 0, true, 0) == false); } } diff --git a/iocore/net/quic/test/test_QUICAltConnectionManager.cc b/iocore/net/quic/test/test_QUICAltConnectionManager.cc index d30da7b390a..298f21b775e 100644 --- a/iocore/net/quic/test/test_QUICAltConnectionManager.cc +++ b/iocore/net/quic/test/test_QUICAltConnectionManager.cc @@ -58,6 +58,7 @@ TEST_CASE("QUICPreferredAddress", "[quic]") CHECK(memcmp(pref_addr->endpoint_ipv6().sin6.sin6_addr.s6_addr, ipv6_addr.s6_addr, 16) == 0); CHECK(pref_addr->cid() == cid55); CHECK(memcmp(pref_addr->token().buf(), buf + 26, 16) == 0); + delete pref_addr; } SECTION("store") @@ -85,6 +86,7 @@ TEST_CASE("QUICPreferredAddress", "[quic]") pref_addr->store(actual, len); CHECK(sizeof(buf) == len); CHECK(memcmp(buf, actual, sizeof(buf)) == 0); + delete pref_addr; } SECTION("unavailable") @@ -93,5 +95,6 @@ TEST_CASE("QUICPreferredAddress", "[quic]") CHECK(!pref_addr->is_available()); CHECK(!pref_addr->has_ipv4()); CHECK(!pref_addr->has_ipv6()); + delete pref_addr; } } diff --git a/iocore/net/quic/test/test_QUICFlowController.cc b/iocore/net/quic/test/test_QUICFlowController.cc index d58a31172a7..61bb652ab1c 100644 --- a/iocore/net/quic/test/test_QUICFlowController.cc +++ b/iocore/net/quic/test/test_QUICFlowController.cc @@ -116,7 +116,7 @@ TEST_CASE("QUICFlowController_Local_Connection", "[quic]") fc.forward_limit(2048); CHECK(fc.current_offset() == 1024); CHECK(fc.current_limit() == 2048); - QUICFrame *frame = fc.generate_frame(frame_buf, QUICEncryptionLevel::ONE_RTT, 0, 1024, 0); + QUICFrame *frame = fc.generate_frame(frame_buf, QUICEncryptionLevel::ONE_RTT, 0, 1024, 0, 0); CHECK(frame); CHECK(frame->type() == QUICFrameType::MAX_DATA); @@ -168,7 +168,7 @@ TEST_CASE("QUICFlowController_Remote_Connection", "[quic]") CHECK(fc.current_offset() == 1000); CHECK(fc.current_limit() == 1024); CHECK(ret != 0); - QUICFrame *frame = fc.generate_frame(frame_buf, QUICEncryptionLevel::ONE_RTT, 0, 1024, 0); + QUICFrame *frame = fc.generate_frame(frame_buf, QUICEncryptionLevel::ONE_RTT, 0, 1024, 0, 0); CHECK(frame); CHECK(frame->type() == QUICFrameType::DATA_BLOCKED); @@ -199,9 +199,9 @@ TEST_CASE("QUICFlowController_Remote_Connection_ZERO_Credit", "[quic]") CHECK(fc.current_limit() == 1024); CHECK(ret == 0); - CHECK(fc.will_generate_frame(QUICEncryptionLevel::ONE_RTT, 0)); + CHECK(fc.will_generate_frame(QUICEncryptionLevel::ONE_RTT, 0, true, 0)); // if there're anything to send - QUICFrame *frame = fc.generate_frame(frame_buf, QUICEncryptionLevel::ONE_RTT, 0, 1024, 0); + QUICFrame *frame = fc.generate_frame(frame_buf, QUICEncryptionLevel::ONE_RTT, 0, 1024, 0, 0); CHECK(frame); CHECK(frame->type() == QUICFrameType::DATA_BLOCKED); @@ -265,7 +265,7 @@ TEST_CASE("QUICFlowController_Local_Stream", "[quic]") fc.forward_limit(2048); CHECK(fc.current_offset() == 1024); CHECK(fc.current_limit() == 2048); - QUICFrame *frame = fc.generate_frame(frame_buf, QUICEncryptionLevel::ONE_RTT, 0, 1024, 0); + QUICFrame *frame = fc.generate_frame(frame_buf, QUICEncryptionLevel::ONE_RTT, 0, 1024, 0, 0); CHECK(frame); CHECK(frame->type() == QUICFrameType::MAX_STREAM_DATA); @@ -306,7 +306,7 @@ TEST_CASE("QUICFlowController_Remote_Stream", "[quic]") CHECK(ret == 0); CHECK(fc.credit() == 0); - CHECK(fc.will_generate_frame(QUICEncryptionLevel::ONE_RTT, 0)); + CHECK(fc.will_generate_frame(QUICEncryptionLevel::ONE_RTT, 0, true, 0)); // Delay ret = fc.update(512); @@ -342,23 +342,23 @@ TEST_CASE("Frame retransmission", "[quic]") QUICRemoteConnectionFlowController fc(1024); // Check initial state - auto frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + auto frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); CHECK(!frame); ret = fc.update(1024); CHECK(ret == 0); - frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); REQUIRE(frame); CHECK(static_cast(frame)->offset() == 1024); QUICFrameId id = frame->id(); // Don't retransmit unless the frame is lost - frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); REQUIRE(!frame); // Retransmit fc.on_frame_lost(id); - frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); REQUIRE(frame); CHECK(static_cast(frame)->offset() == 1024); @@ -366,12 +366,12 @@ TEST_CASE("Frame retransmission", "[quic]") fc.on_frame_lost(frame->id()); fc.forward_limit(2048); ret = fc.update(1536); - frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); CHECK(!frame); // This should not be retransmition ret = fc.update(2048); - frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); REQUIRE(frame); CHECK(static_cast(frame)->offset() == 2048); } @@ -383,23 +383,23 @@ TEST_CASE("Frame retransmission", "[quic]") QUICRemoteStreamFlowController fc(1024, 0); // Check initial state - auto frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + auto frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); CHECK(!frame); ret = fc.update(1024); CHECK(ret == 0); - frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); REQUIRE(frame); CHECK(static_cast(frame)->offset() == 1024); QUICFrameId id = frame->id(); // Don't retransmit unless the frame is lost - frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); REQUIRE(!frame); // Retransmit fc.on_frame_lost(id); - frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); REQUIRE(frame); CHECK(static_cast(frame)->offset() == 1024); @@ -407,12 +407,12 @@ TEST_CASE("Frame retransmission", "[quic]") fc.on_frame_lost(frame->id()); fc.forward_limit(2048); ret = fc.update(1536); - frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); CHECK(!frame); // This should not be retransmition ret = fc.update(2048); - frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); REQUIRE(frame); CHECK(static_cast(frame)->offset() == 2048); } @@ -424,23 +424,23 @@ TEST_CASE("Frame retransmission", "[quic]") QUICLocalConnectionFlowController fc(&rp, 1024); // Check initial state - auto frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + auto frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); CHECK(!frame); fc.update(1024); fc.forward_limit(1024); - frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); REQUIRE(frame); CHECK(static_cast(frame)->maximum_data() == 1024); QUICFrameId id = frame->id(); // Don't retransmit unless the frame is lost - frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); REQUIRE(!frame); // Retransmit fc.on_frame_lost(id); - frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); REQUIRE(frame); CHECK(static_cast(frame)->maximum_data() == 1024); @@ -448,7 +448,7 @@ TEST_CASE("Frame retransmission", "[quic]") fc.on_frame_lost(id); fc.forward_limit(2048); fc.update(2048); - frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); REQUIRE(frame); CHECK(static_cast(frame)->maximum_data() == 2048); } @@ -460,23 +460,23 @@ TEST_CASE("Frame retransmission", "[quic]") QUICLocalStreamFlowController fc(&rp, 1024, 0); // Check initial state - auto frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + auto frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); CHECK(!frame); fc.update(1024); fc.forward_limit(1024); - frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); REQUIRE(frame); CHECK(static_cast(frame)->maximum_stream_data() == 1024); QUICFrameId id = frame->id(); // Don't retransmit unless the frame is lost - frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); REQUIRE(!frame); // Retransmit fc.on_frame_lost(id); - frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); REQUIRE(frame); CHECK(static_cast(frame)->maximum_stream_data() == 1024); @@ -484,7 +484,7 @@ TEST_CASE("Frame retransmission", "[quic]") fc.on_frame_lost(id); fc.forward_limit(2048); fc.update(2048); - frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0); + frame = fc.generate_frame(frame_buf, level, 1024, 1024, 0, 0); REQUIRE(frame); CHECK(static_cast(frame)->maximum_stream_data() == 2048); } diff --git a/iocore/net/quic/test/test_QUICFrame.cc b/iocore/net/quic/test/test_QUICFrame.cc index a8f81fd5538..58f68e49b9f 100644 --- a/iocore/net/quic/test/test_QUICFrame.cc +++ b/iocore/net/quic/test/test_QUICFrame.cc @@ -84,7 +84,7 @@ TEST_CASE("Load STREAM Frame", "[quic]") 0x01, // Stream ID 0x01, 0x02, 0x03, 0x04, // Stream Data }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::STREAM); CHECK(frame1->size() == 6); const QUICStreamFrame *stream_frame = static_cast(frame1); @@ -103,7 +103,7 @@ TEST_CASE("Load STREAM Frame", "[quic]") 0x05, // Data Length 0x01, 0x02, 0x03, 0x04, 0x05, // Stream Data }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::STREAM); CHECK(frame1->size() == 8); const QUICStreamFrame *stream_frame = static_cast(frame1); @@ -123,7 +123,7 @@ TEST_CASE("Load STREAM Frame", "[quic]") 0x05, // Data Length 0x01, 0x02, 0x03, 0x04, 0x05, // Stream Data }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::STREAM); CHECK(frame1->size() == 9); @@ -144,7 +144,7 @@ TEST_CASE("Load STREAM Frame", "[quic]") 0x05, // Data Length 0x01, 0x02, 0x03, 0x04, 0x05, // Stream Data }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::STREAM); CHECK(frame1->size() == 9); @@ -165,7 +165,7 @@ TEST_CASE("Load STREAM Frame", "[quic]") 0x05, // Data Length 0x01, 0x02, 0x03, 0x04, // BAD Stream Data }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::STREAM); CHECK(frame1->valid() == false); } @@ -176,7 +176,7 @@ TEST_CASE("Load STREAM Frame", "[quic]") 0x0e, // 0b00001OLF (OLF=110) 0x01, // Stream ID }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::STREAM); CHECK(frame1->valid() == false); } @@ -428,7 +428,7 @@ TEST_CASE("CRYPTO Frame", "[quic]") 0x05, // Length 0x01, 0x02, 0x03, 0x04, 0x05, // Crypto Data }; - const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf)); + const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf), nullptr); CHECK(frame->type() == QUICFrameType::CRYPTO); CHECK(frame->size() == sizeof(buf)); @@ -444,15 +444,15 @@ TEST_CASE("CRYPTO Frame", "[quic]") 0x06, // Type 0x80, 0x01, 0x00, 0x00, // Offset }; - const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf)); + const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf), nullptr); CHECK(frame->type() == QUICFrameType::CRYPTO); CHECK(frame->valid() == false); } SECTION("Storing") { - uint8_t buf[32] = {0}; - size_t len; + uint8_t buf[32] = {0}; + size_t len = 0; uint8_t expected[] = { 0x06, // Typr 0x80, 0x01, 0x00, 0x00, // Offset @@ -468,7 +468,11 @@ TEST_CASE("CRYPTO Frame", "[quic]") QUICCryptoFrame crypto_frame(block, 0x010000); CHECK(crypto_frame.size() == sizeof(expected)); - crypto_frame.store(buf, &len, 32); + Ptr ibb = crypto_frame.to_io_buffer_block(sizeof(buf)); + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } CHECK(len == sizeof(expected)); CHECK(memcmp(buf, expected, sizeof(expected)) == 0); } @@ -486,7 +490,7 @@ TEST_CASE("Load Ack Frame 1", "[quic]") 0x00, // Ack Block Count 0x00, // Ack Block Section }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::ACK); CHECK(frame1->size() == 6); const QUICAckFrame *ack_frame1 = static_cast(frame1); @@ -494,6 +498,7 @@ TEST_CASE("Load Ack Frame 1", "[quic]") CHECK(ack_frame1->ack_block_count() == 0); CHECK(ack_frame1->largest_acknowledged() == 0x12); CHECK(ack_frame1->ack_delay() == 0x3456); + frame1->~QUICFrame(); } SECTION("0 Ack Block, 8 bit packet number length, 8 bit block length") @@ -505,7 +510,7 @@ TEST_CASE("Load Ack Frame 1", "[quic]") 0x00, // Ack Block Count 0x80, 0x00, 0x00, 0x01, // Ack Block Section (First ACK Block Length) }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::ACK); CHECK(frame1->size() == 12); @@ -518,6 +523,7 @@ TEST_CASE("Load Ack Frame 1", "[quic]") const QUICAckFrame::AckBlockSection *section = ack_frame1->ack_block_section(); CHECK(section->first_ack_block() == 0x01); + frame1->~QUICFrame(); } SECTION("2 Ack Block, 8 bit packet number length, 8 bit block length") @@ -534,7 +540,7 @@ TEST_CASE("Load Ack Frame 1", "[quic]") 0xc9, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, // Ack Block Section (ACK Block 2 Length) }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::ACK); CHECK(frame1->size() == 21); const QUICAckFrame *ack_frame1 = static_cast(frame1); @@ -556,6 +562,7 @@ TEST_CASE("Load Ack Frame 1", "[quic]") CHECK(ite->length() == 0x090a0b0c0d0e0f10); ++ite; CHECK(ite == section->end()); + frame1->~QUICFrame(); } SECTION("load bad frame") @@ -565,9 +572,10 @@ TEST_CASE("Load Ack Frame 1", "[quic]") 0x12, // Largest Acknowledged }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::ACK); CHECK(frame1->valid() == false); + frame1->~QUICFrame(); } SECTION("load bad block") @@ -583,9 +591,10 @@ TEST_CASE("Load Ack Frame 1", "[quic]") 0x85, 0x06, 0x07, 0x08, // Ack Block Section (Gap 2) }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::ACK); CHECK(frame1->valid() == false); + frame1->~QUICFrame(); } SECTION("0 Ack Block, 8 bit packet number length, 8 bit block length with ECN section") @@ -601,7 +610,7 @@ TEST_CASE("Load Ack Frame 1", "[quic]") 0x02, // ECT1 0x03, // ECN-CE }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::ACK); CHECK(frame1->size() == 9); const QUICAckFrame *ack_frame1 = static_cast(frame1); @@ -613,6 +622,7 @@ TEST_CASE("Load Ack Frame 1", "[quic]") CHECK(ack_frame1->ecn_section()->ect0_count() == 1); CHECK(ack_frame1->ecn_section()->ect1_count() == 2); CHECK(ack_frame1->ecn_section()->ecn_ce_count() == 3); + frame1->~QUICFrame(); } SECTION("0 Ack Block, 8 bit packet number length, 8 bit block length with ECN section") @@ -627,9 +637,10 @@ TEST_CASE("Load Ack Frame 1", "[quic]") 0x01, // ECT0 0x02, // ECT1 }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::ACK); CHECK(frame1->valid() == false); + frame1->~QUICFrame(); } } @@ -638,7 +649,7 @@ TEST_CASE("Store Ack Frame", "[quic]") SECTION("0 Ack Block, 8 bit packet number length, 8 bit block length") { uint8_t buf[32] = {0}; - size_t len; + size_t len = 0; uint8_t expected[] = { 0x02, // Type @@ -651,7 +662,11 @@ TEST_CASE("Store Ack Frame", "[quic]") QUICAckFrame ack_frame(0x12, 0x3456, 0); CHECK(ack_frame.size() == 6); - ack_frame.store(buf, &len, 32); + Ptr ibb = ack_frame.to_io_buffer_block(sizeof(buf)); + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } CHECK(len == 6); CHECK(memcmp(buf, expected, len) == 0); } @@ -659,7 +674,7 @@ TEST_CASE("Store Ack Frame", "[quic]") SECTION("2 Ack Block, 8 bit packet number length, 8 bit block length") { uint8_t buf[32] = {0}; - size_t len; + size_t len = 0; uint8_t expected[] = { 0x02, // Type @@ -678,7 +693,11 @@ TEST_CASE("Store Ack Frame", "[quic]") section->add_ack_block({0x05060708, 0x090a0b0c0d0e0f10}); CHECK(ack_frame.size() == 21); - ack_frame.store(buf, &len, 32); + Ptr ibb = ack_frame.to_io_buffer_block(sizeof(buf)); + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } CHECK(len == 21); CHECK(memcmp(buf, expected, len) == 0); } @@ -692,12 +711,12 @@ TEST_CASE("Load RESET_STREAM Frame", "[quic]") uint8_t buf1[] = { 0x04, // Type 0x92, 0x34, 0x56, 0x78, // Stream ID - 0x00, 0x01, // Error Code + 0x01, // Error Code 0xd1, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 // Final Offset }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::RESET_STREAM); - CHECK(frame1->size() == 15); + CHECK(frame1->size() == 14); const QUICRstStreamFrame *rst_stream_frame1 = static_cast(frame1); CHECK(rst_stream_frame1 != nullptr); CHECK(rst_stream_frame1->error_code() == 0x0001); @@ -710,9 +729,9 @@ TEST_CASE("Load RESET_STREAM Frame", "[quic]") uint8_t buf1[] = { 0x04, // Type 0x92, 0x34, 0x56, 0x78, // Stream ID - 0x00, 0x01, // Error Code + 0x01, // Error Code }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::RESET_STREAM); CHECK(frame1->valid() == false); } @@ -721,19 +740,23 @@ TEST_CASE("Load RESET_STREAM Frame", "[quic]") TEST_CASE("Store RESET_STREAM Frame", "[quic]") { uint8_t buf[65535]; - size_t len; + size_t len = 0; uint8_t expected[] = { 0x04, // Type 0x92, 0x34, 0x56, 0x78, // Stream ID - 0x00, 0x01, // Error Code + 0x01, // Error Code 0xd1, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 // Final Offset }; QUICRstStreamFrame rst_stream_frame(0x12345678, 0x0001, 0x1122334455667788); - CHECK(rst_stream_frame.size() == 15); + CHECK(rst_stream_frame.size() == 14); - rst_stream_frame.store(buf, &len, 65535); - CHECK(len == 15); + Ptr ibb = rst_stream_frame.to_io_buffer_block(sizeof(buf)); + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } + CHECK(len == 14); CHECK(memcmp(buf, expected, len) == 0); } @@ -743,7 +766,7 @@ TEST_CASE("Load Ping Frame", "[quic]") uint8_t buf[] = { 0x01, // Type }; - const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf)); + const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf), nullptr); CHECK(frame->type() == QUICFrameType::PING); CHECK(frame->size() == 1); @@ -754,7 +777,7 @@ TEST_CASE("Load Ping Frame", "[quic]") TEST_CASE("Store Ping Frame", "[quic]") { uint8_t buf[16]; - size_t len; + size_t len = 0; uint8_t expected[] = { 0x01, // Type @@ -763,7 +786,11 @@ TEST_CASE("Store Ping Frame", "[quic]") QUICPingFrame frame; CHECK(frame.size() == 1); - frame.store(buf, &len, 16); + Ptr ibb = frame.to_io_buffer_block(sizeof(buf)); + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } CHECK(len == 1); CHECK(memcmp(buf, expected, len) == 0); } @@ -772,11 +799,11 @@ TEST_CASE("Load Padding Frame", "[quic]") { uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE]; uint8_t buf1[] = { - 0x00, // Type + 0x00, 0x00, 0x00 // Type }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::PADDING); - CHECK(frame1->size() == 1); + CHECK(frame1->size() == 3); const QUICPaddingFrame *paddingFrame1 = static_cast(frame1); CHECK(paddingFrame1 != nullptr); } @@ -784,14 +811,18 @@ TEST_CASE("Load Padding Frame", "[quic]") TEST_CASE("Store Padding Frame", "[quic]") { uint8_t buf[65535]; - size_t len; + size_t len = 0; uint8_t expected[] = { - 0x00, // Type + 0x00, 0x00, 0x00, // Type }; - QUICPaddingFrame padding_frame; - padding_frame.store(buf, &len, 65535); - CHECK(len == 1); + QUICPaddingFrame padding_frame(3); + Ptr ibb = padding_frame.to_io_buffer_block(sizeof(buf)); + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } + CHECK(len == 3); CHECK(memcmp(buf, expected, len) == 0); } @@ -805,13 +836,13 @@ TEST_CASE("ConnectionClose Frame", "[quic]") { uint8_t buf[] = { 0x1c, // Type - 0x00, 0x0A, // Error Code + 0x0A, // Error Code 0x00, // Frame Type 0x05, // Reason Phrase Length 0x41, 0x42, 0x43, 0x44, 0x45 // Reason Phrase ("ABCDE"); }; - const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf)); + const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf), nullptr); CHECK(frame->type() == QUICFrameType::CONNECTION_CLOSE); CHECK(frame->size() == sizeof(buf)); @@ -826,13 +857,13 @@ TEST_CASE("ConnectionClose Frame", "[quic]") SECTION("Bad loading") { uint8_t buf[] = { - 0x1c, // Type - 0x00, 0x0A, // Error Code - 0x00, // Frame Type - 0x05, // Reason Phrase Length + 0x1c, // Type + 0x0A, // Error Code + 0x00, // Frame Type + 0x05, // Reason Phrase Length }; - const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf)); + const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf), nullptr); CHECK(frame->type() == QUICFrameType::CONNECTION_CLOSE); CHECK(frame->valid() == false); } @@ -840,12 +871,12 @@ TEST_CASE("ConnectionClose Frame", "[quic]") SECTION("loading w/o reason phrase") { uint8_t buf[] = { - 0x1c, // Type - 0x00, 0x0A, // Error Code - 0x04, // Frame Type - 0x00, // Reason Phrase Length + 0x1c, // Type + 0x0A, // Error Code + 0x04, // Frame Type + 0x00, // Reason Phrase Length }; - const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf)); + const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf), nullptr); CHECK(frame->type() == QUICFrameType::CONNECTION_CLOSE); CHECK(frame->size() == sizeof(buf)); @@ -859,11 +890,11 @@ TEST_CASE("ConnectionClose Frame", "[quic]") SECTION("storing w/ reason phrase") { uint8_t buf[32]; - size_t len; + size_t len = 0; uint8_t expected[] = { 0x1c, // Type - 0x00, 0x0A, // Error Code + 0x0A, // Error Code 0x08, // Frame Type 0x05, // Reason Phrase Length 0x41, 0x42, 0x43, 0x44, 0x45 // Reason Phrase ("ABCDE"); @@ -872,7 +903,11 @@ TEST_CASE("ConnectionClose Frame", "[quic]") QUICFrameType::STREAM, 5, "ABCDE"); CHECK(connection_close_frame.size() == sizeof(expected)); - connection_close_frame.store(buf, &len, 32); + Ptr ibb = connection_close_frame.to_io_buffer_block(sizeof(buf)); + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } CHECK(len == sizeof(expected)); CHECK(memcmp(buf, expected, len) == 0); } @@ -880,17 +915,21 @@ TEST_CASE("ConnectionClose Frame", "[quic]") SECTION("storing w/o reason phrase") { uint8_t buf[32]; - size_t len; + size_t len = 0; uint8_t expected[] = { - 0x1c, // Type - 0x00, 0x0A, // Error Code - 0x00, // Frame Type - 0x00, // Reason Phrase Length + 0x1c, // Type + 0x0A, // Error Code + 0x00, // Frame Type + 0x00, // Reason Phrase Length }; QUICConnectionCloseFrame connection_close_frame(static_cast(QUICTransErrorCode::PROTOCOL_VIOLATION), QUICFrameType::UNKNOWN, 0, nullptr); - connection_close_frame.store(buf, &len, 32); + Ptr ibb = connection_close_frame.to_io_buffer_block(sizeof(buf)); + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } CHECK(len == sizeof(expected)); CHECK(memcmp(buf, expected, len) == 0); } @@ -905,7 +944,7 @@ TEST_CASE("Load MaxData Frame", "[quic]") 0x10, // Type 0xd1, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 // Maximum Data }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::MAX_DATA); CHECK(frame1->size() == 9); const QUICMaxDataFrame *max_data_frame = static_cast(frame1); @@ -918,7 +957,7 @@ TEST_CASE("Load MaxData Frame", "[quic]") uint8_t buf1[] = { 0x10, // Type }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::MAX_DATA); CHECK(frame1->valid() == false); } @@ -927,7 +966,7 @@ TEST_CASE("Load MaxData Frame", "[quic]") TEST_CASE("Store MaxData Frame", "[quic]") { uint8_t buf[65535]; - size_t len; + size_t len = 0; uint8_t expected[] = { 0x10, // Type @@ -936,7 +975,11 @@ TEST_CASE("Store MaxData Frame", "[quic]") QUICMaxDataFrame max_data_frame(0x1122334455667788, 0, nullptr); CHECK(max_data_frame.size() == 9); - max_data_frame.store(buf, &len, 65535); + Ptr ibb = max_data_frame.to_io_buffer_block(sizeof(buf)); + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } CHECK(len == 9); CHECK(memcmp(buf, expected, len) == 0); } @@ -951,7 +994,7 @@ TEST_CASE("Load MaxStreamData Frame", "[quic]") 0x81, 0x02, 0x03, 0x04, // Stream ID 0xd1, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 // Maximum Stream Data }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::MAX_STREAM_DATA); CHECK(frame1->size() == 13); const QUICMaxStreamDataFrame *maxStreamDataFrame1 = static_cast(frame1); @@ -966,7 +1009,7 @@ TEST_CASE("Load MaxStreamData Frame", "[quic]") 0x11, // Type 0x81, 0x02, 0x03, 0x04, // Stream ID }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::MAX_STREAM_DATA); CHECK(frame1->valid() == false); } @@ -975,7 +1018,7 @@ TEST_CASE("Load MaxStreamData Frame", "[quic]") TEST_CASE("Store MaxStreamData Frame", "[quic]") { uint8_t buf[65535]; - size_t len; + size_t len = 0; uint8_t expected[] = { 0x11, // Type @@ -985,7 +1028,11 @@ TEST_CASE("Store MaxStreamData Frame", "[quic]") QUICMaxStreamDataFrame max_stream_data_frame(0x01020304, 0x1122334455667788ULL); CHECK(max_stream_data_frame.size() == 13); - max_stream_data_frame.store(buf, &len, 65535); + Ptr ibb = max_stream_data_frame.to_io_buffer_block(sizeof(buf)); + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } CHECK(len == 13); CHECK(memcmp(buf, expected, len) == 0); } @@ -999,7 +1046,7 @@ TEST_CASE("Load MaxStreams Frame", "[quic]") 0x12, // Type 0x81, 0x02, 0x03, 0x04, // Stream ID }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::MAX_STREAMS); CHECK(frame1->size() == 5); const QUICMaxStreamsFrame *max_streams_frame = static_cast(frame1); @@ -1011,7 +1058,7 @@ TEST_CASE("Load MaxStreams Frame", "[quic]") uint8_t buf1[] = { 0x12, // Type }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::MAX_STREAMS); CHECK(frame1->valid() == false); } @@ -1020,7 +1067,7 @@ TEST_CASE("Load MaxStreams Frame", "[quic]") TEST_CASE("Store MaxStreams Frame", "[quic]") { uint8_t buf[65535]; - size_t len; + size_t len = 0; uint8_t expected[] = { 0x12, // Type @@ -1029,7 +1076,11 @@ TEST_CASE("Store MaxStreams Frame", "[quic]") QUICMaxStreamsFrame max_streams_frame(0x01020304, 0, nullptr); CHECK(max_streams_frame.size() == 5); - max_streams_frame.store(buf, &len, 65535); + Ptr ibb = max_streams_frame.to_io_buffer_block(sizeof(buf)); + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } CHECK(len == 5); CHECK(memcmp(buf, expected, len) == 0); } @@ -1043,7 +1094,7 @@ TEST_CASE("Load DataBlocked Frame", "[quic]") 0x14, // Type 0x07, // Offset }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::DATA_BLOCKED); CHECK(frame1->size() == 2); const QUICDataBlockedFrame *blocked_stream_frame = static_cast(frame1); @@ -1056,7 +1107,7 @@ TEST_CASE("Load DataBlocked Frame", "[quic]") uint8_t buf1[] = { 0x14, // Type }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::DATA_BLOCKED); CHECK(frame1->valid() == false); } @@ -1065,7 +1116,7 @@ TEST_CASE("Load DataBlocked Frame", "[quic]") TEST_CASE("Store DataBlocked Frame", "[quic]") { uint8_t buf[65535]; - size_t len; + size_t len = 0; uint8_t expected[] = { 0x14, // Type @@ -1074,7 +1125,11 @@ TEST_CASE("Store DataBlocked Frame", "[quic]") QUICDataBlockedFrame blocked_stream_frame(0x07, 0, nullptr); CHECK(blocked_stream_frame.size() == 2); - blocked_stream_frame.store(buf, &len, 65535); + Ptr ibb = blocked_stream_frame.to_io_buffer_block(sizeof(buf)); + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } CHECK(len == 2); CHECK(memcmp(buf, expected, len) == 0); } @@ -1089,7 +1144,7 @@ TEST_CASE("Load StreamDataBlocked Frame", "[quic]") 0x81, 0x02, 0x03, 0x04, // Stream ID 0x07, // Offset }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::STREAM_DATA_BLOCKED); CHECK(frame1->size() == 6); const QUICStreamDataBlockedFrame *stream_blocked_frame = static_cast(frame1); @@ -1104,7 +1159,7 @@ TEST_CASE("Load StreamDataBlocked Frame", "[quic]") 0x15, // Type 0x81, 0x02, 0x03, 0x04, // Stream ID }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::STREAM_DATA_BLOCKED); CHECK(frame1->valid() == false); } @@ -1113,7 +1168,7 @@ TEST_CASE("Load StreamDataBlocked Frame", "[quic]") TEST_CASE("Store StreamDataBlocked Frame", "[quic]") { uint8_t buf[65535]; - size_t len; + size_t len = 0; uint8_t expected[] = { 0x15, // Type @@ -1123,7 +1178,11 @@ TEST_CASE("Store StreamDataBlocked Frame", "[quic]") QUICStreamDataBlockedFrame stream_blocked_frame(0x01020304, 0x07); CHECK(stream_blocked_frame.size() == 6); - stream_blocked_frame.store(buf, &len, 65535); + Ptr ibb = stream_blocked_frame.to_io_buffer_block(sizeof(buf)); + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } CHECK(len == 6); CHECK(memcmp(buf, expected, len) == 0); } @@ -1137,7 +1196,7 @@ TEST_CASE("Load StreamsBlocked Frame", "[quic]") 0x16, // Type 0x41, 0x02, // Stream ID }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::STREAMS_BLOCKED); CHECK(frame1->size() == 3); const QUICStreamIdBlockedFrame *stream_id_blocked_frame = static_cast(frame1); @@ -1150,7 +1209,7 @@ TEST_CASE("Load StreamsBlocked Frame", "[quic]") uint8_t buf1[] = { 0x16, // Type }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1->type() == QUICFrameType::STREAMS_BLOCKED); CHECK(frame1->valid() == false); } @@ -1159,7 +1218,7 @@ TEST_CASE("Load StreamsBlocked Frame", "[quic]") TEST_CASE("Store StreamsBlocked Frame", "[quic]") { uint8_t buf[65535]; - size_t len; + size_t len = 0; uint8_t expected[] = { 0x16, // Type @@ -1168,7 +1227,11 @@ TEST_CASE("Store StreamsBlocked Frame", "[quic]") QUICStreamIdBlockedFrame stream_id_blocked_frame(0x0102, 0, nullptr); CHECK(stream_id_blocked_frame.size() == 3); - stream_id_blocked_frame.store(buf, &len, 65535); + Ptr ibb = stream_id_blocked_frame.to_io_buffer_block(sizeof(buf)); + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } CHECK(len == 3); CHECK(memcmp(buf, expected, len) == 0); } @@ -1176,61 +1239,74 @@ TEST_CASE("Store StreamsBlocked Frame", "[quic]") TEST_CASE("Load NewConnectionId Frame", "[quic]") { uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE]; + SECTION("load") { - uint8_t buf1[] = { + uint8_t buf[] = { 0x18, // Type 0x41, 0x02, // Sequence + 0x41, 0x00, // Retire Prior To 0x08, // Length 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, // Connection ID 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, // Stateless Reset Token 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); - CHECK(frame1->type() == QUICFrameType::NEW_CONNECTION_ID); - CHECK(frame1->size() == 28); - const QUICNewConnectionIdFrame *new_con_id_frame = static_cast(frame1); + const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf), nullptr); + CHECK(frame->type() == QUICFrameType::NEW_CONNECTION_ID); + CHECK(frame->size() == sizeof(buf)); + CHECK(frame->valid() == true); + + const QUICNewConnectionIdFrame *new_con_id_frame = static_cast(frame); CHECK(new_con_id_frame != nullptr); CHECK(new_con_id_frame->sequence() == 0x0102); + CHECK(new_con_id_frame->retire_prior_to() == 0x0100); CHECK((new_con_id_frame->connection_id() == QUICConnectionId(reinterpret_cast("\x11\x22\x33\x44\x55\x66\x77\x88"), 8))); - CHECK(memcmp(new_con_id_frame->stateless_reset_token().buf(), buf1 + 12, 16) == 0); + CHECK(memcmp(new_con_id_frame->stateless_reset_token().buf(), buf + sizeof(buf) - QUICStatelessResetToken::LEN, + QUICStatelessResetToken::LEN) == 0); } SECTION("Bad Load") { - uint8_t buf1[] = { + uint8_t buf[] = { 0x18, // Type 0x41, 0x02, // Sequence + 0x41, 0x00, // Retire Prior To 0x08, // Length 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, // Connection ID 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, // Stateless Reset Token }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); - CHECK(frame1->type() == QUICFrameType::NEW_CONNECTION_ID); - CHECK(frame1->valid() == false); + const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf), nullptr); + CHECK(frame->type() == QUICFrameType::NEW_CONNECTION_ID); + CHECK(frame->valid() == false); } } TEST_CASE("Store NewConnectionId Frame", "[quic]") { uint8_t buf[32]; - size_t len; + size_t len = 0; uint8_t expected[] = { 0x18, // Type - 0x41, 0x02, // Sequence + 0x41, 0x02, // Sequence Number + 0x41, 0x00, // Retire Prior To 0x08, // Length 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, // Connection ID 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // Stateless Reset Token 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, }; - QUICNewConnectionIdFrame new_con_id_frame(0x0102, {reinterpret_cast("\x11\x22\x33\x44\x55\x66\x77\x88"), 8}, - {expected + 12}); - CHECK(new_con_id_frame.size() == 28); - - new_con_id_frame.store(buf, &len, 32); - CHECK(len == 28); + QUICNewConnectionIdFrame new_con_id_frame(0x0102, 0x0100, + {reinterpret_cast("\x11\x22\x33\x44\x55\x66\x77\x88"), 8}, + {expected + sizeof(expected) - QUICStatelessResetToken::LEN}); + CHECK(new_con_id_frame.size() == sizeof(expected)); + + Ptr ibb = new_con_id_frame.to_io_buffer_block(sizeof(buf)); + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } + CHECK(len == sizeof(expected)); CHECK(memcmp(buf, expected, len) == 0); } @@ -1242,16 +1318,16 @@ TEST_CASE("Load STOP_SENDING Frame", "[quic]") uint8_t buf[] = { 0x05, // Type 0x92, 0x34, 0x56, 0x78, // Stream ID - 0x00, 0x01, // Error Code + 0x01, // Error Code }; - const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf)); + const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf), nullptr); CHECK(frame->type() == QUICFrameType::STOP_SENDING); - CHECK(frame->size() == 7); + CHECK(frame->size() == 6); const QUICStopSendingFrame *stop_sending_frame = static_cast(frame); CHECK(stop_sending_frame != nullptr); CHECK(stop_sending_frame->stream_id() == 0x12345678); - CHECK(stop_sending_frame->error_code() == 0x0001); + CHECK(stop_sending_frame->error_code() == 0x01); } SECTION("Bad LOAD") @@ -1260,7 +1336,7 @@ TEST_CASE("Load STOP_SENDING Frame", "[quic]") 0x05, // Type 0x92, 0x34, 0x56, 0x78, // Stream ID }; - const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf)); + const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf), nullptr); CHECK(frame->type() == QUICFrameType::STOP_SENDING); CHECK(frame->valid() == false); } @@ -1269,18 +1345,22 @@ TEST_CASE("Load STOP_SENDING Frame", "[quic]") TEST_CASE("Store STOP_SENDING Frame", "[quic]") { uint8_t buf[65535]; - size_t len; + size_t len = 0; uint8_t expected[] = { 0x05, // Type 0x92, 0x34, 0x56, 0x78, // Stream ID - 0x00, 0x01, // Error Code + 0x01, // Error Code }; QUICStopSendingFrame stop_sending_frame(0x12345678, static_cast(0x01)); - CHECK(stop_sending_frame.size() == 7); + CHECK(stop_sending_frame.size() == 6); - stop_sending_frame.store(buf, &len, 65535); - CHECK(len == 7); + Ptr ibb = stop_sending_frame.to_io_buffer_block(sizeof(buf)); + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } + CHECK(len == 6); CHECK(memcmp(buf, expected, len) == 0); } @@ -1293,13 +1373,14 @@ TEST_CASE("Load PATH_CHALLENGE Frame", "[quic]") 0x1a, // Type 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, // Data }; - const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf)); + const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf), nullptr); CHECK(frame->type() == QUICFrameType::PATH_CHALLENGE); CHECK(frame->size() == 9); const QUICPathChallengeFrame *path_challenge_frame = static_cast(frame); CHECK(path_challenge_frame != nullptr); CHECK(memcmp(path_challenge_frame->data(), "\x01\x23\x45\x67\x89\xab\xcd\xef", QUICPathChallengeFrame::DATA_LEN) == 0); + frame->~QUICFrame(); } SECTION("Load") @@ -1308,16 +1389,17 @@ TEST_CASE("Load PATH_CHALLENGE Frame", "[quic]") 0x1a, // Type 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xef, // Data }; - const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf)); + const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf), nullptr); CHECK(frame->type() == QUICFrameType::PATH_CHALLENGE); CHECK(frame->valid() == false); + frame->~QUICFrame(); } } TEST_CASE("Store PATH_CHALLENGE Frame", "[quic]") { uint8_t buf[16]; - size_t len; + size_t len = 0; uint8_t expected[] = { 0x1a, // Type @@ -1332,7 +1414,11 @@ TEST_CASE("Store PATH_CHALLENGE Frame", "[quic]") QUICPathChallengeFrame frame(std::move(data)); CHECK(frame.size() == 9); - frame.store(buf, &len, 16); + Ptr ibb = frame.to_io_buffer_block(sizeof(buf)); + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } CHECK(len == 9); CHECK(memcmp(buf, expected, len) == 0); } @@ -1346,13 +1432,14 @@ TEST_CASE("Load PATH_RESPONSE Frame", "[quic]") 0x1b, // Type 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, // Data }; - const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf)); + const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf), nullptr); CHECK(frame->type() == QUICFrameType::PATH_RESPONSE); CHECK(frame->size() == 9); const QUICPathResponseFrame *path_response_frame = static_cast(frame); CHECK(path_response_frame != nullptr); CHECK(memcmp(path_response_frame->data(), "\x01\x23\x45\x67\x89\xab\xcd\xef", QUICPathResponseFrame::DATA_LEN) == 0); + frame->~QUICFrame(); } SECTION("Load") @@ -1361,16 +1448,17 @@ TEST_CASE("Load PATH_RESPONSE Frame", "[quic]") 0x1b, // Type 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, // Data }; - const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf)); + const QUICFrame *frame = QUICFrameFactory::create(frame_buf, buf, sizeof(buf), nullptr); CHECK(frame->type() == QUICFrameType::PATH_RESPONSE); CHECK(frame->valid() == false); + frame->~QUICFrame(); } } TEST_CASE("Store PATH_RESPONSE Frame", "[quic]") { uint8_t buf[16]; - size_t len; + size_t len = 0; uint8_t expected[] = { 0x1b, // Type @@ -1385,7 +1473,11 @@ TEST_CASE("Store PATH_RESPONSE Frame", "[quic]") QUICPathResponseFrame frame(std::move(data)); CHECK(frame.size() == 9); - frame.store(buf, &len, 16); + Ptr ibb = frame.to_io_buffer_block(sizeof(buf)); + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } CHECK(len == 9); CHECK(memcmp(buf, expected, len) == 0); } @@ -1405,7 +1497,7 @@ TEST_CASE("NEW_TOKEN Frame", "[quic]") SECTION("load") { - const QUICFrame *frame = QUICFrameFactory::create(frame_buf, raw_new_token_frame, raw_new_token_frame_len); + const QUICFrame *frame = QUICFrameFactory::create(frame_buf, raw_new_token_frame, raw_new_token_frame_len, nullptr); CHECK(frame->type() == QUICFrameType::NEW_TOKEN); CHECK(frame->size() == raw_new_token_frame_len); @@ -1413,19 +1505,21 @@ TEST_CASE("NEW_TOKEN Frame", "[quic]") CHECK(new_token_frame != nullptr); CHECK(new_token_frame->token_length() == raw_token_len); CHECK(memcmp(new_token_frame->token(), raw_token, raw_token_len) == 0); + frame->~QUICFrame(); } SECTION("bad load") { - const QUICFrame *frame = QUICFrameFactory::create(frame_buf, raw_new_token_frame, raw_new_token_frame_len - 5); + const QUICFrame *frame = QUICFrameFactory::create(frame_buf, raw_new_token_frame, raw_new_token_frame_len - 5, nullptr); CHECK(frame->type() == QUICFrameType::NEW_TOKEN); CHECK(frame->valid() == false); + frame->~QUICFrame(); } SECTION("store") { uint8_t buf[32]; - size_t len; + size_t len = 0; ats_unique_buf token = ats_unique_malloc(raw_token_len); memcpy(token.get(), raw_token, raw_token_len); @@ -1433,7 +1527,11 @@ TEST_CASE("NEW_TOKEN Frame", "[quic]") QUICNewTokenFrame frame(std::move(token), raw_token_len); CHECK(frame.size() == raw_new_token_frame_len); - frame.store(buf, &len, 16); + Ptr ibb = frame.to_io_buffer_block(sizeof(buf)); + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } CHECK(len == raw_new_token_frame_len); CHECK(memcmp(buf, raw_new_token_frame, len) == 0); } @@ -1452,7 +1550,7 @@ TEST_CASE("RETIRE_CONNECTION_ID Frame", "[quic]") SECTION("load") { const QUICFrame *frame = - QUICFrameFactory::create(frame_buf, raw_retire_connection_id_frame, raw_retire_connection_id_frame_len); + QUICFrameFactory::create(frame_buf, raw_retire_connection_id_frame, raw_retire_connection_id_frame_len, nullptr); CHECK(frame->type() == QUICFrameType::RETIRE_CONNECTION_ID); CHECK(frame->size() == raw_retire_connection_id_frame_len); @@ -1464,7 +1562,7 @@ TEST_CASE("RETIRE_CONNECTION_ID Frame", "[quic]") SECTION("bad load") { const QUICFrame *frame = - QUICFrameFactory::create(frame_buf, raw_retire_connection_id_frame, raw_retire_connection_id_frame_len - 1); + QUICFrameFactory::create(frame_buf, raw_retire_connection_id_frame, raw_retire_connection_id_frame_len - 1, nullptr); CHECK(frame->type() == QUICFrameType::RETIRE_CONNECTION_ID); CHECK(frame->valid() == false); } @@ -1472,12 +1570,16 @@ TEST_CASE("RETIRE_CONNECTION_ID Frame", "[quic]") SECTION("store") { uint8_t buf[32]; - size_t len; + size_t len = 0; QUICRetireConnectionIdFrame frame(seq_num, 0, nullptr); CHECK(frame.size() == raw_retire_connection_id_frame_len); - frame.store(buf, &len, 16); + Ptr ibb = frame.to_io_buffer_block(sizeof(buf)); + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } CHECK(len == raw_retire_connection_id_frame_len); CHECK(memcmp(buf, raw_retire_connection_id_frame, len) == 0); } @@ -1489,7 +1591,7 @@ TEST_CASE("QUICFrameFactory Create Unknown Frame", "[quic]") uint8_t buf1[] = { 0x20, // Type }; - const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1)); + const QUICFrame *frame1 = QUICFrameFactory::create(frame_buf, buf1, sizeof(buf1), nullptr); CHECK(frame1 == nullptr); } @@ -1505,13 +1607,13 @@ TEST_CASE("QUICFrameFactory Fast Create Frame", "[quic]") 0x12, // Type 0x85, 0x06, 0x07, 0x08, // Stream Data }; - const QUICFrame &frame1 = factory.fast_create(buf1, sizeof(buf1)); + const QUICFrame &frame1 = factory.fast_create(buf1, sizeof(buf1), nullptr); CHECK(frame1.type() == QUICFrameType::MAX_STREAMS); const QUICMaxStreamsFrame &max_streams_frame1 = static_cast(frame1); CHECK(max_streams_frame1.maximum_streams() == 0x01020304); - const QUICFrame &frame2 = factory.fast_create(buf2, sizeof(buf2)); + const QUICFrame &frame2 = factory.fast_create(buf2, sizeof(buf2), nullptr); CHECK(frame2.type() == QUICFrameType::MAX_STREAMS); const QUICMaxStreamsFrame &max_streams_frame2 = static_cast(frame2); @@ -1527,7 +1629,7 @@ TEST_CASE("QUICFrameFactory Fast Create Unknown Frame", "[quic]") uint8_t buf1[] = { 0x20, // Type }; - const QUICFrame &frame1 = factory.fast_create(buf1, sizeof(buf1)); + const QUICFrame &frame1 = factory.fast_create(buf1, sizeof(buf1), nullptr); CHECK(frame1.type() == QUICFrameType::UNKNOWN); } diff --git a/iocore/net/quic/test/test_QUICFrameDispatcher.cc b/iocore/net/quic/test/test_QUICFrameDispatcher.cc index be81c2e37fe..eb89aa786ee 100644 --- a/iocore/net/quic/test/test_QUICFrameDispatcher.cc +++ b/iocore/net/quic/test/test_QUICFrameDispatcher.cc @@ -36,14 +36,12 @@ TEST_CASE("QUICFrameHandler", "[quic]") QUICStreamFrame streamFrame(block, 0x03, 0); - MockQUICLDConfig ld_config; - MockQUICCCConfig cc_config; + MockQUICContext context; + MockQUICConnection connection; - MockQUICStreamManager streamManager; + MockQUICStreamManager streamManager = {&connection}; MockQUICConnectionInfoProvider info; - MockQUICCongestionController cc(&info, cc_config); - QUICRTTMeasure rtt_measure; - MockQUICLossDetector lossDetector(&info, &cc, &rtt_measure, ld_config); + MockQUICLossDetector lossDetector(context); QUICFrameDispatcher quicFrameDispatcher(&info); quicFrameDispatcher.add_handler(&connection); @@ -64,14 +62,19 @@ TEST_CASE("QUICFrameHandler", "[quic]") } bool should_send_ack; bool is_flow_controlled; - quicFrameDispatcher.receive_frames(QUICEncryptionLevel::INITIAL, buf, len, should_send_ack, is_flow_controlled, nullptr); + quicFrameDispatcher.receive_frames(QUICEncryptionLevel::INITIAL, buf, len, should_send_ack, is_flow_controlled, nullptr, nullptr); CHECK(connection.getTotalFrameCount() == 0); CHECK(streamManager.getTotalFrameCount() == 1); // CONNECTION_CLOSE frame QUICConnectionCloseFrame connectionCloseFrame(0, 0, "", 0, nullptr); - connectionCloseFrame.store(buf, &len, 4096); - quicFrameDispatcher.receive_frames(QUICEncryptionLevel::INITIAL, buf, len, should_send_ack, is_flow_controlled, nullptr); + ibb = connectionCloseFrame.to_io_buffer_block(sizeof(buf)); + len = 0; + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } + quicFrameDispatcher.receive_frames(QUICEncryptionLevel::INITIAL, buf, len, should_send_ack, is_flow_controlled, nullptr, nullptr); CHECK(connection.getTotalFrameCount() == 1); CHECK(streamManager.getTotalFrameCount() == 1); } diff --git a/iocore/net/quic/test/test_QUICIncomingFrameBuffer.cc b/iocore/net/quic/test/test_QUICIncomingFrameBuffer.cc index 50a3dfaf364..3b4e8a9c594 100644 --- a/iocore/net/quic/test/test_QUICIncomingFrameBuffer.cc +++ b/iocore/net/quic/test/test_QUICIncomingFrameBuffer.cc @@ -71,7 +71,7 @@ TEST_CASE("QUICIncomingStreamFrameBuffer_fin_offset", "[quic]") buffer.insert(new QUICStreamFrame(*stream1_frame_2_r)); err = buffer.insert(new QUICStreamFrame(*stream1_frame_3_r)); CHECK(err->cls == QUICErrorClass::TRANSPORT); - CHECK(err->code == static_cast(QUICTransErrorCode::FINAL_OFFSET_ERROR)); + CHECK(err->code == static_cast(QUICTransErrorCode::FINAL_SIZE_ERROR)); buffer.clear(); @@ -82,7 +82,7 @@ TEST_CASE("QUICIncomingStreamFrameBuffer_fin_offset", "[quic]") buffer2.insert(new QUICStreamFrame(*stream1_frame_1_r)); err = buffer2.insert(new QUICStreamFrame(*stream1_frame_2_r)); CHECK(err->cls == QUICErrorClass::TRANSPORT); - CHECK(err->code == static_cast(QUICTransErrorCode::FINAL_OFFSET_ERROR)); + CHECK(err->code == static_cast(QUICTransErrorCode::FINAL_SIZE_ERROR)); buffer2.clear(); @@ -91,7 +91,7 @@ TEST_CASE("QUICIncomingStreamFrameBuffer_fin_offset", "[quic]") buffer3.insert(new QUICStreamFrame(*stream1_frame_4_r)); err = buffer3.insert(new QUICStreamFrame(*stream1_frame_3_r)); CHECK(err->cls == QUICErrorClass::TRANSPORT); - CHECK(err->code == static_cast(QUICTransErrorCode::FINAL_OFFSET_ERROR)); + CHECK(err->code == static_cast(QUICTransErrorCode::FINAL_SIZE_ERROR)); buffer3.clear(); } @@ -158,14 +158,19 @@ TEST_CASE("QUICIncomingStreamFrameBuffer_pop", "[quic]") auto frame = static_cast(buffer.pop()); CHECK(frame->offset() == 0); + delete frame; frame = static_cast(buffer.pop()); CHECK(frame->offset() == 1024); + delete frame; frame = static_cast(buffer.pop()); CHECK(frame->offset() == 2048); + delete frame; frame = static_cast(buffer.pop()); CHECK(frame->offset() == 3072); + delete frame; frame = static_cast(buffer.pop()); CHECK(frame->offset() == 4096); + delete frame; CHECK(buffer.empty()); buffer.clear(); @@ -179,14 +184,19 @@ TEST_CASE("QUICIncomingStreamFrameBuffer_pop", "[quic]") frame = static_cast(buffer.pop()); CHECK(frame->offset() == 0); + delete frame; frame = static_cast(buffer.pop()); CHECK(frame->offset() == 1024); + delete frame; frame = static_cast(buffer.pop()); CHECK(frame->offset() == 2048); + delete frame; frame = static_cast(buffer.pop()); CHECK(frame->offset() == 3072); + delete frame; frame = static_cast(buffer.pop()); CHECK(frame->offset() == 4096); + delete frame; CHECK(buffer.empty()); delete stream; @@ -228,12 +238,16 @@ TEST_CASE("QUICIncomingStreamFrameBuffer_dup_frame", "[quic]") auto frame = static_cast(buffer.pop()); CHECK(frame->offset() == 0); + delete frame; frame = static_cast(buffer.pop()); CHECK(frame->offset() == 1024); + delete frame; frame = static_cast(buffer.pop()); CHECK(frame->offset() == 2048); + delete frame; frame = static_cast(buffer.pop()); CHECK(frame == nullptr); + delete frame; CHECK(buffer.empty()); buffer.clear(); @@ -251,10 +265,13 @@ TEST_CASE("QUICIncomingStreamFrameBuffer_dup_frame", "[quic]") frame = static_cast(buffer.pop()); CHECK(frame->offset() == 0); + delete frame; frame = static_cast(buffer.pop()); CHECK(frame->offset() == 1024); + delete frame; frame = static_cast(buffer.pop()); CHECK(frame->offset() == 2048); + delete frame; frame = static_cast(buffer.pop()); CHECK(frame == nullptr); CHECK(buffer.empty()); diff --git a/iocore/net/quic/test/test_QUICInvariants.cc b/iocore/net/quic/test/test_QUICInvariants.cc index 5cdbc28b632..e57aab14311 100644 --- a/iocore/net/quic/test/test_QUICInvariants.cc +++ b/iocore/net/quic/test/test_QUICInvariants.cc @@ -37,8 +37,9 @@ TEST_CASE("Long Header - regular case", "[quic]") const uint8_t buf[] = { 0x80, // Long header, Type: NONE 0x11, 0x22, 0x33, 0x44, // Version - 0x55, // DCIL/SCIL + 0x08, // DCID Len 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Destination Connection ID + 0x08, // SCID Len 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, // Source Connection ID }; uint64_t buf_len = sizeof(buf); @@ -53,12 +54,12 @@ TEST_CASE("Long Header - regular case", "[quic]") CHECK(version == 0x11223344); CHECK(QUICInvariants::dcil(dcil, buf, buf_len)); - CHECK(dcil == 5); + CHECK(dcil == sizeof(raw_dcid)); CHECK(QUICInvariants::dcid(dcid, buf, buf_len)); CHECK(dcid == expected_dcid); CHECK(QUICInvariants::scil(scil, buf, buf_len)); - CHECK(scil == 5); + CHECK(scil == sizeof(raw_scid)); CHECK(QUICInvariants::scid(scid, buf, buf_len)); CHECK(scid == expected_scid); } @@ -68,7 +69,8 @@ TEST_CASE("Long Header - regular case", "[quic]") const uint8_t buf[] = { 0x80, // Long header, Type: NONE 0x11, 0x22, 0x33, 0x44, // Version - 0x05, // DCIL/SCIL + 0x00, // DCID Len + 0x08, // SCID Len 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, // Source Connection ID }; uint64_t buf_len = sizeof(buf); @@ -88,7 +90,7 @@ TEST_CASE("Long Header - regular case", "[quic]") CHECK(dcid == QUICConnectionId::ZERO()); CHECK(QUICInvariants::scil(scil, buf, buf_len)); - CHECK(scil == 5); + CHECK(scil == sizeof(raw_scid)); CHECK(QUICInvariants::scid(scid, buf, buf_len)); CHECK(scid == expected_scid); } @@ -98,8 +100,9 @@ TEST_CASE("Long Header - regular case", "[quic]") const uint8_t buf[] = { 0x80, // Long header, Type: NONE 0x11, 0x22, 0x33, 0x44, // Version - 0x50, // DCIL/SCIL + 0x08, // DCID Len 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Destination Connection ID + 0x00, // SCID Len }; uint64_t buf_len = sizeof(buf); @@ -113,7 +116,7 @@ TEST_CASE("Long Header - regular case", "[quic]") CHECK(version == 0x11223344); CHECK(QUICInvariants::dcil(dcil, buf, buf_len)); - CHECK(dcil == 5); + CHECK(dcil == sizeof(raw_dcid)); CHECK(QUICInvariants::dcid(dcid, buf, buf_len)); CHECK(dcid == expected_dcid); @@ -143,8 +146,9 @@ TEST_CASE("Long Header - error cases", "[quic]") const uint8_t buf[] = { 0x80, // Long header, Type: NONE 0x11, 0x22, 0x33, 0x44, // Version - 0x55, // DCIL/SCIL + 0x08, // DCID Len 0x01, 0x02, 0x03, 0x04, // Invalid Destination Connection ID + 0x00, // SCID Len }; uint64_t buf_len = sizeof(buf); @@ -164,8 +168,9 @@ TEST_CASE("Long Header - error cases", "[quic]") const uint8_t buf[] = { 0x80, // Long header, Type: NONE 0x11, 0x22, 0x33, 0x44, // Version - 0x55, // DCIL/SCIL + 0x08, // DCID Len 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Destination Connection ID + 0x08, // SCID Len 0x11, 0x12, 0x13, 0x14, // Invalid Source Connection ID }; uint64_t buf_len = sizeof(buf); diff --git a/iocore/net/quic/test/test_QUICKeyGenerator.cc b/iocore/net/quic/test/test_QUICKeyGenerator.cc index e24d3dbb711..4c1858a1562 100644 --- a/iocore/net/quic/test/test_QUICKeyGenerator.cc +++ b/iocore/net/quic/test/test_QUICKeyGenerator.cc @@ -36,7 +36,7 @@ #include "QUICPacketProtectionKeyInfo.h" // https://github.com/quicwg/base-drafts/wiki/Test-Vector-for-the-Clear-Text-AEAD-key-derivation -TEST_CASE("draft-17 Test Vectors", "[quic]") +TEST_CASE("draft-23 Test Vectors", "[quic]") { SECTION("CLIENT Initial") { @@ -44,15 +44,9 @@ TEST_CASE("draft-17 Test Vectors", "[quic]") QUICConnectionId cid = {reinterpret_cast("\xc6\x54\xef\xd8\xa3\x1b\x47\x92"), 8}; - uint8_t expected_client_key[] = { - 0x86, 0xd1, 0x83, 0x04, 0x80, 0xb4, 0x0f, 0x86, 0xcf, 0x9d, 0x68, 0xdc, 0xad, 0xf3, 0x5d, 0xfe, - }; - uint8_t expected_client_iv[] = { - 0x12, 0xf3, 0x93, 0x8a, 0xca, 0x34, 0xaa, 0x02, 0x54, 0x31, 0x63, 0xd4, - }; - uint8_t expected_client_hp[] = { - 0xcd, 0x25, 0x3a, 0x36, 0xff, 0x93, 0x93, 0x7c, 0x46, 0x93, 0x84, 0xa8, 0x23, 0xaf, 0x6c, 0x56, - }; + uint8_t expected_client_key[] = {0xfc, 0x4a, 0x14, 0x7a, 0x7e, 0xe9, 0x70, 0x29, 0x1b, 0x8f, 0x1c, 0x3, 0x2d, 0x2c, 0x40, 0xf9}; + uint8_t expected_client_iv[] = {0x1e, 0x6a, 0x5d, 0xdb, 0x7c, 0x1d, 0x1a, 0xa7, 0xa0, 0xfd, 0x70, 0x5}; + uint8_t expected_client_hp[] = {0x43, 0x1d, 0x22, 0x82, 0xb4, 0x7b, 0xb9, 0x3f, 0xeb, 0xd2, 0xcf, 0x19, 0x85, 0x21, 0xe2, 0xbe}; QUICPacketProtectionKeyInfo pp_key_info; pp_key_info.set_cipher_initial(EVP_aes_128_gcm()); @@ -74,15 +68,10 @@ TEST_CASE("draft-17 Test Vectors", "[quic]") QUICConnectionId cid = {reinterpret_cast("\xc6\x54\xef\xd8\xa3\x1b\x47\x92"), 8}; - uint8_t expected_server_key[] = { - 0x2c, 0x78, 0x63, 0x3e, 0x20, 0x6e, 0x99, 0xad, 0x25, 0x19, 0x64, 0xf1, 0x9f, 0x6d, 0xcd, 0x6d, - }; - uint8_t expected_server_iv[] = { - 0x7b, 0x50, 0xbf, 0x36, 0x98, 0xa0, 0x6d, 0xfa, 0xbf, 0x75, 0xf2, 0x87, - }; - uint8_t expected_server_hp[] = { - 0x25, 0x79, 0xd8, 0x69, 0x6f, 0x85, 0xed, 0xa6, 0x8d, 0x35, 0x02, 0xb6, 0x55, 0x96, 0x58, 0x6b, - }; + uint8_t expected_server_key[] = {0x60, 0xc0, 0x2f, 0xa6, 0x12, 0x1e, 0xb1, 0xab, + 0xa4, 0x35, 0x1f, 0x2a, 0x63, 0xb0, 0xac, 0xf8}; + uint8_t expected_server_iv[] = {0x38, 0xd, 0xf3, 0xc0, 0xf2, 0x8d, 0x94, 0x7, 0x76, 0x5c, 0x55, 0xa1}; + uint8_t expected_server_hp[] = {0x92, 0xe8, 0x67, 0xb1, 0x20, 0xb1, 0x3f, 0x40, 0x9c, 0x1a, 0xa8, 0xef, 0x54, 0x30, 0x53, 0x51}; QUICPacketProtectionKeyInfo pp_key_info; pp_key_info.set_cipher_initial(EVP_aes_128_gcm()); diff --git a/iocore/net/quic/test/test_QUICLossDetector.cc b/iocore/net/quic/test/test_QUICLossDetector.cc index 00167247299..6c3604ffef3 100644 --- a/iocore/net/quic/test/test_QUICLossDetector.cc +++ b/iocore/net/quic/test/test_QUICLossDetector.cc @@ -38,11 +38,11 @@ TEST_CASE("QUICLossDetector_Loss", "[quic]") QUICAckFrameManager afm; QUICConnectionId connection_id = {reinterpret_cast("\x01"), 1}; - MockQUICCCConfig cc_config; - MockQUICLDConfig ld_config; - MockQUICConnectionInfoProvider info; - MockQUICCongestionController cc(&info, cc_config); - QUICLossDetector detector(&info, &cc, &rtt_measure, ld_config); + MockQUICContext context; + QUICPinger pinger; + QUICPadder padder(NetVConnectionContext_t::NET_VCONNECTION_IN); + MockQUICCongestionController cc; + QUICLossDetector detector(context, &cc, &rtt_measure, &pinger, &padder); ats_unique_buf payload = ats_unique_malloc(512); size_t payload_len = 512; QUICPacketUPtr packet = QUICPacketFactory::create_null_packet(); @@ -54,11 +54,16 @@ TEST_CASE("QUICLossDetector_Loss", "[quic]") // Check initial state uint8_t frame_buffer[1024] = {0}; CHECK(g.lost_frame_count == 0); - QUICFrame *ping_frame = g.generate_frame(frame_buffer, QUICEncryptionLevel::HANDSHAKE, 4, UINT16_MAX, 0); + QUICFrame *ping_frame = g.generate_frame(frame_buffer, QUICEncryptionLevel::HANDSHAKE, 4, UINT16_MAX, 0, 0); uint8_t raw[4]; - size_t len; - CHECK(ping_frame->store(raw, &len, 10240) < 4); + size_t len = 0; + Ptr ibb = ping_frame->to_io_buffer_block(sizeof(raw)); + for (auto b = ibb; b; b = b->next) { + memcpy(raw + len, b->start(), b->size()); + len += b->size(); + } + CHECK(len < 4); // Send SERVER_CLEARTEXT (Handshake message) ats_unique_buf payload = ats_unique_malloc(sizeof(raw)); @@ -245,7 +250,7 @@ TEST_CASE("QUICLossDetector_Loss", "[quic]") afm.update(level, pn9, payload_len, false); afm.update(level, pn10, payload_len, false); uint8_t buf[QUICFrame::MAX_INSTANCE_SIZE]; - QUICFrame *x = afm.generate_frame(buf, level, 2048, 2048, 0); + QUICFrame *x = afm.generate_frame(buf, level, 2048, 2048, 0, 0); frame = static_cast(x); ink_hrtime_sleep(HRTIME_MSECONDS(1000)); detector.handle_frame(level, *frame); @@ -263,18 +268,19 @@ TEST_CASE("QUICLossDetector_Loss", "[quic]") CHECK(cc.lost_packets.find(pn8) == cc.lost_packets.end()); CHECK(cc.lost_packets.find(pn9) == cc.lost_packets.end()); CHECK(cc.lost_packets.find(pn9) == cc.lost_packets.end()); + x->~QUICFrame(); } } TEST_CASE("QUICLossDetector_HugeGap", "[quic]") { uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE]; - MockQUICConnectionInfoProvider info; - MockQUICCCConfig cc_config; - MockQUICLDConfig ld_config; - MockQUICCongestionController cc(&info, cc_config); QUICRTTMeasure rtt_measure; - QUICLossDetector detector(&info, &cc, &rtt_measure, ld_config); + MockQUICContext context; + QUICPinger pinger; + QUICPadder padder(NetVConnectionContext_t::NET_VCONNECTION_IN); + MockQUICCongestionController cc; + QUICLossDetector detector(context, &cc, &rtt_measure, &pinger, &padder); auto t1 = Thread::get_hrtime(); QUICAckFrame *ack = QUICFrameFactory::create_ack_frame(frame_buf, 100000000, 100, 10000000); @@ -282,4 +288,5 @@ TEST_CASE("QUICLossDetector_HugeGap", "[quic]") detector.handle_frame(QUICEncryptionLevel::INITIAL, *ack); auto t2 = Thread::get_hrtime(); CHECK(t2 - t1 < HRTIME_MSECONDS(100)); + ack->~QUICAckFrame(); } diff --git a/iocore/net/quic/test/test_QUICPacket.cc b/iocore/net/quic/test/test_QUICPacket.cc index f50d156af65..573e1a89077 100644 --- a/iocore/net/quic/test/test_QUICPacket.cc +++ b/iocore/net/quic/test/test_QUICPacket.cc @@ -32,8 +32,9 @@ TEST_CASE("QUICPacketHeader - Long", "[quic]") const uint8_t input[] = { 0xc0, // Long header, Type: NONE 0x00, 0x00, 0x00, 0x00, // Version - 0x55, // DCIL/SCIL + 0x08, // DCID Len 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Destination Connection ID + 0x08, // SCID Len 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, // Source Connection ID 0x00, 0x00, 0x00, 0x08, // Supported Version 1 0x00, 0x00, 0x00, 0x09, // Supported Version 1 @@ -41,9 +42,9 @@ TEST_CASE("QUICPacketHeader - Long", "[quic]") ats_unique_buf uinput = ats_unique_malloc(sizeof(input)); memcpy(uinput.get(), input, sizeof(input)); - QUICPacketHeaderUPtr header = QUICPacketHeader::load({}, std::move(uinput), sizeof(input), 0); - CHECK(header->size() == 22); - CHECK(header->packet_size() == 30); + QUICPacketHeaderUPtr header = QUICPacketHeader::load({}, {}, std::move(uinput), sizeof(input), 0); + CHECK(header->size() == sizeof(input) - 8); + CHECK(header->packet_size() == sizeof(input)); CHECK(header->type() == QUICPacketType::VERSION_NEGOTIATION); CHECK( (header->destination_cid() == QUICConnectionId(reinterpret_cast("\x01\x02\x03\x04\x05\x06\x07\x08"), 8))); @@ -57,18 +58,19 @@ TEST_CASE("QUICPacketHeader - Long", "[quic]") const uint8_t input[] = { 0xc3, // Long header, Type: INITIAL 0x11, 0x22, 0x33, 0x44, // Version - 0x55, // DCIL/SCIL + 0x08, // DCID Len 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Destination Connection ID + 0x08, // SCID Len 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, // Source Connection ID 0x00, // Token Length (i), Token (*) - 0x02, // Payload length + 0x06, // Length 0x01, 0x23, 0x45, 0x67, // Packet number 0xff, 0xff, // Payload (dummy) }; ats_unique_buf uinput = ats_unique_malloc(sizeof(input)); memcpy(uinput.get(), input, sizeof(input)); - QUICPacketHeaderUPtr header = QUICPacketHeader::load({}, std::move(uinput), sizeof(input), 0); + QUICPacketHeaderUPtr header = QUICPacketHeader::load({}, {}, std::move(uinput), sizeof(input), 0); CHECK(header->size() == sizeof(input) - 2); // Packet Length - Payload Length CHECK(header->packet_size() == sizeof(input)); CHECK(header->type() == QUICPacketType::INITIAL); @@ -85,9 +87,11 @@ TEST_CASE("QUICPacketHeader - Long", "[quic]") const uint8_t input[] = { 0xf5, // Long header, Type: RETRY 0x11, 0x22, 0x33, 0x44, // Version - 0x55, // DCIL/SCIL + 0x08, // DCID Len 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Destination Connection ID + 0x08, // SCID Len 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, // Source Connection ID + 0x08, // ODCID Len 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, // Original Destination Connection ID 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, // Retry Token 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, @@ -97,7 +101,7 @@ TEST_CASE("QUICPacketHeader - Long", "[quic]") const uint8_t retry_token[] = {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0}; - QUICPacketHeaderUPtr header = QUICPacketHeader::load({}, std::move(uinput), sizeof(input), 0); + QUICPacketHeaderUPtr header = QUICPacketHeader::load({}, {}, std::move(uinput), sizeof(input), 0); CHECK(header->size() == sizeof(input) - 16); // Packet Length - Payload Length (Retry Token) CHECK(header->packet_size() == sizeof(input)); CHECK(header->type() == QUICPacketType::RETRY); @@ -114,6 +118,62 @@ TEST_CASE("QUICPacketHeader - Long", "[quic]") CHECK(header->version() == 0x11223344); } + SECTION("Long Header (parse) INITIAL Packet") + { + const uint8_t buf[] = { + 0xc3, // Long header, Type: INITIAL + 0x11, 0x22, 0x33, 0x44, // Version + 0x08, // DCID Len + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Destination Connection ID + 0x08, // SCID Len + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, // Source Connection ID + 0x00, // Token Length (i), Token (*) + 0x06, // Length + 0x01, 0x23, 0x45, 0x67, // Packet number + 0xff, 0xff, // Payload (dummy) + }; + + QUICPacketType type; + REQUIRE(QUICPacketLongHeader::type(type, buf, sizeof(buf))); + CHECK(type == QUICPacketType::INITIAL); + + QUICVersion version; + REQUIRE(QUICPacketLongHeader::version(version, buf, sizeof(buf))); + CHECK(version == 0x11223344); + + uint8_t dcil; + REQUIRE(QUICPacketLongHeader::dcil(dcil, buf, sizeof(buf))); + CHECK(dcil == 8); + + uint8_t scil; + REQUIRE(QUICPacketLongHeader::scil(scil, buf, sizeof(buf))); + CHECK(dcil == 8); + + size_t token_length; + uint8_t token_length_field_len; + size_t token_length_field_offset; + REQUIRE(QUICPacketLongHeader::token_length(token_length, token_length_field_len, token_length_field_offset, buf, sizeof(buf))); + CHECK(token_length == 0); + CHECK(token_length_field_len == 1); + CHECK(token_length_field_offset == 23); + + size_t length; + uint8_t length_field_len; + size_t length_field_offset; + REQUIRE(QUICPacketLongHeader::length(length, length_field_len, length_field_offset, buf, sizeof(buf))); + CHECK(length == 6); + CHECK(length_field_len == 1); + CHECK(length_field_offset == 24); + + size_t pn_offset; + REQUIRE(QUICPacketLongHeader::packet_number_offset(pn_offset, buf, sizeof(buf))); + CHECK(pn_offset == 25); + + size_t packet_length; + REQUIRE(QUICPacketLongHeader::packet_length(packet_length, buf, sizeof(buf))); + CHECK(packet_length == sizeof(buf)); + } + SECTION("Long Header (store) INITIAL Packet") { uint8_t buf[64] = {0}; @@ -122,8 +182,9 @@ TEST_CASE("QUICPacketHeader - Long", "[quic]") const uint8_t expected[] = { 0xc3, // Long header, Type: INITIAL 0x11, 0x22, 0x33, 0x44, // Version - 0x55, // DCIL/SCIL + 0x08, // DCID Len 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Destination Connection ID + 0x08, // SCID Len 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, // Source Connection ID 0x00, // Token Length (i), Token (*) 0x19, // Length (Not 0x09 because it will have 16 bytes of AEAD tag) @@ -160,11 +221,13 @@ TEST_CASE("QUICPacketHeader - Long", "[quic]") size_t len = 0; const uint8_t expected[] = { - 0xf5, // Long header, Type: RETRY + 0xf0, // Long header, Type: RETRY 0x11, 0x22, 0x33, 0x44, // Version - 0x55, // DCIL/SCIL + 0x08, // DCID Len 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Destination Connection ID + 0x08, // SCID Len 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, // Source Connection ID + 0x08, // ODCID Len 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, // Original Destination Connection ID 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, // Retry Token 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, @@ -220,7 +283,7 @@ TEST_CASE("QUICPacketHeader - Short", "[quic]") ats_unique_buf uinput = ats_unique_malloc(sizeof(input)); memcpy(uinput.get(), input, sizeof(input)); - QUICPacketHeaderUPtr header = QUICPacketHeader::load({}, std::move(uinput), sizeof(input), 0); + QUICPacketHeaderUPtr header = QUICPacketHeader::load({}, {}, std::move(uinput), sizeof(input), 0); CHECK(header->size() == 23); CHECK(header->packet_size() == 25); CHECK(header->key_phase() == QUICKeyPhase::PHASE_0); diff --git a/iocore/net/quic/test/test_QUICPacketFactory.cc b/iocore/net/quic/test/test_QUICPacketFactory.cc index 08d94b494ca..dc017658803 100644 --- a/iocore/net/quic/test/test_QUICPacketFactory.cc +++ b/iocore/net/quic/test/test_QUICPacketFactory.cc @@ -50,10 +50,11 @@ TEST_CASE("QUICPacketFactory_Create_VersionNegotiationPacket", "[quic]") uint8_t expected[] = { 0xa7, // Long header, Type: NONE 0x00, 0x00, 0x00, 0x00, // Version - 0x55, // DCIL/SCIL + 0x08, // DCID Len 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, // Destination Connection ID + 0x08, // SCID Len 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Source Connection ID - 0xff, 0x00, 0x00, 0x14, // Supported Version + 0xff, 0x00, 0x00, 0x17, // Supported Version 0x1a, 0x2a, 0x3a, 0x4a, // Excercise Version }; uint8_t buf[1024] = {0}; diff --git a/iocore/net/quic/test/test_QUICPacketHeaderProtector.cc b/iocore/net/quic/test/test_QUICPacketHeaderProtector.cc index dc754a4a2f6..5cb69af9efa 100644 --- a/iocore/net/quic/test/test_QUICPacketHeaderProtector.cc +++ b/iocore/net/quic/test/test_QUICPacketHeaderProtector.cc @@ -70,13 +70,19 @@ TEST_CASE("QUICPacketHeaderProtector") SECTION("Long header", "[quic]") { uint8_t original[] = { - 0xC3, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0xc3, // Long header, Type: INITIAL + 0x11, 0x22, 0x33, 0x44, // Version + 0x08, // DCID Len + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Destination Connection ID + 0x08, // SCID Len + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, // Source Connection ID + 0x00, // Token Length (i), Token (*) + 0x19, // Length (Not 0x09 because it will have 16 bytes of AEAD tag) + 0x01, 0x23, 0x45, 0x67, // Packet number + 0x11, 0x22, 0x33, 0x44, 0x55, // Payload (dummy) }; uint8_t tmp[64]; - memcpy(tmp, original, sizeof(tmp)); + memcpy(tmp, original, sizeof(original)); QUICPacketProtectionKeyInfo pp_key_info_client; QUICPacketProtectionKeyInfo pp_key_info_server; @@ -91,15 +97,18 @@ TEST_CASE("QUICPacketHeaderProtector") QUICPacketHeaderProtector server_ph_protector(pp_key_info_server); // ## Client -> Server - client_ph_protector.protect(tmp, sizeof(tmp), 18); + REQUIRE(client_ph_protector.protect(tmp, sizeof(tmp), 18)); CHECK(memcmp(original, tmp, sizeof(original)) != 0); - server_ph_protector.unprotect(tmp, sizeof(tmp)); + REQUIRE(server_ph_protector.unprotect(tmp, sizeof(tmp))); CHECK(memcmp(original, tmp, sizeof(original)) == 0); // ## Server -> Client - server_ph_protector.protect(tmp, sizeof(tmp), 18); + REQUIRE(server_ph_protector.protect(tmp, sizeof(tmp), 18)); CHECK(memcmp(original, tmp, sizeof(original)) != 0); - client_ph_protector.unprotect(tmp, sizeof(tmp)); + REQUIRE(client_ph_protector.unprotect(tmp, sizeof(tmp))); CHECK(memcmp(original, tmp, sizeof(original)) == 0); + + delete client; + delete server; } SECTION("Short header", "[quic]") @@ -197,14 +206,24 @@ TEST_CASE("QUICPacketHeaderProtector") REQUIRE(client->handshake(&msg5, &msg4) == 1); // ## Client -> Server - client_ph_protector.protect(tmp, sizeof(tmp), 18); + REQUIRE(client_ph_protector.protect(tmp, sizeof(tmp), 18)); CHECK(memcmp(original, tmp, sizeof(original)) != 0); - server_ph_protector.unprotect(tmp, sizeof(tmp)); + REQUIRE(server_ph_protector.unprotect(tmp, sizeof(tmp))); CHECK(memcmp(original, tmp, sizeof(original)) == 0); // ## Server -> Client - server_ph_protector.protect(tmp, sizeof(tmp), 18); + REQUIRE(server_ph_protector.protect(tmp, sizeof(tmp), 18)); CHECK(memcmp(original, tmp, sizeof(original)) != 0); - client_ph_protector.unprotect(tmp, sizeof(tmp)); + REQUIRE(client_ph_protector.unprotect(tmp, sizeof(tmp))); CHECK(memcmp(original, tmp, sizeof(original)) == 0); + + delete client; + delete server; } + + SSL_CTX_free(client_ssl_ctx); + SSL_CTX_free(server_ssl_ctx); + BIO_free(crt_bio); + BIO_free(key_bio); + X509_free(x509); + EVP_PKEY_free(pkey); } diff --git a/iocore/net/quic/test/test_QUICPathValidator.cc b/iocore/net/quic/test/test_QUICPathValidator.cc new file mode 100644 index 00000000000..78c51f2f355 --- /dev/null +++ b/iocore/net/quic/test/test_QUICPathValidator.cc @@ -0,0 +1,112 @@ +/** @file + * + * A brief file description + * + * @section license License + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "catch.hpp" + +#include "quic/QUICPathValidator.h" +#include "quic/Mock.h" +#include "stdio.h" +#include "stdlib.h" + +TEST_CASE("QUICPathValidator", "[quic]") +{ + MockQUICConnectionInfoProvider cinfo_provider; + QUICPathValidator pv_c(cinfo_provider, [](bool x) {}); + QUICPathValidator pv_s(cinfo_provider, [](bool x) {}); + + SECTION("interests") + { + auto interests = pv_c.interests(); + CHECK(std::find_if(interests.begin(), interests.end(), [](QUICFrameType t) { return t == QUICFrameType::PATH_CHALLENGE; }) != + interests.end()); + CHECK(std::find_if(interests.begin(), interests.end(), [](QUICFrameType t) { return t == QUICFrameType::PATH_RESPONSE; }) != + interests.end()); + CHECK(std::find_if(interests.begin(), interests.end(), [](QUICFrameType t) { + return t != QUICFrameType::PATH_CHALLENGE && t != QUICFrameType::PATH_RESPONSE; + }) == interests.end()); + } + + SECTION("basic scenario") + { + uint8_t frame_buf[1024]; + uint32_t seq_num = 1; + IpEndpoint local, remote; + ats_ip_pton("127.0.0.1:4433", &local); + ats_ip_pton("127.0.0.1:12345", &remote); + QUICPath path = {local, remote}; + + // Send a challenge + CHECK(!pv_c.is_validating(path)); + CHECK(!pv_c.is_validated(path)); + REQUIRE(!pv_c.will_generate_frame(QUICEncryptionLevel::ONE_RTT, 0, false, seq_num)); + pv_c.validate(path); + CHECK(pv_c.is_validating(path)); + CHECK(!pv_c.is_validated(path)); + REQUIRE(pv_c.will_generate_frame(QUICEncryptionLevel::ONE_RTT, 0, false, seq_num)); + auto frame = pv_c.generate_frame(frame_buf, QUICEncryptionLevel::ONE_RTT, 1024, 1024, 0, seq_num); + REQUIRE(frame); + CHECK(frame->type() == QUICFrameType::PATH_CHALLENGE); + CHECK(pv_c.is_validating(path)); + CHECK(!pv_c.is_validated(path)); + ++seq_num; + + // Receive the challenge and respond + CHECK(!pv_s.is_validating(path)); + CHECK(!pv_s.is_validated(path)); + REQUIRE(!pv_s.will_generate_frame(QUICEncryptionLevel::ONE_RTT, 0, false, seq_num)); + auto error = pv_s.handle_frame(QUICEncryptionLevel::ONE_RTT, *frame); + REQUIRE(!error); + CHECK(!pv_s.is_validating(path)); + CHECK(!pv_s.is_validated(path)); + REQUIRE(pv_s.will_generate_frame(QUICEncryptionLevel::ONE_RTT, 0, false, seq_num)); + frame->~QUICFrame(); + frame = pv_s.generate_frame(frame_buf, QUICEncryptionLevel::ONE_RTT, 1024, 1024, 0, seq_num); + REQUIRE(frame); + CHECK(frame->type() == QUICFrameType::PATH_RESPONSE); + CHECK(!pv_s.is_validating(path)); + CHECK(!pv_s.is_validated(path)); + ++seq_num; + + uint8_t buf[1024]; + size_t len = 0; + uint8_t received_frame_buf[1024]; + Ptr ibb = frame->to_io_buffer_block(sizeof(buf)); + for (auto b = ibb; b; b = b->next) { + memcpy(buf + len, b->start(), b->size()); + len += b->size(); + } + MockQUICPacket mock_packet; + auto received_frame = QUICFrameFactory::create(received_frame_buf, buf, len, &mock_packet); + mock_packet.set_from(remote); + mock_packet.set_to(local); + + // Receive the response + error = pv_c.handle_frame(QUICEncryptionLevel::ONE_RTT, *received_frame); + REQUIRE(!error); + CHECK(!pv_c.is_validating(path)); + CHECK(pv_c.is_validated(path)); + + frame->~QUICFrame(); + received_frame->~QUICFrame(); + } +} diff --git a/iocore/net/quic/test/test_QUICPinger.cc b/iocore/net/quic/test/test_QUICPinger.cc new file mode 100644 index 00000000000..fce04c62ce1 --- /dev/null +++ b/iocore/net/quic/test/test_QUICPinger.cc @@ -0,0 +1,101 @@ +/** @file + * + * A brief file description + * + * @section license License + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "catch.hpp" + +#include "QUICPinger.h" + +static constexpr QUICEncryptionLevel level = QUICEncryptionLevel::ONE_RTT; +static uint8_t frame[1024] = {0}; + +TEST_CASE("QUICPinger", "[quic]") +{ + SECTION("request and cancel") + { + QUICPinger pinger; + pinger.request(); + REQUIRE(pinger.count() == 1); + pinger.request(); + REQUIRE(pinger.count() == 2); + pinger.cancel(); + REQUIRE(pinger.count() == 1); + REQUIRE(pinger.generate_frame(frame, level, UINT64_MAX, UINT16_MAX, 0, 0) != nullptr); + REQUIRE(pinger.count() == 0); + } + + SECTION("generate PING Frame twice") + { + QUICPinger pinger; + pinger.request(); + REQUIRE(pinger.count() == 1); + pinger.request(); + REQUIRE(pinger.count() == 2); + REQUIRE(pinger.will_generate_frame(level, UINT64_MAX, false, 0) == true); + REQUIRE(pinger.count() == 2); + REQUIRE(pinger.will_generate_frame(level, UINT64_MAX, false, 0) == false); + REQUIRE(pinger.count() == 2); + } + + SECTION("don't generate frame when packet is ack_elicting") + { + QUICPinger pinger; + pinger.request(); + REQUIRE(pinger.count() == 1); + pinger.request(); + REQUIRE(pinger.count() == 2); + REQUIRE(pinger.will_generate_frame(level, UINT64_MAX, true, 0) == false); + REQUIRE(pinger.count() == 1); + REQUIRE(pinger.will_generate_frame(level, UINT64_MAX, true, 1) == false); + REQUIRE(pinger.count() == 0); + } + + SECTION("generating PING Frame for next continuos un-ack-eliciting packets") + { + QUICPinger pinger; + REQUIRE(pinger.will_generate_frame(level, UINT64_MAX, false, 0) == true); + REQUIRE(pinger.count() == 1); + REQUIRE(pinger.will_generate_frame(level, UINT64_MAX, true, 1) == false); + REQUIRE(pinger.count() == 0); + REQUIRE(pinger.will_generate_frame(level, UINT64_MAX, false, 2) == false); + REQUIRE(pinger.count() == 0); + REQUIRE(pinger.will_generate_frame(level, UINT64_MAX, false, 3) == true); + REQUIRE(pinger.count() == 1); + } + + SECTION("don't send PING Frame for empty packet") + { + QUICPinger pinger; + REQUIRE(pinger.will_generate_frame(level, 0, false, 0) == false); + REQUIRE(pinger.count() == 0); + REQUIRE(pinger.will_generate_frame(level, UINT64_MAX, false, 1) == true); + REQUIRE(pinger.count() == 1); + REQUIRE(pinger.will_generate_frame(level, UINT64_MAX, true, 2) == false); + REQUIRE(pinger.count() == 0); + REQUIRE(pinger.will_generate_frame(level, UINT64_MAX, false, 3) == false); + REQUIRE(pinger.count() == 0); + REQUIRE(pinger.will_generate_frame(level, 0, false, 4) == false); + REQUIRE(pinger.count() == 0); + REQUIRE(pinger.will_generate_frame(level, 1, false, 5) == true); + REQUIRE(pinger.count() == 1); + } +} diff --git a/iocore/net/quic/test/test_QUICStream.cc b/iocore/net/quic/test/test_QUICStream.cc index aefc4883033..1ed23562515 100644 --- a/iocore/net/quic/test/test_QUICStream.cc +++ b/iocore/net/quic/test/test_QUICStream.cc @@ -229,50 +229,50 @@ TEST_CASE("QUICBidiStream", "[quic]") write_buffer->write(data, 1024); stream->handleEvent(VC_EVENT_WRITE_READY, nullptr); - CHECK(stream->will_generate_frame(level, 0) == true); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); CHECK(frame->type() == QUICFrameType::STREAM); - CHECK(stream->will_generate_frame(level, 0) == false); + CHECK(stream->will_generate_frame(level, 0, false, 0) == false); write_buffer->write(data, 1024); stream->handleEvent(VC_EVENT_WRITE_READY, nullptr); - CHECK(stream->will_generate_frame(level, 0) == true); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); CHECK(frame->type() == QUICFrameType::STREAM); - CHECK(stream->will_generate_frame(level, 0) == false); + CHECK(stream->will_generate_frame(level, 0, false, 0) == false); write_buffer->write(data, 1024); stream->handleEvent(VC_EVENT_WRITE_READY, nullptr); - CHECK(stream->will_generate_frame(level, 0) == true); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); CHECK(frame->type() == QUICFrameType::STREAM); - CHECK(stream->will_generate_frame(level, 0) == false); + CHECK(stream->will_generate_frame(level, 0, false, 0) == false); write_buffer->write(data, 1024); stream->handleEvent(VC_EVENT_WRITE_READY, nullptr); - CHECK(stream->will_generate_frame(level, 0) == true); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); CHECK(frame->type() == QUICFrameType::STREAM); - CHECK(stream->will_generate_frame(level, 0) == false); + CHECK(stream->will_generate_frame(level, 0, false, 0) == false); // This should not send a frame because of flow control write_buffer->write(data, 1024); stream->handleEvent(VC_EVENT_WRITE_READY, nullptr); - CHECK(stream->will_generate_frame(level, 0) == true); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); CHECK(frame); CHECK(frame->type() == QUICFrameType::STREAM_DATA_BLOCKED); - CHECK(stream->will_generate_frame(level, 0) == true); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); // Update window stream->recv(*std::make_shared(stream_id, 5120)); // This should send a frame stream->handleEvent(VC_EVENT_WRITE_READY, nullptr); - CHECK(stream->will_generate_frame(level, 0) == true); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); CHECK(frame->type() == QUICFrameType::STREAM); - CHECK(stream->will_generate_frame(level, 0) == false); + CHECK(stream->will_generate_frame(level, 0, false, 0) == false); // Update window stream->recv(*std::make_shared(stream_id, 5632)); @@ -280,24 +280,24 @@ TEST_CASE("QUICBidiStream", "[quic]") // This should send a frame write_buffer->write(data, 1024); stream->handleEvent(VC_EVENT_WRITE_READY, nullptr); - CHECK(stream->will_generate_frame(level, 0) == true); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); CHECK(frame->type() == QUICFrameType::STREAM); - CHECK(stream->will_generate_frame(level, 0) == true); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); stream->handleEvent(VC_EVENT_WRITE_READY, nullptr); - CHECK(stream->will_generate_frame(level, 0) == true); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); CHECK(frame->type() == QUICFrameType::STREAM_DATA_BLOCKED); // Update window stream->recv(*std::make_shared(stream_id, 6144)); stream->handleEvent(VC_EVENT_WRITE_READY, nullptr); - CHECK(stream->will_generate_frame(level, 0) == true); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); CHECK(frame->type() == QUICFrameType::STREAM); - CHECK(stream->will_generate_frame(level, 0) == false); + CHECK(stream->will_generate_frame(level, 0, false, 0) == false); } /* @@ -329,13 +329,13 @@ TEST_CASE("QUICBidiStream", "[quic]") write_buffer->write(data1, sizeof(data1)); stream->handleEvent(VC_EVENT_WRITE_READY, nullptr); // Generate STREAM frame - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); frame1 = static_cast(frame); CHECK(frame->type() == QUICFrameType::STREAM); - CHECK(stream->generate_frame(frame_buf, level, 4096, 4096, 0) == nullptr); - CHECK(stream->will_generate_frame(level, 0) == false); + CHECK(stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0) == nullptr); + CHECK(stream->will_generate_frame(level, 0, false, 0) == false); stream->on_frame_lost(frame->id()); - CHECK(stream->will_generate_frame(level, 0) == true); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); // Write data2 write_buffer->write(data2, sizeof(data2)); @@ -343,7 +343,7 @@ TEST_CASE("QUICBidiStream", "[quic]") // Lost the frame stream->on_frame_lost(frame->id()); // Regenerate a frame - frame = stream->generate_frame(frame_buf2, level, 4096, 4096, 0); + frame = stream->generate_frame(frame_buf2, level, 4096, 4096, 0, 0); // Lost data should be resent first frame2 = static_cast(frame); CHECK(frame->type() == QUICFrameType::STREAM); @@ -370,15 +370,15 @@ TEST_CASE("QUICBidiStream", "[quic]") QUICFrame *frame = nullptr; stream->reset(QUICStreamErrorUPtr(new QUICStreamError(stream.get(), QUIC_APP_ERROR_CODE_STOPPING))); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); REQUIRE(frame); CHECK(frame->type() == QUICFrameType::RESET_STREAM); // Don't send it again untill it is considers as lost - CHECK(stream->generate_frame(frame_buf, level, 4096, 4096, 0) == nullptr); + CHECK(stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0) == nullptr); // Loss the frame stream->on_frame_lost(frame->id()); // After the loss the frame should be regenerated - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); REQUIRE(frame); CHECK(frame->type() == QUICFrameType::RESET_STREAM); } @@ -401,15 +401,15 @@ TEST_CASE("QUICBidiStream", "[quic]") QUICFrame *frame = nullptr; stream->stop_sending(QUICStreamErrorUPtr(new QUICStreamError(stream.get(), QUIC_APP_ERROR_CODE_STOPPING))); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); REQUIRE(frame); CHECK(frame->type() == QUICFrameType::STOP_SENDING); // Don't send it again untill it is considers as lost - CHECK(stream->generate_frame(frame_buf, level, 4096, 4096, 0) == nullptr); + CHECK(stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0) == nullptr); // Loss the frame stream->on_frame_lost(frame->id()); // After the loss the frame should be regenerated - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); REQUIRE(frame); CHECK(frame->type() == QUICFrameType::STOP_SENDING); } @@ -599,15 +599,15 @@ TEST_CASE("QUIC receive only stream", "[quic]") QUICFrame *frame = nullptr; stream->stop_sending(QUICStreamErrorUPtr(new QUICStreamError(stream.get(), QUIC_APP_ERROR_CODE_STOPPING))); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); REQUIRE(frame); CHECK(frame->type() == QUICFrameType::STOP_SENDING); // Don't send it again untill it is considers as lost - CHECK(stream->generate_frame(frame_buf, level, 4096, 4096, 0) == nullptr); + CHECK(stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0) == nullptr); // Loss the frame stream->on_frame_lost(frame->id()); // After the loss the frame should be regenerated - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); REQUIRE(frame); CHECK(frame->type() == QUICFrameType::STOP_SENDING); } @@ -687,50 +687,50 @@ TEST_CASE("QUIC send only stream", "[quic]") write_buffer->write(data, 1024); stream->handleEvent(VC_EVENT_WRITE_READY, nullptr); - CHECK(stream->will_generate_frame(level, 0) == true); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); CHECK(frame->type() == QUICFrameType::STREAM); - CHECK(stream->will_generate_frame(level, 0) == false); + CHECK(stream->will_generate_frame(level, 0, false, 0) == false); write_buffer->write(data, 1024); stream->handleEvent(VC_EVENT_WRITE_READY, nullptr); - CHECK(stream->will_generate_frame(level, 0) == true); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); CHECK(frame->type() == QUICFrameType::STREAM); - CHECK(stream->will_generate_frame(level, 0) == false); + CHECK(stream->will_generate_frame(level, 0, false, 0) == false); write_buffer->write(data, 1024); stream->handleEvent(VC_EVENT_WRITE_READY, nullptr); - CHECK(stream->will_generate_frame(level, 0) == true); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); CHECK(frame->type() == QUICFrameType::STREAM); - CHECK(stream->will_generate_frame(level, 0) == false); + CHECK(stream->will_generate_frame(level, 0, false, 0) == false); write_buffer->write(data, 1024); stream->handleEvent(VC_EVENT_WRITE_READY, nullptr); - CHECK(stream->will_generate_frame(level, 0) == true); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); CHECK(frame->type() == QUICFrameType::STREAM); - CHECK(stream->will_generate_frame(level, 0) == false); + CHECK(stream->will_generate_frame(level, 0, false, 0) == false); // This should not send a frame because of flow control write_buffer->write(data, 1024); stream->handleEvent(VC_EVENT_WRITE_READY, nullptr); - CHECK(stream->will_generate_frame(level, 0) == true); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); CHECK(frame); CHECK(frame->type() == QUICFrameType::STREAM_DATA_BLOCKED); - CHECK(stream->will_generate_frame(level, 0) == true); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); // Update window stream->recv(*std::make_shared(stream_id, 5120)); // This should send a frame stream->handleEvent(VC_EVENT_WRITE_READY, nullptr); - CHECK(stream->will_generate_frame(level, 0) == true); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); CHECK(frame->type() == QUICFrameType::STREAM); - CHECK(stream->will_generate_frame(level, 0) == false); + CHECK(stream->will_generate_frame(level, 0, false, 0) == false); // Update window stream->recv(*std::make_shared(stream_id, 5632)); @@ -738,24 +738,24 @@ TEST_CASE("QUIC send only stream", "[quic]") // This should send a frame write_buffer->write(data, 1024); stream->handleEvent(VC_EVENT_WRITE_READY, nullptr); - CHECK(stream->will_generate_frame(level, 0) == true); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); CHECK(frame->type() == QUICFrameType::STREAM); - CHECK(stream->will_generate_frame(level, 0) == true); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); stream->handleEvent(VC_EVENT_WRITE_READY, nullptr); - CHECK(stream->will_generate_frame(level, 0) == true); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); CHECK(frame->type() == QUICFrameType::STREAM_DATA_BLOCKED); // Update window stream->recv(*std::make_shared(stream_id, 6144)); stream->handleEvent(VC_EVENT_WRITE_READY, nullptr); - CHECK(stream->will_generate_frame(level, 0) == true); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); CHECK(frame->type() == QUICFrameType::STREAM); - CHECK(stream->will_generate_frame(level, 0) == false); + CHECK(stream->will_generate_frame(level, 0, false, 0) == false); } /* @@ -786,13 +786,13 @@ TEST_CASE("QUIC send only stream", "[quic]") write_buffer->write(data1, sizeof(data1)); stream->handleEvent(VC_EVENT_WRITE_READY, nullptr); // Generate STREAM frame - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); frame1 = static_cast(frame); CHECK(frame->type() == QUICFrameType::STREAM); - CHECK(stream->generate_frame(frame_buf, level, 4096, 4096, 0) == nullptr); - CHECK(stream->will_generate_frame(level, 0) == false); + CHECK(stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0) == nullptr); + CHECK(stream->will_generate_frame(level, 0, false, 0) == false); stream->on_frame_lost(frame->id()); - CHECK(stream->will_generate_frame(level, 0) == true); + CHECK(stream->will_generate_frame(level, 0, false, 0) == true); // Write data2 write_buffer->write(data2, sizeof(data2)); @@ -800,7 +800,7 @@ TEST_CASE("QUIC send only stream", "[quic]") // Lost the frame stream->on_frame_lost(frame->id()); // Regenerate a frame - frame = stream->generate_frame(frame_buf2, level, 4096, 4096, 0); + frame = stream->generate_frame(frame_buf2, level, 4096, 4096, 0, 0); // Lost data should be resent first frame2 = static_cast(frame); CHECK(frame->type() == QUICFrameType::STREAM); @@ -826,15 +826,15 @@ TEST_CASE("QUIC send only stream", "[quic]") QUICFrame *frame = nullptr; stream->reset(QUICStreamErrorUPtr(new QUICStreamError(stream.get(), QUIC_APP_ERROR_CODE_STOPPING))); - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); REQUIRE(frame); CHECK(frame->type() == QUICFrameType::RESET_STREAM); // Don't send it again untill it is considers as lost - CHECK(stream->generate_frame(frame_buf, level, 4096, 4096, 0) == nullptr); + CHECK(stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0) == nullptr); // Loss the frame stream->on_frame_lost(frame->id()); // After the loss the frame should be regenerated - frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0); + frame = stream->generate_frame(frame_buf, level, 4096, 4096, 0, 0); REQUIRE(frame); CHECK(frame->type() == QUICFrameType::RESET_STREAM); } diff --git a/iocore/net/quic/test/test_QUICStreamManager.cc b/iocore/net/quic/test/test_QUICStreamManager.cc index ced351aba7e..74a37cc2fb1 100644 --- a/iocore/net/quic/test/test_QUICStreamManager.cc +++ b/iocore/net/quic/test/test_QUICStreamManager.cc @@ -247,12 +247,12 @@ TEST_CASE("QUICStreamManager_total_offset_sent", "[quic]") // total_offset should be a integer in unit of octets uint8_t frame_buf[4096]; mock_app.send(reinterpret_cast(block_1024->buf()), 1024, 0); - sm.generate_frame(frame_buf, QUICEncryptionLevel::ONE_RTT, 16384, 16384, 0); + sm.generate_frame(frame_buf, QUICEncryptionLevel::ONE_RTT, 16384, 16384, 0, 0); CHECK(sm.total_offset_sent() == 1024); // total_offset should be a integer in unit of octets mock_app.send(reinterpret_cast(block_1024->buf()), 1024, 4); - sm.generate_frame(frame_buf, QUICEncryptionLevel::ONE_RTT, 16384, 16384, 0); + sm.generate_frame(frame_buf, QUICEncryptionLevel::ONE_RTT, 16384, 16384, 0, 0); CHECK(sm.total_offset_sent() == 2048); // Wait for event processing diff --git a/iocore/net/quic/test/test_QUICTransportParameters.cc b/iocore/net/quic/test/test_QUICTransportParameters.cc index d60e2606790..95fb0ae27bd 100644 --- a/iocore/net/quic/test/test_QUICTransportParameters.cc +++ b/iocore/net/quic/test/test_QUICTransportParameters.cc @@ -167,7 +167,7 @@ TEST_CASE("QUICTransportParametersInEncryptedExtensions_read", "[quic]") CHECK(len == 16); CHECK(memcmp(data, buf + 12, 16) == 0); - CHECK(!params_in_ee.contains(QUICTransportParameterId::DISABLE_MIGRATION)); + CHECK(!params_in_ee.contains(QUICTransportParameterId::DISABLE_ACTIVE_MIGRATION)); } SECTION("OK case - zero length value") @@ -205,7 +205,7 @@ TEST_CASE("QUICTransportParametersInEncryptedExtensions_read", "[quic]") CHECK(len == 2); CHECK(memcmp(data, "\x51\x23", 2) == 0); - CHECK(params_in_ee.contains(QUICTransportParameterId::DISABLE_MIGRATION)); + CHECK(params_in_ee.contains(QUICTransportParameterId::DISABLE_ACTIVE_MIGRATION)); } SECTION("Duplicate parameters") @@ -281,7 +281,7 @@ TEST_CASE("QUICTransportParametersEncryptedExtensions_write", "[quic]") uint16_t max_packet_size = 0x1bcd; params_in_ee.set(QUICTransportParameterId::MAX_PACKET_SIZE, max_packet_size); - params_in_ee.set(QUICTransportParameterId::DISABLE_MIGRATION, nullptr, 0); + params_in_ee.set(QUICTransportParameterId::DISABLE_ACTIVE_MIGRATION, nullptr, 0); params_in_ee.add_version(0x01020304); params_in_ee.add_version(0x05060708); diff --git a/iocore/net/quic/test/test_QUICType.cc b/iocore/net/quic/test/test_QUICType.cc index aff8247fb4c..fb45c44c05d 100644 --- a/iocore/net/quic/test/test_QUICType.cc +++ b/iocore/net/quic/test/test_QUICType.cc @@ -30,6 +30,74 @@ TEST_CASE("QUICType", "[quic]") { + SECTION("QUICPath") + { + IpEndpoint local_a, local_b, remote_a, remote_b; + QUICPath path_a = {{}, {}}, path_b = {{}, {}}; + + // The same addresses and ports -> TRUE + ats_ip_pton("192.168.0.1:4433", &local_a); + ats_ip_pton("192.168.1.1:12345", &remote_a); + ats_ip_pton("192.168.0.1:4433", &local_b); + ats_ip_pton("192.168.1.1:12345", &remote_b); + path_a = {local_a, remote_a}; + path_b = {local_b, remote_b}; + CHECK(path_a == path_b); + CHECK(path_b == path_a); + path_a = {remote_a, local_a}; + path_b = {remote_b, local_b}; + CHECK(path_a == path_b); + CHECK(path_b == path_a); + + // Different ports -> FALSE + ats_ip_pton("192.168.0.1:4433", &local_a); + ats_ip_pton("192.168.1.1:12345", &remote_a); + ats_ip_pton("192.168.0.1:4433", &local_b); + ats_ip_pton("192.168.1.1:54321", &remote_b); + path_a = {local_a, remote_a}; + path_b = {local_b, remote_b}; + CHECK(!(path_a == path_b)); + CHECK(!(path_b == path_a)); + path_a = {remote_a, local_a}; + path_b = {remote_b, local_b}; + CHECK(!(path_a == path_b)); + CHECK(!(path_b == path_a)); + + // Different addresses but the same ports -> FALSE + ats_ip_pton("192.168.0.1:4433", &local_a); + ats_ip_pton("192.168.1.1:12345", &remote_a); + ats_ip_pton("192.168.0.1:4433", &local_b); + ats_ip_pton("192.168.2.1:12345", &remote_b); + path_a = {local_a, remote_a}; + path_b = {local_b, remote_b}; + CHECK(!(path_a == path_b)); + CHECK(!(path_b == path_a)); + path_a = {remote_a, local_a}; + path_b = {remote_b, local_b}; + CHECK(!(path_a == path_b)); + CHECK(!(path_b == path_a)); + + // Server local address is any -> TRUE + ats_ip_pton("0.0.0.0:4433", &local_a); + ats_ip_pton("192.168.1.1:12345", &remote_a); + ats_ip_pton("192.168.0.1:4433", &local_b); + ats_ip_pton("192.168.1.1:12345", &remote_b); + path_a = {local_a, remote_a}; + path_b = {local_b, remote_b}; + CHECK(path_a == path_b); + CHECK(path_b == path_a); + + // Client local address and port are any -> TRUE + ats_ip_pton("0.0.0.0:0", &local_a); + ats_ip_pton("192.168.1.1:12345", &remote_a); + ats_ip_pton("192.168.0.1:4433", &local_b); + ats_ip_pton("192.168.1.1:12345", &remote_b); + path_a = {local_a, remote_a}; + path_b = {local_b, remote_b}; + CHECK(path_a == path_b); + CHECK(path_b == path_a); + } + SECTION("QUICRetryToken") { IpEndpoint ep; diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc index 92adf0f48e9..f983e96f4fc 100644 --- a/mgmt/RecordsConfig.cc +++ b/mgmt/RecordsConfig.cc @@ -1373,7 +1373,7 @@ static const RecordElement RecordsConfig[] = , {RECT_CONFIG, "proxy.config.quic.initial_max_stream_data_uni_in", RECD_INT, "4096", RECU_DYNAMIC, RR_NULL, RECC_STR, "^-?[0-9]+$", RECA_NULL} , - {RECT_CONFIG, "proxy.config.quic.initial_max_stream_data_uni_out", RECD_INT, "0", RECU_DYNAMIC, RR_NULL, RECC_STR, "^-?[0-9]+$", RECA_NULL} + {RECT_CONFIG, "proxy.config.quic.initial_max_stream_data_uni_out", RECD_INT, "4096", RECU_DYNAMIC, RR_NULL, RECC_STR, "^-?[0-9]+$", RECA_NULL} , {RECT_CONFIG, "proxy.config.quic.initial_max_streams_bidi_in", RECD_INT, "100", RECU_DYNAMIC, RR_NULL, RECC_STR, "^-?[0-9]+$", RECA_NULL} , @@ -1391,6 +1391,10 @@ static const RecordElement RecordsConfig[] = , {RECT_CONFIG, "proxy.config.quic.max_ack_delay_out", RECD_INT, "25", RECU_DYNAMIC, RR_NULL, RECC_STR, "^-?[0-9]+$", RECA_NULL} , + {RECT_CONFIG, "proxy.config.quic.active_cid_limit_in", RECD_INT, "4", RECU_DYNAMIC, RR_NULL, RECC_STR, "^-?[0-9]+$", RECA_NULL} + , + {RECT_CONFIG, "proxy.config.quic.active_cid_limit_out", RECD_INT, "8", RECU_DYNAMIC, RR_NULL, RECC_STR, "^-?[0-9]+$", RECA_NULL} + , // Constants of Loss Detection {RECT_CONFIG, "proxy.config.quic.loss_detection.packet_threshold", RECD_INT, "3", RECU_DYNAMIC, RR_NULL, RECC_STR, "^-?[0-9]+$", RECA_NULL} , @@ -1398,7 +1402,7 @@ static const RecordElement RecordsConfig[] = , {RECT_CONFIG, "proxy.config.quic.loss_detection.granularity", RECD_INT, "1", RECU_DYNAMIC, RR_NULL, RECC_STR, "[0-1]", RECA_NULL} , - {RECT_CONFIG, "proxy.config.quic.loss_detection.initial_rtt", RECD_INT, "100", RECU_DYNAMIC, RR_NULL, RECC_STR, "^-?[0-9]+$", RECA_NULL} + {RECT_CONFIG, "proxy.config.quic.loss_detection.initial_rtt", RECD_INT, "500", RECU_DYNAMIC, RR_NULL, RECC_STR, "^-?[0-9]+$", RECA_NULL} , // Constatns of Congestion Control @@ -1410,7 +1414,7 @@ static const RecordElement RecordsConfig[] = , {RECT_CONFIG, "proxy.config.quic.congestion_control.loss_reduction_factor", RECD_FLOAT, "0.5", RECU_DYNAMIC, RR_NULL, RECC_STR, "^-?[\\.0-9]+$", RECA_NULL} , - {RECT_CONFIG, "proxy.config.quic.congestion_control.persistent_congestion_threshold", RECD_INT, "2", RECU_DYNAMIC, RR_NULL, RECC_STR, "^-?[\\.0-9]+$", RECA_NULL} + {RECT_CONFIG, "proxy.config.quic.congestion_control.persistent_congestion_threshold", RECD_INT, "3", RECU_DYNAMIC, RR_NULL, RECC_STR, "^-?[\\.0-9]+$", RECA_NULL} , //# Add LOCAL Records Here diff --git a/proxy/http3/QPACK.h b/proxy/http3/QPACK.h index 85bd7106701..feb106868e4 100644 --- a/proxy/http3/QPACK.h +++ b/proxy/http3/QPACK.h @@ -151,12 +151,12 @@ class QPACK : public QUICApplication { public: DecodeRequest(uint16_t largest_reference, EThread *thread, Continuation *continuation, uint64_t stream_id, - const uint8_t *header_blcok, size_t header_block_len, HTTPHdr &hdr) + const uint8_t *header_block, size_t header_block_len, HTTPHdr &hdr) : _largest_reference(largest_reference), _thread(thread), _continuation(continuation), _stream_id(stream_id), - _header_block(header_blcok), + _header_block(header_block), _header_block_len(header_block_len), _hdr(hdr) { diff --git a/src/traffic_quic/quic_client.cc b/src/traffic_quic/quic_client.cc index 007c20ae3e8..7f3ec64ce34 100644 --- a/src/traffic_quic/quic_client.cc +++ b/src/traffic_quic/quic_client.cc @@ -33,8 +33,8 @@ // https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_alpn_protos.html // Should be integrate with IP_PROTO_TAG_HTTP_QUIC in ts/ink_inet.h ? using namespace std::literals; -static constexpr std::string_view HQ_ALPN_PROTO_LIST("\5hq-20"sv); -static constexpr std::string_view H3_ALPN_PROTO_LIST("\5h3-20"sv); +static constexpr std::string_view HQ_ALPN_PROTO_LIST("\5hq-23"sv); +static constexpr std::string_view H3_ALPN_PROTO_LIST("\5h3-23"sv); QUICClient::QUICClient(const QUICClientConfig *config) : Continuation(new_ProxyMutex()), _config(config) { diff --git a/src/tscore/ink_inet.cc b/src/tscore/ink_inet.cc index 648385070c9..9f36ce9f9a8 100644 --- a/src/tscore/ink_inet.cc +++ b/src/tscore/ink_inet.cc @@ -50,8 +50,8 @@ const std::string_view IP_PROTO_TAG_HTTP_0_9("http/0.9"sv); const std::string_view IP_PROTO_TAG_HTTP_1_0("http/1.0"sv); const std::string_view IP_PROTO_TAG_HTTP_1_1("http/1.1"sv); const std::string_view IP_PROTO_TAG_HTTP_2_0("h2"sv); // HTTP/2 over TLS -const std::string_view IP_PROTO_TAG_HTTP_QUIC("hq-20"sv); // HTTP/0.9 over QUIC -const std::string_view IP_PROTO_TAG_HTTP_3("h3-20"sv); // HTTP/3 over QUIC +const std::string_view IP_PROTO_TAG_HTTP_QUIC("hq-23"sv); // HTTP/0.9 over QUIC +const std::string_view IP_PROTO_TAG_HTTP_3("h3-23"sv); // HTTP/3 over QUIC const std::string_view UNIX_PROTO_TAG{"unix"sv}; From e589e8e15df1033c5fca4c4e038cb773ca8a0285 Mon Sep 17 00:00:00 2001 From: Bryan Call Date: Thu, 3 Oct 2019 11:32:27 -0700 Subject: [PATCH 055/718] Add filename to error message in header_rewrite (cherry picked from commit 32b5dae814310f8b6386638b6024bde4aecedb1b) --- plugins/header_rewrite/header_rewrite.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/header_rewrite/header_rewrite.cc b/plugins/header_rewrite/header_rewrite.cc index 09825449579..b728e420b28 100644 --- a/plugins/header_rewrite/header_rewrite.cc +++ b/plugins/header_rewrite/header_rewrite.cc @@ -236,7 +236,7 @@ RulesConfig::parse_config(const std::string &fname, TSHttpHookID default_hook) } } } catch (std::runtime_error &e) { - TSError("[%s] header_rewrite configuration exception: %s", PLUGIN_NAME, e.what()); + TSError("[%s] header_rewrite configuration exception: %s in file: %s", PLUGIN_NAME, e.what(), fname.c_str()); delete rule; return false; } From e0d70d66dd97713c8183ad8f2d6f035f3fac3d31 Mon Sep 17 00:00:00 2001 From: Fei Deng Date: Thu, 10 Oct 2019 12:18:10 -0500 Subject: [PATCH 056/718] do not schedule stuff during shutdown (cherry picked from commit d970c3787d20ad6c7a0d04bb9ac23988f6fd2962) --- iocore/eventsystem/P_UnixEventProcessor.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/iocore/eventsystem/P_UnixEventProcessor.h b/iocore/eventsystem/P_UnixEventProcessor.h index 8ebf1f95d7d..df4d419ebd5 100644 --- a/iocore/eventsystem/P_UnixEventProcessor.h +++ b/iocore/eventsystem/P_UnixEventProcessor.h @@ -23,6 +23,8 @@ #pragma once +#include + #include "tscore/ink_align.h" #include "I_EventProcessor.h" @@ -91,6 +93,10 @@ EventProcessor::schedule(Event *e, EventType etype, bool fast_signal) { ink_assert(etype < MAX_EVENT_TYPES); + if (TSSystemState::is_event_system_shut_down()) { + return nullptr; + } + EThread *ethread = e->continuation->getThreadAffinity(); if (ethread != nullptr && ethread->is_event_type(etype)) { e->ethread = ethread; From 08ed0619e28f1b2aa396a7adf18792f56aad8409 Mon Sep 17 00:00:00 2001 From: Masakazu Kitajo Date: Fri, 19 Apr 2019 17:06:37 +0900 Subject: [PATCH 057/718] Destroy MIMEFieldBlockImpl that doesn't have fields in use Because MIMEFieldBlocks are destroyed only when MIMEHdr is destroyed, the block chain never be short. With this change, a block will be destroyed when all fields in a block are deleted, and the block will be removed from a block chain. (cherry picked from commit 482e30accbe2e755c73fd1f8dd7e4b2c40705171) --- proxy/hdrs/MIME.cc | 40 +++++++++++++++++++++++++++------------- proxy/hdrs/MIME.h | 3 +++ 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/proxy/hdrs/MIME.cc b/proxy/hdrs/MIME.cc index f37b95df346..9f9c57cee6e 100644 --- a/proxy/hdrs/MIME.cc +++ b/proxy/hdrs/MIME.cc @@ -1639,20 +1639,8 @@ mime_hdr_field_delete(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, bool del { if (delete_all_dups) { while (field) { - // NOTE: we pass zero to field_detach for detach_all_dups - // since this loop will already detach each dup MIMEField *next = field->m_next_dup; - - heap->free_string(field->m_ptr_name, field->m_len_name); - heap->free_string(field->m_ptr_value, field->m_len_value); - - MIME_HDR_SANITY_CHECK(mh); - mime_hdr_field_detach(mh, field, false); - - MIME_HDR_SANITY_CHECK(mh); - mime_field_destroy(mh, field); - - MIME_HDR_SANITY_CHECK(mh); + mime_hdr_field_delete(heap, mh, field, false); field = next; } } else { @@ -1664,6 +1652,32 @@ mime_hdr_field_delete(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, bool del MIME_HDR_SANITY_CHECK(mh); mime_field_destroy(mh, field); + + MIMEFieldBlockImpl *prev_block = nullptr; + bool can_destroy_block = true; + for (auto fblock = &(mh->m_first_fblock); fblock != nullptr; fblock = fblock->m_next) { + if (prev_block != nullptr) { + if (fblock->m_freetop == MIME_FIELD_BLOCK_SLOTS && fblock->contains(field)) { + // Check if fields in all slots are deleted + for (int i = 0; i < MIME_FIELD_BLOCK_SLOTS; ++i) { + if (fblock->m_field_slots[i].m_readiness != MIME_FIELD_SLOT_READINESS_DELETED) { + can_destroy_block = false; + break; + } + } + // Destroy a block and maintain the chain + if (can_destroy_block) { + prev_block->m_next = fblock->m_next; + _mime_field_block_destroy(heap, fblock); + if (prev_block->m_next == nullptr) { + mh->m_fblock_list_tail = prev_block; + } + } + break; + } + } + prev_block = fblock; + } } MIME_HDR_SANITY_CHECK(mh); diff --git a/proxy/hdrs/MIME.h b/proxy/hdrs/MIME.h index ebf1677bc90..75a48f9a90f 100644 --- a/proxy/hdrs/MIME.h +++ b/proxy/hdrs/MIME.h @@ -718,6 +718,9 @@ void mime_hdr_field_attach(MIMEHdrImpl *mh, MIMEField *field, int check_for_dups void mime_hdr_field_detach(MIMEHdrImpl *mh, MIMEField *field, bool detach_all_dups = false); void mime_hdr_field_delete(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, bool delete_all_dups = false); +/** + * Returned slotnum is not a persistent value. A slotnum may refer a different field after making changes to a mime header. + */ int mime_hdr_field_slotnum(MIMEHdrImpl *mh, MIMEField *field); inkcoreapi MIMEField *mime_hdr_prepare_for_value_set(HdrHeap *heap, MIMEHdrImpl *mh, const char *name, int name_length); From 1f5b382a99d1bf092b92a2a68b3506c57eaedf32 Mon Sep 17 00:00:00 2001 From: Masakazu Kitajo Date: Thu, 26 Sep 2019 15:08:47 +0900 Subject: [PATCH 058/718] Fix a build issue on enabling FIPS (cherry picked from commit 526efb0a22a2018ee79ac4851f5e392a47acbd37) --- src/tscore/unit_tests/test_BufferWriterFormat.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/tscore/unit_tests/test_BufferWriterFormat.cc b/src/tscore/unit_tests/test_BufferWriterFormat.cc index a3ef870720d..90f95d899ea 100644 --- a/src/tscore/unit_tests/test_BufferWriterFormat.cc +++ b/src/tscore/unit_tests/test_BufferWriterFormat.cc @@ -29,7 +29,10 @@ #include "tscore/BufferWriter.h" #include "tscore/bwf_std_format.h" #include "tscpp/util/MemSpan.h" +#include "tscore/ink_config.h" +#if TS_ENABLE_FIPS == 0 #include "tscore/INK_MD5.h" +#endif #include "tscore/CryptoHash.h" using namespace std::literals; @@ -252,6 +255,7 @@ TEST_CASE("BWFormat numerics", "[bwprint][bwformat]") bw20.print("012345|{:^10s}|6789abc", true); REQUIRE(bw20.view() == "012345| true |67"); +#if TS_ENABLE_FIPS == 0 INK_MD5 md5; bw.reduce(0); bw.print("{}", md5); @@ -260,6 +264,7 @@ TEST_CASE("BWFormat numerics", "[bwprint][bwformat]") bw.reduce(0); bw.print("{}", md5); REQUIRE(bw.view() == "e99a18c428cb38d5f260853678922e03"); +#endif bw.reset().print("Char '{}'", 'a'); REQUIRE(bw.view() == "Char 'a'"); @@ -594,12 +599,14 @@ TEST_CASE("bwstring std formats", "[libts][bwprint]") w.reset().print("{} bytes {} digits {}", sizeof(double), std::numeric_limits::digits10, ts::bwf::Hex_Dump(2.718281828)); REQUIRE(w.view() == "8 bytes 15 digits 9b91048b0abf0540"); +#if TS_ENABLE_FIPS == 0 INK_MD5 md5; w.reset().print("{}", ts::bwf::Hex_Dump(md5)); REQUIRE(w.view() == "00000000000000000000000000000000"); CryptoContext().hash_immediate(md5, s2.data(), s2.size()); w.reset().print("{}", ts::bwf::Hex_Dump(md5)); REQUIRE(w.view() == "f240ccd7a95c7ec66d6c111e2925b23e"); +#endif } // Normally there's no point in running the performance tests, but it's worth keeping the code From 3a2740df9993c3d564d6b7759123a8845f8e9458 Mon Sep 17 00:00:00 2001 From: Evan Zelkowitz <19699200+ezelkow1@users.noreply.github.com> Date: Fri, 27 Sep 2019 13:24:47 -0600 Subject: [PATCH 059/718] Change the ready checks for ats to use the actual ats port and not the server port. Add ready check on server port for the server (cherry picked from commit 29b1dc90e276813dd1b62cde881bb8f806065eaa) --- tests/gold_tests/headers/syntax.test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/gold_tests/headers/syntax.test.py b/tests/gold_tests/headers/syntax.test.py index c10ab02e629..dbaacb984e7 100644 --- a/tests/gold_tests/headers/syntax.test.py +++ b/tests/gold_tests/headers/syntax.test.py @@ -40,8 +40,8 @@ # Test 1 - 200 Response tr = Test.AddTestRun() -tr.Processes.Default.StartBefore(server) -tr.Processes.Default.StartBefore(Test.Processes.ts, ready=When.PortOpen(server.Variables.Port)) +tr.Processes.Default.StartBefore(server, ready=When.PortOpen(server.Variables.Port)) +tr.Processes.Default.StartBefore(Test.Processes.ts, ready=When.PortOpen(ts.Variables.port)) tr.Processes.Default.Command = 'curl -s -D - -v --ipv4 --http1.1 -H " foo: bar" -H "Host: www.example.com" http://localhost:{0}/'.format(ts.Variables.port) tr.Processes.Default.ReturnCode = 0 tr.Processes.Default.Streams.stdout = "syntax.200.gold" From 582c8cbada501df7f27a718e4ba616574655c6c8 Mon Sep 17 00:00:00 2001 From: xinli1 Date: Wed, 14 Aug 2019 22:17:44 -0700 Subject: [PATCH 060/718] log filter enhancement fix the bug if filter word included in param value (cherry picked from commit d3ed0276545774d989d050fe57fdf7dd3877b49c) fix the bug if filter word included in param value (cherry picked from commit 601d090b07f64a90cbf11bf55d6c1fad83f34f2d) fix typo issue (cherry picked from commit 16ddd19307dc8a04a05bf5cbe8afedd00c538019) move code to utility function to reduce the interface size (cherry picked from commit 89bed7bcbc5b57652f9392b1905908d993483674) code clean from review comments (cherry picked from commit ca24696ab407f532cb090a0abd40c1a5edb99d40) 1) add autest for log filter; 2) support filter for duplicated param name in query parm of URL (cherry picked from commit 87db2452595ccbc2498a5eecc31dc9d2a67be62c) --- proxy/logging/LogFilter.h | 111 +++++++++++----- .../gold_tests/logging/gold/filter-test.gold | 5 + tests/gold_tests/logging/log-filter.test.py | 124 ++++++++++++++++++ 3 files changed, 208 insertions(+), 32 deletions(-) create mode 100644 tests/gold_tests/logging/gold/filter-test.gold create mode 100644 tests/gold_tests/logging/log-filter.test.py diff --git a/proxy/logging/LogFilter.h b/proxy/logging/LogFilter.h index 1cb55fead46..083dc08e6f0 100644 --- a/proxy/logging/LogFilter.h +++ b/proxy/logging/LogFilter.h @@ -382,6 +382,72 @@ LogFilterString::_checkCondition(OperatorFunction f, const char *field_value, si return retVal; } +/*--------------------------------------------------------------------------- + * find pattern from the query param + * 1) if pattern is not in the query param, return nullptr + * 2) if got the pattern in one param's value, search again until it's in one param name, or nullptr if can't find it from param +name +---------------------------------------------------------------------------*/ +static const char * +findPatternFromParamName(const char *lookup_query_param, const char *pattern) +{ + const char *pattern_in_query_param = strstr(lookup_query_param, pattern); + while (pattern_in_query_param) { + // wipe pattern in param name, need to search again if find pattern in param value + const char *param_value_str = strchr(pattern_in_query_param, '='); + if (!param_value_str) { + // no "=" after pattern_in_query_param, means pattern_in_query_param is not in the param name, and no more param after it + pattern_in_query_param = nullptr; + break; + } + const char *param_name_str = strchr(pattern_in_query_param, '&'); + if (param_name_str && param_value_str > param_name_str) { + //"=" is after "&" followd by pattern_in_query_param, means pattern_in_query_param is not in the param name + pattern_in_query_param = strstr(param_name_str, pattern); + continue; + } + // ensure pattern_in_query_param is in the param name now + break; + } + return pattern_in_query_param; +} + +/*--------------------------------------------------------------------------- + * replace param value whose name contains pattern with same count 'X' of original value str length +---------------------------------------------------------------------------*/ +static void +updatePatternForFieldValue(char **field, const char *pattern_str, int field_pos, char *buf_dest) +{ + int buf_dest_len = strlen(buf_dest); + char buf_dest_to_field[buf_dest_len + 1]; + char *temp_text = buf_dest_to_field; + memcpy(temp_text, buf_dest, (pattern_str - buf_dest)); + temp_text += (pattern_str - buf_dest); + const char *value_str = strchr(pattern_str, '='); + if (value_str) { + value_str++; + memcpy(temp_text, pattern_str, (value_str - pattern_str)); + temp_text += (value_str - pattern_str); + const char *next_param_str = strchr(value_str, '&'); + if (next_param_str) { + for (int i = 0; i < (next_param_str - value_str); i++) { + temp_text[i] = 'X'; + } + temp_text += (next_param_str - value_str); + memcpy(temp_text, next_param_str, ((buf_dest + buf_dest_len) - next_param_str)); + } else { + for (int i = 0; i < ((buf_dest + buf_dest_len) - value_str); i++) { + temp_text[i] = 'X'; + } + } + } else { + return; + } + + buf_dest_to_field[buf_dest_len] = '\0'; + strcpy(*field, buf_dest_to_field); +} + /*--------------------------------------------------------------------------- wipeField : Given a dest buffer, wipe the first occurrence of the value of the field in the buffer. @@ -394,44 +460,25 @@ wipeField(char **field, char *pattern, const char *uppercase_field) const char *lookup_dest = uppercase_field ? uppercase_field : *field; if (buf_dest) { - char *query_param = strstr(buf_dest, "?"); - const char *lookup_query_param = strstr(lookup_dest, "?"); + char *query_param = strchr(buf_dest, '?'); + const char *lookup_query_param = strchr(lookup_dest, '?'); if (!query_param || !lookup_query_param) { return; } - const char *p1 = strstr(lookup_query_param, pattern); - int field_pos = p1 - lookup_query_param; - p1 = query_param + field_pos; - - if (p1) { - char tmp_text[strlen(buf_dest) + 10]; - char *temp_text = tmp_text; - memcpy(temp_text, buf_dest, (p1 - buf_dest)); - temp_text += (p1 - buf_dest); - const char *p2 = strstr(p1, "="); - if (p2) { - p2++; - memcpy(temp_text, p1, (p2 - p1)); - temp_text += (p2 - p1); - const char *p3 = strstr(p2, "&"); - if (p3) { - for (int i = 0; i < (p3 - p2); i++) { - temp_text[i] = 'X'; - } - temp_text += (p3 - p2); - memcpy(temp_text, p3, ((buf_dest + strlen(buf_dest)) - p3)); - } else { - for (int i = 0; i < ((buf_dest + strlen(buf_dest)) - p2); i++) { - temp_text[i] = 'X'; - } - } + const char *pattern_in_param_name = findPatternFromParamName(lookup_query_param, pattern); + while (pattern_in_param_name) { + int field_pos = pattern_in_param_name - lookup_query_param; + pattern_in_param_name = query_param + field_pos; + updatePatternForFieldValue(field, pattern_in_param_name, field_pos, buf_dest); + + // search new param again + const char *new_param = strchr(lookup_query_param + field_pos, '&'); + if (new_param && (new_param + 1)) { + pattern_in_param_name = findPatternFromParamName(new_param + 1, pattern); } else { - return; + break; } - - tmp_text[strlen(buf_dest)] = '\0'; - strcpy(*field, tmp_text); } } } diff --git a/tests/gold_tests/logging/gold/filter-test.gold b/tests/gold_tests/logging/gold/filter-test.gold new file mode 100644 index 00000000000..9dc6586efdf --- /dev/null +++ b/tests/gold_tests/logging/gold/filter-test.gold @@ -0,0 +1,5 @@ +http://test-1/test-1?name=value&email=XXXXXXXXXXXXX +http://test-2/test-2?email=XXXXXXXXXXXXX&name=password +http://test-3/test-3?trivial=password&name1=val1&email=XXXXXXXXXXXXX +http://test-4/test-4?trivial=password&email=&name=handle&session_redirect=XXXXXXXXXXXX +http://test-5/test-5?trivial=password&email=XXXXXXXXXXXXX&email=XXXXXXXXXXXXX&session_redirect=XXXXXXXXXXXX&email=XXXXXXXXXXXXX&name=value diff --git a/tests/gold_tests/logging/log-filter.test.py b/tests/gold_tests/logging/log-filter.test.py new file mode 100644 index 00000000000..784fee27ec8 --- /dev/null +++ b/tests/gold_tests/logging/log-filter.test.py @@ -0,0 +1,124 @@ +''' +''' +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os + +Test.Summary = ''' +Test log filter. +''' +# Only on Linux (why??) +Test.SkipUnless( + Condition.IsPlatform("linux") +) + +# Define default ATS +ts = Test.MakeATSProcess("ts") +# Microserver +server = Test.MakeOriginServer("server") + +request_header = {'timestamp': 100, "headers": "GET /test-1 HTTP/1.1\r\nHost: test-1\r\n\r\n", "body": ""} +response_header = {'timestamp': 100, + "headers": "HTTP/1.1 200 OK\r\nTest: 1\r\nContent-Type: application/json\r\nConnection: close\r\nContent-Type: application/json\r\n\r\n", "body": "Test 1"} +server.addResponse("sessionlog.json", request_header, response_header) +server.addResponse("sessionlog.json", + {'timestamp': 101, "headers": "GET /test-2 HTTP/1.1\r\nHost: test-2\r\n\r\n", "body": ""}, + {'timestamp': 101, "headers": "HTTP/1.1 200 OK\r\nTest: 2\r\nContent-Type: application/jason\r\nConnection: close\r\nContent-Type: application/json\r\n\r\n", "body": "Test 2"} + ) +server.addResponse("sessionlog.json", + {'timestamp': 102, "headers": "GET /test-3 HTTP/1.1\r\nHost: test-3\r\n\r\n", "body": ""}, + {'timestamp': 102, "headers": "HTTP/1.1 200 OK\r\nTest: 3\r\nConnection: close\r\nContent-Type: application/json\r\n\r\n", "body": "Test 3"} + ) +server.addResponse("sessionlog.json", + {'timestamp': 103, "headers": "GET /test-4 HTTP/1.1\r\nHost: test-4\r\n\r\n", "body": ""}, + {'timestamp': 103, "headers": "HTTP/1.1 200 OK\r\nTest: 4\r\nConnection: close\r\nContent-Type: application/json\r\n\r\n", "body": "Test 4"} + ) +server.addResponse("sessionlog.json", + {'timestamp': 104, "headers": "GET /test-5 HTTP/1.1\r\nHost: test-5\r\n\r\n", "body": ""}, + {'timestamp': 104, "headers": "HTTP/1.1 200 OK\r\nTest: 5\r\nConnection: close\r\nContent-Type: application/json\r\n\r\n", "body": "Test 5"} + ) + +ts.Disk.records_config.update({ + 'proxy.config.net.connections_throttle': 100, + 'proxy.config.http.cache.http': 0 +}) +# setup some config file for this server +ts.Disk.remap_config.AddLine( + 'map / http://localhost:{}/'.format(server.Variables.Port) +) + +ts.Disk.logging_yaml.AddLines( + ''' +logging: + filters: + - name: queryparamescaper_cquuc + action: WIPE_FIELD_VALUE + condition: cquuc CASE_INSENSITIVE_CONTAIN password,secret,access_token,session_redirect,cardNumber,code,query,search-query,prefix,keywords,email,handle + formats: + - name: custom + format: '%' + logs: + - filename: filter-test + format: custom + filters: + - queryparamescaper_cquuc +'''.split("\n") +) + +# ######################################################################### +# at the end of the different test run a custom log file should exist +# Because of this we expect the testruns to pass the real test is if the +# customlog file exists and passes the format check +Test.Disk.File(os.path.join(ts.Variables.LOGDIR, 'filter-test.log'), + exists=True, content='gold/filter-test.gold') + +# first test is a miss for default +tr = Test.AddTestRun() +# Wait for the micro server +tr.Processes.Default.StartBefore(server) +# Delay on readiness of our ssl ports +tr.Processes.Default.StartBefore(Test.Processes.ts) + +tr.Processes.Default.Command = 'curl --verbose --header "Host: test-1" "http://localhost:{0}/test-1?name=value&email=123@gmail.com"' .format( + ts.Variables.port) +tr.Processes.Default.ReturnCode = 0 + +tr = Test.AddTestRun() +tr.Processes.Default.Command = 'curl --verbose --header "Host: test-2" "http://localhost:{0}/test-2?email=123@gmail.com&name=password"' .format( + ts.Variables.port) +tr.Processes.Default.ReturnCode = 0 + +tr = Test.AddTestRun() +tr.Processes.Default.Command = 'curl --verbose --header "Host: test-3" "http://localhost:{0}/test-3?trivial=password&name1=val1&email=123@gmail.com"' .format( + ts.Variables.port) +tr.Processes.Default.ReturnCode = 0 + +tr = Test.AddTestRun() +tr.Processes.Default.Command = 'curl --verbose --header "Host: test-4" "http://localhost:{0}/test-4?trivial=password&email=&name=handle&session_redirect=wiped_string"' .format( + ts.Variables.port) +tr.Processes.Default.ReturnCode = 0 + +tr = Test.AddTestRun() +tr.Processes.Default.Command = 'curl --verbose --header "Host: test-5" "http://localhost:{0}/test-5?trivial=password&email=123@gmail.com&email=456@gmail.com&session_redirect=wiped_string&email=789@gmail.com&name=value"' .format( + ts.Variables.port) +tr.Processes.Default.ReturnCode = 0 + +tr = Test.AddTestRun() +tr.DelayStart = 10 +tr.Processes.Default.Command = 'echo "Delay for log flush"' +tr.Processes.Default.ReturnCode = 0 + From c5b3203dc79363550db15e800b5189fc47784610 Mon Sep 17 00:00:00 2001 From: Eric Schwartz Date: Thu, 22 Aug 2019 14:36:44 +0000 Subject: [PATCH 061/718] pipe buffer size for log.pipe should be configurable Conflicts: proxy/logging/YamlLogConfig.cc (cherry picked from commit 45592cff2f8e424f87c80059a62befdbfdd06633) --- proxy/logging/LogFile.cc | 28 ++++++++++++++++++++++++++-- proxy/logging/LogFile.h | 3 ++- proxy/logging/LogObject.cc | 12 ++++++++---- proxy/logging/LogObject.h | 5 ++++- proxy/logging/YamlLogConfig.cc | 23 +++++++++++++++++------ 5 files changed, 57 insertions(+), 14 deletions(-) diff --git a/proxy/logging/LogFile.cc b/proxy/logging/LogFile.cc index c0928beb6b7..c9e911c0723 100644 --- a/proxy/logging/LogFile.cc +++ b/proxy/logging/LogFile.cc @@ -63,12 +63,13 @@ -------------------------------------------------------------------------*/ LogFile::LogFile(const char *name, const char *header, LogFileFormat format, uint64_t signature, size_t ascii_buffer_size, - size_t max_line_size) + size_t max_line_size, int pipe_buffer_size) : m_file_format(format), m_name(ats_strdup(name)), m_header(ats_strdup(header)), m_signature(signature), - m_max_line_size(max_line_size) + m_max_line_size(max_line_size), + m_pipe_buffer_size(pipe_buffer_size) { if (m_file_format != LOG_FILE_PIPE) { m_log = new BaseLogFile(name, m_signature); @@ -97,6 +98,7 @@ LogFile::LogFile(const LogFile ©) m_signature(copy.m_signature), m_ascii_buffer_size(copy.m_ascii_buffer_size), m_max_line_size(copy.m_max_line_size), + m_pipe_buffer_size(copy.m_pipe_buffer_size), m_fd(copy.m_fd) { ink_release_assert(m_ascii_buffer_size >= m_max_line_size); @@ -185,6 +187,28 @@ LogFile::open_file() Debug("log-file", "no readers for pipe %s", m_name); return LOG_FILE_NO_PIPE_READERS; } + + // adjust pipe size if necessary + if (m_pipe_buffer_size) { + long pipe_size = (long)fcntl(m_fd, F_GETPIPE_SZ); + if (pipe_size == -1) { + Error("get pipe size failed for pipe %s", m_name); + } else { + Debug("log-file", "Default pipe size for pipe %s = %ld", m_name, pipe_size); + } + + int ret = fcntl(m_fd, F_SETPIPE_SZ, m_pipe_buffer_size); + if (ret == -1) { + Error("set pipe size failed for pipe %s", m_name); + } + + pipe_size = (long)fcntl(m_fd, F_GETPIPE_SZ); + if (pipe_size == -1) { + Error("get pipe size failed for pipe %s", m_name); + } else { + Debug("log-file", "NEW pipe size for pipe %s = %ld", m_name, pipe_size); + } + } } else { if (m_log) { int status = m_log->open_file(Log::config->logfile_perm); diff --git a/proxy/logging/LogFile.h b/proxy/logging/LogFile.h index 4f2fd65853d..1a9a7f1ee8c 100644 --- a/proxy/logging/LogFile.h +++ b/proxy/logging/LogFile.h @@ -43,7 +43,7 @@ class LogFile : public LogBufferSink, public RefCountObj { public: LogFile(const char *name, const char *header, LogFileFormat format, uint64_t signature, size_t ascii_buffer_size = 4 * 9216, - size_t max_line_size = 9216); + size_t max_line_size = 9216, int pipe_buffer_size = 0); LogFile(const LogFile &); ~LogFile() override; @@ -120,6 +120,7 @@ class LogFile : public LogBufferSink, public RefCountObj uint64_t m_signature; // signature of log object stored size_t m_ascii_buffer_size; // size of ascii buffer size_t m_max_line_size; // size of longest log line (record) + int m_pipe_buffer_size; // this is the size of the pipe buffer set by fcntl int m_fd; // this could back m_log or a pipe, depending on the situation public: diff --git a/proxy/logging/LogObject.cc b/proxy/logging/LogObject.cc index 8032dbdd296..f1c2337b01d 100644 --- a/proxy/logging/LogObject.cc +++ b/proxy/logging/LogObject.cc @@ -90,7 +90,8 @@ LogBufferManager::preproc_buffers(LogBufferSink *sink) LogObject::LogObject(const LogFormat *format, const char *log_dir, const char *basename, LogFileFormat file_format, const char *header, Log::RollingEnabledValues rolling_enabled, int flush_threads, int rolling_interval_sec, - int rolling_offset_hr, int rolling_size_mb, bool auto_created, int max_rolled, bool reopen_after_rolling) + int rolling_offset_hr, int rolling_size_mb, bool auto_created, int max_rolled, bool reopen_after_rolling, + int pipe_buffer_size) : m_alt_filename(nullptr), m_flags(0), m_signature(0), @@ -101,7 +102,8 @@ LogObject::LogObject(const LogFormat *format, const char *log_dir, const char *b m_last_roll_time(0), m_max_rolled(max_rolled), m_reopen_after_rolling(reopen_after_rolling), - m_buffer_manager_idx(0) + m_buffer_manager_idx(0), + m_pipe_buffer_size(pipe_buffer_size) { ink_release_assert(format); m_format = new LogFormat(*format); @@ -118,7 +120,8 @@ LogObject::LogObject(const LogFormat *format, const char *log_dir, const char *b // compute_signature is a static function m_signature = compute_signature(m_format, m_basename, m_flags); - m_logFile = new LogFile(m_filename, header, file_format, m_signature, Log::config->ascii_buffer_size, Log::config->max_line_size); + m_logFile = new LogFile(m_filename, header, file_format, m_signature, Log::config->ascii_buffer_size, Log::config->max_line_size, + m_pipe_buffer_size); if (m_reopen_after_rolling) { m_logFile->open_file(); @@ -148,7 +151,8 @@ LogObject::LogObject(LogObject &rhs) m_last_roll_time(rhs.m_last_roll_time), m_max_rolled(rhs.m_max_rolled), m_reopen_after_rolling(rhs.m_reopen_after_rolling), - m_buffer_manager_idx(rhs.m_buffer_manager_idx) + m_buffer_manager_idx(rhs.m_buffer_manager_idx), + m_pipe_buffer_size(rhs.m_pipe_buffer_size) { m_format = new LogFormat(*(rhs.m_format)); m_buffer_manager = new LogBufferManager[m_flush_threads]; diff --git a/proxy/logging/LogObject.h b/proxy/logging/LogObject.h index fcf604662f5..32dafb1f3d4 100644 --- a/proxy/logging/LogObject.h +++ b/proxy/logging/LogObject.h @@ -95,7 +95,8 @@ class LogObject : public RefCountObj LogObject(const LogFormat *format, const char *log_dir, const char *basename, LogFileFormat file_format, const char *header, Log::RollingEnabledValues rolling_enabled, int flush_threads, int rolling_interval_sec = 0, int rolling_offset_hr = 0, - int rolling_size_mb = 0, bool auto_created = false, int rolling_max_count = 0, bool reopen_after_rolling = false); + int rolling_size_mb = 0, bool auto_created = false, int rolling_max_count = 0, bool reopen_after_rolling = false, + int pipe_buffer_size = 0); LogObject(LogObject &); ~LogObject() override; @@ -285,6 +286,8 @@ class LogObject : public RefCountObj unsigned m_buffer_manager_idx; LogBufferManager *m_buffer_manager; + int m_pipe_buffer_size; + void generate_filenames(const char *log_dir, const char *basename, LogFileFormat file_format); void _setup_rolling(Log::RollingEnabledValues rolling_enabled, int rolling_interval_sec, int rolling_offset_hr, int rolling_size_mb); diff --git a/proxy/logging/YamlLogConfig.cc b/proxy/logging/YamlLogConfig.cc index 985f0aa0f61..ec44d1a3aa3 100644 --- a/proxy/logging/YamlLogConfig.cc +++ b/proxy/logging/YamlLogConfig.cc @@ -111,7 +111,8 @@ TsEnumDescriptor ROLLING_MODE_LUA = { std::set valid_log_object_keys = { "filename", "format", "mode", "header", "rolling_enabled", "rolling_interval_sec", - "rolling_offset_hr", "rolling_size_mb", "filters", "min_count", "rolling_max_count", "rolling_allow_empty"}; + "rolling_offset_hr", "rolling_size_mb", "filters", "min_count", "rolling_max_count", "rolling_allow_empty", + "pipe_buffer_size"}; LogObject * YamlLogConfig::decodeLogObject(const YAML::Node &node) @@ -196,11 +197,21 @@ YamlLogConfig::decodeLogObject(const YAML::Node &node) Warning("Invalid log rolling value '%d' in log object", obj_rolling_enabled); } - auto logObject = - new LogObject(fmt, Log::config->logfile_dir, filename.c_str(), file_type, header.c_str(), - static_cast(obj_rolling_enabled), Log::config->preproc_threads, - obj_rolling_interval_sec, obj_rolling_offset_hr, obj_rolling_size_mb, /* auto_created */ false, - /* rolling_max_count */ obj_rolling_max_count, /* reopen_after_rolling */ obj_rolling_allow_empty > 0); + // get buffer for pipe + int pipe_buffer_size = 0; + if (node["pipe_buffer_size"]) { + if (file_type != LOG_FILE_PIPE) { + Warning("Pipe buffer size field should only be set for log.pipe object."); + } else { + pipe_buffer_size = node["pipe_buffer_size"].as(); + } + } + + auto logObject = new LogObject(fmt, Log::config->logfile_dir, filename.c_str(), file_type, header.c_str(), + static_cast(obj_rolling_enabled), Log::config->preproc_threads, + obj_rolling_interval_sec, obj_rolling_offset_hr, obj_rolling_size_mb, /* auto_created */ false, + /* rolling_max_count */ obj_rolling_max_count, + /* reopen_after_rolling */ obj_rolling_allow_empty > 0, pipe_buffer_size); // Generate LogDeletingInfo entry for later use std::string ext; From 91fb9b7447bd723b9a70d3c22f4624f547803fe5 Mon Sep 17 00:00:00 2001 From: Eric Schwartz Date: Tue, 27 Aug 2019 20:50:40 +0000 Subject: [PATCH 062/718] address review comments (cherry picked from commit 8e4776c24e58e9bf41a6040a3aad71fd64e3a1ef) --- doc/admin-guide/logging/destinations.en.rst | 3 +++ doc/admin-guide/logging/examples.en.rst | 20 ++++++++++++++++++++ proxy/logging/LogFile.cc | 4 ++++ 3 files changed, 27 insertions(+) diff --git a/doc/admin-guide/logging/destinations.en.rst b/doc/admin-guide/logging/destinations.en.rst index 5b70913ad64..03b6f75fb91 100644 --- a/doc/admin-guide/logging/destinations.en.rst +++ b/doc/admin-guide/logging/destinations.en.rst @@ -109,6 +109,9 @@ pipe, only full records are dropped. Output to named pipes is always, as the mode's name implies, in ASCII format. There is no option for logging binary format log data to a named pipe. +For ASCII pipes there exists an option to set the ``pipe_buffer_size`` in +the YAML config. + .. _admin-logging-ascii-v-binary: Deciding Between ASCII or Binary Output diff --git a/doc/admin-guide/logging/examples.en.rst b/doc/admin-guide/logging/examples.en.rst index 4cca17e9d38..f1d08409ec8 100644 --- a/doc/admin-guide/logging/examples.en.rst +++ b/doc/admin-guide/logging/examples.en.rst @@ -299,6 +299,26 @@ for them to a UNIX pipe that the alerting software can constantly read from. - canaryfilter filename: alerting_canaries +Configuring ASCII Pipe Buffer Size +================================== + +This example mirrors the one above but also sets a ```pipe_buffer_size``` of +1024 * 1024 for the pipe. This can be set on a per-pipe basis but is not +available on FreeBSD dists of ATS. If this field is not set, the pipe buffer +will default to the OS default size. + +.. code:: yaml + + logs: + - mode: pipe + format: canaryformat + filters: + - canaryfilter + filename: alerting_canaries + pipe_buffer_size: 1048576 + + + Summarizing Origin Responses by Hour ==================================== diff --git a/proxy/logging/LogFile.cc b/proxy/logging/LogFile.cc index c9e911c0723..41543298dce 100644 --- a/proxy/logging/LogFile.cc +++ b/proxy/logging/LogFile.cc @@ -188,6 +188,9 @@ LogFile::open_file() return LOG_FILE_NO_PIPE_READERS; } +#ifdef __FreeBSD__ + // we don't do this for FreeBSD +#else // adjust pipe size if necessary if (m_pipe_buffer_size) { long pipe_size = (long)fcntl(m_fd, F_GETPIPE_SZ); @@ -209,6 +212,7 @@ LogFile::open_file() Debug("log-file", "NEW pipe size for pipe %s = %ld", m_name, pipe_size); } } +#endif } else { if (m_log) { int status = m_log->open_file(Log::config->logfile_perm); From e2bce63311122e3e317f175ab7cd87c99e9fa86c Mon Sep 17 00:00:00 2001 From: Valentin Gutierrez Date: Fri, 27 Sep 2019 10:01:55 +0000 Subject: [PATCH 063/718] Cache SSL EC explicitly (cherry picked from commit 757256129811441f29eea288b1d7e19bc54fab9c) --- iocore/net/P_SSLNetVConnection.h | 28 ++++++++++++++++++++-------- iocore/net/P_SSLUtils.h | 9 +++++++++ iocore/net/SSLNetVConnection.cc | 9 +++++++++ iocore/net/SSLSessionCache.cc | 27 +++++++++++++++++++-------- iocore/net/SSLSessionCache.h | 17 +++++++++++------ iocore/net/SSLUtils.cc | 20 +++++++++++++++++--- src/traffic_server/InkAPI.cc | 7 ++++--- 7 files changed, 89 insertions(+), 28 deletions(-) diff --git a/iocore/net/P_SSLNetVConnection.h b/iocore/net/P_SSLNetVConnection.h index 0dae517ff7b..3b014050777 100644 --- a/iocore/net/P_SSLNetVConnection.h +++ b/iocore/net/P_SSLNetVConnection.h @@ -43,6 +43,7 @@ #include "P_UnixNetVConnection.h" #include "P_UnixNet.h" #include "P_ALPNSupport.h" +#include "P_SSLUtils.h" // These are included here because older OpenSSL libraries don't have them. // Don't copy these defines, or use their values directly, they are merely @@ -302,26 +303,35 @@ class SSLNetVConnection : public UnixNetVConnection, public ALPNSupport return ssl ? SSL_get_cipher_name(ssl) : nullptr; } + void + setSSLCurveNID(ssl_curve_id curve_nid) + { + sslCurveNID = curve_nid; + } + + ssl_curve_id + getSSLCurveNID() const + { + return sslCurveNID; + } + const char * getSSLCurve() const { if (!ssl) { return nullptr; } - + ssl_curve_id curve = getSSLCurveNID(); #ifndef OPENSSL_IS_BORINGSSL - int curve_nid = SSL_get_shared_curve(ssl, 0); - - if (curve_nid == NID_undef) { + if (curve == NID_undef) { return nullptr; } - return OBJ_nid2sn(curve_nid); + return OBJ_nid2sn(curve); #else - if (uint16_t curve_id = SSL_get_curve_id(ssl); curve_id != 0) { - return SSL_get_curve_name(curve_id); - } else { + if (curve == 0) { return nullptr; } + return SSL_get_curve_name(curve); #endif } @@ -418,6 +428,7 @@ class SSLNetVConnection : public UnixNetVConnection, public ALPNSupport std::string_view map_tls_protocol_to_tag(const char *proto_string) const; bool update_rbio(bool move_to_socket); void increment_ssl_version_metric(int version) const; + void fetch_ssl_curve(); enum SSLHandshakeStatus sslHandshakeStatus = SSL_HANDSHAKE_ONGOING; bool sslClientRenegotiationAbort = false; @@ -426,6 +437,7 @@ class SSLNetVConnection : public UnixNetVConnection, public ALPNSupport IOBufferReader *handShakeHolder = nullptr; IOBufferReader *handShakeReader = nullptr; int handShakeBioStored = 0; + int sslCurveNID = NID_undef; bool transparentPassThrough = false; diff --git a/iocore/net/P_SSLUtils.h b/iocore/net/P_SSLUtils.h index 19f6bc1008d..da85e1aa36a 100644 --- a/iocore/net/P_SSLUtils.h +++ b/iocore/net/P_SSLUtils.h @@ -39,6 +39,15 @@ class SSLNetVConnection; typedef int ssl_error_t; +#ifndef OPENSSL_IS_BORING +typedef int ssl_curve_id; +#else +typedef uint16_t ssl_curve_id; +#endif + +// Return the SSL Curve ID associated to the specified SSL connection +ssl_curve_id SSLGetCurveNID(SSL *ssl); + /** @brief Load SSL certificates from ssl_multicert.config and setup SSLCertLookup for SSLCertificateConfig */ diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc index aacfb05649b..a29f1b241dc 100644 --- a/iocore/net/SSLNetVConnection.cc +++ b/iocore/net/SSLNetVConnection.cc @@ -1255,6 +1255,7 @@ SSLNetVConnection::sslServerHandShakeEvent(int &err) unsigned len = 0; increment_ssl_version_metric(SSL_version(ssl)); + fetch_ssl_curve(); // If it's possible to negotiate both NPN and ALPN, then ALPN // is preferred since it is the server's preference. The server @@ -1806,6 +1807,14 @@ SSLNetVConnection::increment_ssl_version_metric(int version) const } } +void +SSLNetVConnection::fetch_ssl_curve() +{ + if (!getSSLSessionCacheHit()) { + setSSLCurveNID(SSLGetCurveNID(ssl)); + } +} + std::string_view SSLNetVConnection::map_tls_protocol_to_tag(const char *proto_string) const { diff --git a/iocore/net/SSLSessionCache.cc b/iocore/net/SSLSessionCache.cc index 8c803892016..611b4c8b70f 100644 --- a/iocore/net/SSLSessionCache.cc +++ b/iocore/net/SSLSessionCache.cc @@ -60,7 +60,7 @@ SSLSessionCache::getSessionBuffer(const SSLSessionID &sid, char *buffer, int &le } bool -SSLSessionCache::getSession(const SSLSessionID &sid, SSL_SESSION **sess) const +SSLSessionCache::getSession(const SSLSessionID &sid, SSL_SESSION **sess, ssl_session_cache_exdata **data) const { uint64_t hash = sid.hash(); uint64_t target_bucket = hash % nbuckets; @@ -73,7 +73,7 @@ SSLSessionCache::getSession(const SSLSessionID &sid, SSL_SESSION **sess) const target_bucket, bucket, buf, hash); } - return bucket->getSession(sid, sess); + return bucket->getSession(sid, sess, data); } void @@ -97,7 +97,7 @@ SSLSessionCache::removeSession(const SSLSessionID &sid) } void -SSLSessionCache::insertSession(const SSLSessionID &sid, SSL_SESSION *sess) +SSLSessionCache::insertSession(const SSLSessionID &sid, SSL_SESSION *sess, SSL *ssl) { uint64_t hash = sid.hash(); uint64_t target_bucket = hash % nbuckets; @@ -110,11 +110,11 @@ SSLSessionCache::insertSession(const SSLSessionID &sid, SSL_SESSION *sess) target_bucket, bucket, buf, hash); } - bucket->insertSession(sid, sess); + bucket->insertSession(sid, sess, ssl); } void -SSLSessionBucket::insertSession(const SSLSessionID &id, SSL_SESSION *sess) +SSLSessionBucket::insertSession(const SSLSessionID &id, SSL_SESSION *sess, SSL *ssl) { size_t len = i2d_SSL_SESSION(sess, nullptr); // make sure we're not going to need more than SSL_MAX_SESSION_SIZE bytes /* do not cache a session that's too big. */ @@ -158,12 +158,19 @@ SSLSessionBucket::insertSession(const SSLSessionID &id, SSL_SESSION *sess) } Ptr buf; - buf = new_IOBufferData(buffer_size_to_index(len, MAX_BUFFER_SIZE_INDEX), MEMALIGNED); + Ptr buf_exdata; + size_t len_exdata = sizeof(ssl_session_cache_exdata); + buf = new_IOBufferData(buffer_size_to_index(len, MAX_BUFFER_SIZE_INDEX), MEMALIGNED); ink_release_assert(static_cast(buf->block_size()) >= len); unsigned char *loc = reinterpret_cast(buf->data()); i2d_SSL_SESSION(sess, &loc); + buf_exdata = new_IOBufferData(buffer_size_to_index(len, MAX_BUFFER_SIZE_INDEX), MEMALIGNED); + ink_release_assert(static_cast(buf_exdata->block_size()) >= len_exdata); + ssl_session_cache_exdata *exdata = reinterpret_cast(buf_exdata->data()); + // This could be moved to a function in charge of populating exdata + exdata->curve = SSLGetCurveNID(ssl); - ats_scoped_obj ssl_session(new SSLSession(id, buf, len)); + ats_scoped_obj ssl_session(new SSLSession(id, buf, len, buf_exdata)); /* do the actual insert */ queue.enqueue(ssl_session.release()); @@ -207,7 +214,7 @@ SSLSessionBucket::getSessionBuffer(const SSLSessionID &id, char *buffer, int &le } bool -SSLSessionBucket::getSession(const SSLSessionID &id, SSL_SESSION **sess) +SSLSessionBucket::getSession(const SSLSessionID &id, SSL_SESSION **sess, ssl_session_cache_exdata **data) { char buf[id.len * 2 + 1]; buf[0] = '\0'; // just to be safe. @@ -237,6 +244,10 @@ SSLSessionBucket::getSession(const SSLSessionID &id, SSL_SESSION **sess) if (node->session_id == id) { const unsigned char *loc = reinterpret_cast(node->asn1_data->data()); *sess = d2i_SSL_SESSION(nullptr, &loc, node->len_asn1_data); + if (data != nullptr) { + ssl_session_cache_exdata *exdata = reinterpret_cast(node->extra_data->data()); + *data = exdata; + } return true; } diff --git a/iocore/net/SSLSessionCache.h b/iocore/net/SSLSessionCache.h index a32809c3c6a..7968b46bd34 100644 --- a/iocore/net/SSLSessionCache.h +++ b/iocore/net/SSLSessionCache.h @@ -32,6 +32,10 @@ #define SSL_MAX_SESSION_SIZE 256 +struct ssl_session_cache_exdata { + ssl_curve_id curve; +}; + struct SSLSessionID : public TSSslSessionID { SSLSessionID(const unsigned char *s, size_t l) { @@ -115,9 +119,10 @@ class SSLSession SSLSessionID session_id; Ptr asn1_data; /* this is the ASN1 representation of the SSL_CTX */ size_t len_asn1_data; + Ptr extra_data; - SSLSession(const SSLSessionID &id, const Ptr &ssl_asn1_data, size_t len_asn1) - : session_id(id), asn1_data(ssl_asn1_data), len_asn1_data(len_asn1) + SSLSession(const SSLSessionID &id, const Ptr &ssl_asn1_data, size_t len_asn1, Ptr &exdata) + : session_id(id), asn1_data(ssl_asn1_data), len_asn1_data(len_asn1), extra_data(exdata) { } @@ -129,8 +134,8 @@ class SSLSessionBucket public: SSLSessionBucket(); ~SSLSessionBucket(); - void insertSession(const SSLSessionID &, SSL_SESSION *ctx); - bool getSession(const SSLSessionID &, SSL_SESSION **ctx); + void insertSession(const SSLSessionID &, SSL_SESSION *ctx, SSL *ssl); + bool getSession(const SSLSessionID &, SSL_SESSION **ctx, ssl_session_cache_exdata **data); int getSessionBuffer(const SSLSessionID &, char *buffer, int &len); void removeSession(const SSLSessionID &); @@ -146,9 +151,9 @@ class SSLSessionBucket class SSLSessionCache { public: - bool getSession(const SSLSessionID &sid, SSL_SESSION **sess) const; + bool getSession(const SSLSessionID &sid, SSL_SESSION **sess, ssl_session_cache_exdata **data) const; int getSessionBuffer(const SSLSessionID &sid, char *buffer, int &len) const; - void insertSession(const SSLSessionID &sid, SSL_SESSION *sess); + void insertSession(const SSLSessionID &sid, SSL_SESSION *sess, SSL *ssl); void removeSession(const SSLSessionID &sid); SSLSessionCache(); ~SSLSessionCache(); diff --git a/iocore/net/SSLUtils.cc b/iocore/net/SSLUtils.cc index d25b69219d1..9e8b352abbc 100644 --- a/iocore/net/SSLUtils.cc +++ b/iocore/net/SSLUtils.cc @@ -200,9 +200,11 @@ ssl_get_cached_session(SSL *ssl, const unsigned char *id, int len, int *copy) hook = hook->m_link.next; } - SSL_SESSION *session = nullptr; - if (session_cache->getSession(sid, &session)) { + SSL_SESSION *session = nullptr; + ssl_session_cache_exdata *exdata = nullptr; + if (session_cache->getSession(sid, &session, &exdata)) { ink_assert(session); + ink_assert(exdata); // Double check the timeout if (ssl_session_timed_out(session)) { @@ -217,6 +219,7 @@ ssl_get_cached_session(SSL *ssl, const unsigned char *id, int len, int *copy) SSLNetVConnection *netvc = SSLNetVCAccess(ssl); SSL_INCREMENT_DYN_STAT(ssl_session_cache_hit); netvc->setSSLSessionCacheHit(true); + netvc->setSSLCurveNID(exdata->curve); } } else { SSL_INCREMENT_DYN_STAT(ssl_session_cache_miss); @@ -229,6 +232,7 @@ ssl_new_cached_session(SSL *ssl, SSL_SESSION *sess) { unsigned int len = 0; const unsigned char *id = SSL_SESSION_get_id(sess, &len); + SSLSessionID sid(id, len); if (diags->tag_activated("ssl.session_cache")) { @@ -239,7 +243,7 @@ ssl_new_cached_session(SSL *ssl, SSL_SESSION *sess) } SSL_INCREMENT_DYN_STAT(ssl_session_cache_new_session); - session_cache->insertSession(sid, sess); + session_cache->insertSession(sid, sess, ssl); // Call hook after new session is created APIHook *hook = ssl_hooks->get(TSSslHookInternalID(TS_SSL_SESSION_HOOK)); @@ -1975,3 +1979,13 @@ SSLMultiCertConfigLoader::clear_pw_references(SSL_CTX *ssl_ctx) SSL_CTX_set_default_passwd_cb(ssl_ctx, nullptr); SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, nullptr); } + +ssl_curve_id +SSLGetCurveNID(SSL *ssl) +{ +#ifndef OPENSSL_IS_BORINGSSL + return SSL_get_shared_curve(ssl, 0); +#else + return SSL_get_curve_id(ssl); +#endif +} diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc index 29f9b0d293c..d6aeeab6b13 100644 --- a/src/traffic_server/InkAPI.cc +++ b/src/traffic_server/InkAPI.cc @@ -9551,7 +9551,7 @@ TSSslSessionGet(const TSSslSessionID *session_id) { SSL_SESSION *session = nullptr; if (session_id && session_cache) { - session_cache->getSession(reinterpret_cast(*session_id), &session); + session_cache->getSession(reinterpret_cast(*session_id), &session, nullptr); } return reinterpret_cast(session); } @@ -9568,7 +9568,7 @@ TSSslSessionGetBuffer(const TSSslSessionID *session_id, char *buffer, int *len_p } TSReturnCode -TSSslSessionInsert(const TSSslSessionID *session_id, TSSslSession add_session) +TSSslSessionInsert(const TSSslSessionID *session_id, TSSslSession add_session, TSSslConnection ssl_conn) { // Don't insert if there is no session id or the cache is not yet set up if (session_id && session_cache) { @@ -9579,7 +9579,8 @@ TSSslSessionInsert(const TSSslSessionID *session_id, TSSslSession add_session) Debug("ssl.session_cache.insert", "TSSslSessionInsert: Inserting session '%s' ", buf); } SSL_SESSION *session = reinterpret_cast(add_session); - session_cache->insertSession(reinterpret_cast(*session_id), session); + SSL *ssl = reinterpret_cast(ssl_conn); + session_cache->insertSession(reinterpret_cast(*session_id), session, ssl); // insertSession returns void, assume all went well return TS_SUCCESS; } else { From 9c242f120fbd84157efc4d68336bdc6a9f67a324 Mon Sep 17 00:00:00 2001 From: Sudheer Vinukonda Date: Wed, 2 Oct 2019 09:27:22 -0700 Subject: [PATCH 064/718] Fix use-after-free problem related to logging headers mime_header_value_set() has a coalesce logic to coalesce dead allocations in the header heap and in the process can free up previously allocated strings that Logging references (cquuc etc). When logging tries to access those fields subsequently it results in a use-after-free (caught using ASAN build). In the wipe field logging use case, there isn't a need to recreate new header heaps, just need to replace the fields with wiped values. So, added a new utility function to simply overwrite the fields. The fix has been retested with ASAN and looks good on prod host. (cherry picked from commit 702c6ac75cc416b988a1f8407baebeb1986e6bb3) --- proxy/hdrs/HdrTest.cc | 27 +++++++++++++++++++++++++++ proxy/hdrs/MIME.h | 25 ++++++++++++++++++++++--- proxy/logging/LogAccess.cc | 5 ++++- 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/proxy/hdrs/HdrTest.cc b/proxy/hdrs/HdrTest.cc index 9d8e30fe7dc..b0f84d39f11 100644 --- a/proxy/hdrs/HdrTest.cc +++ b/proxy/hdrs/HdrTest.cc @@ -495,6 +495,33 @@ HdrTest::test_mime() obj_describe((HdrHeapObjImpl *)(hdr.m_mime), true); + const char *field_name = "Test_heap_reuse"; + + MIMEField *f = hdr.field_create(field_name, static_cast(strlen(field_name))); + ink_release_assert(f->m_ptr_value == nullptr); + + hdr.field_attach(f); + ink_release_assert(f->m_ptr_value == nullptr); + + const char *test_value = "mytest"; + + printf("Testing Heap Reuse..\n"); + hdr.field_value_set(f, "orig_value", strlen("orig_value")); + const char *m_ptr_value_orig = f->m_ptr_value; + hdr.field_value_set(f, test_value, strlen(test_value), true); + ink_release_assert(f->m_ptr_value != test_value); // should be copied + ink_release_assert(f->m_ptr_value == m_ptr_value_orig); // heap doesn't change + ink_release_assert(f->m_len_value == strlen(test_value)); + ink_release_assert(memcmp(f->m_ptr_value, test_value, f->m_len_value) == 0); + + m_ptr_value_orig = f->m_ptr_value; + const char *new_test_value = "myTest"; + hdr.field_value_set(f, new_test_value, strlen(new_test_value), false); + ink_release_assert(f->m_ptr_value != new_test_value); // should be copied + ink_release_assert(f->m_ptr_value != m_ptr_value_orig); // new heap + ink_release_assert(f->m_len_value == strlen(new_test_value)); + ink_release_assert(memcmp(f->m_ptr_value, new_test_value, f->m_len_value) == 0); + hdr.fields_clear(); hdr.destroy(); diff --git a/proxy/hdrs/MIME.h b/proxy/hdrs/MIME.h index 75a48f9a90f..1752ad39626 100644 --- a/proxy/hdrs/MIME.h +++ b/proxy/hdrs/MIME.h @@ -1039,7 +1039,7 @@ class MIMEHdr : public HdrHeapSDKHandle void value_append(const char *name, int name_length, const char *value, int value_length, bool prepend_comma = false, const char separator = ','); - void field_value_set(MIMEField *field, const char *value, int value_length); + void field_value_set(MIMEField *field, const char *value, int value_length, bool reuse_heaps = false); void field_value_set_int(MIMEField *field, int32_t value); void field_value_set_uint(MIMEField *field, uint32_t value); void field_value_set_int64(MIMEField *field, int64_t value); @@ -1095,6 +1095,12 @@ class MIMEHdr : public HdrHeapSDKHandle // No gratuitous copies & refcounts! MIMEHdr(const MIMEHdr &m) = delete; MIMEHdr &operator=(const MIMEHdr &m) = delete; + +private: + // Interface to replace (overwrite) field value without + // changing the heap as long as the new value is not longer + // than the current value + bool field_value_replace(MIMEField *field, const char *value, int value_length); }; /*------------------------------------------------------------------------- @@ -1400,10 +1406,23 @@ MIMEHdr::value_get_comma_list(const char *name, int name_length, StrList *list) /*------------------------------------------------------------------------- -------------------------------------------------------------------------*/ +inline bool +MIMEHdr::field_value_replace(MIMEField *field, const char *value, int value_length) +{ + if (field->m_len_value >= value_length) { + memcpy((char *)field->m_ptr_value, value, value_length); + field->m_len_value = value_length; + return true; + } + return false; +} + inline void -MIMEHdr::field_value_set(MIMEField *field, const char *value, int value_length) +MIMEHdr::field_value_set(MIMEField *field, const char *value, int value_length, bool reuse_heaps) { - field->value_set(m_heap, m_mime, value, value_length); + if (!reuse_heaps || !field_value_replace(field, value, value_length)) { + field->value_set(m_heap, m_mime, value, value_length); + } } inline void diff --git a/proxy/logging/LogAccess.cc b/proxy/logging/LogAccess.cc index e1c631b916f..c0c6888b400 100644 --- a/proxy/logging/LogAccess.cc +++ b/proxy/logging/LogAccess.cc @@ -2841,7 +2841,10 @@ LogAccess::set_http_header_field(LogField::Container container, char *field, cha // Loop over dups, update each of them // while (fld) { - header->value_set((const char *)field, static_cast(::strlen(field)), buf, len); + // make sure to reuse header heaps as otherwise + // coalesce logic in header heap may free up + // memory pointed to by cquuc or other log fields + header->field_value_set(fld, buf, len, true); fld = fld->m_next_dup; } } From f336266ace49737c43e7c86f5a3fa7a63db67ba6 Mon Sep 17 00:00:00 2001 From: Bryan Call Date: Tue, 1 Oct 2019 15:25:53 -0700 Subject: [PATCH 065/718] Removed hardcoded logging.yaml filename in logs (cherry picked from commit 173173fc14bbcd8b43b60727c1a2a59565b844b1) --- proxy/logging/LogConfig.cc | 6 +++--- proxy/logging/YamlLogConfig.cc | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/proxy/logging/LogConfig.cc b/proxy/logging/LogConfig.cc index 5160554204b..41b0fcc4c05 100644 --- a/proxy/logging/LogConfig.cc +++ b/proxy/logging/LogConfig.cc @@ -809,14 +809,14 @@ LogConfig::evaluate_config() return false; } - Note("logging.yaml loading ..."); + Note("%s loading ...", path.get()); YamlLogConfig y(this); bool zret = y.parse(path.get()); if (zret) { - Note("logging.yaml finished loading"); + Note("%s finished loading", path.get()); } else { - Note("logging.yaml failed to load"); + Note("%s failed to load", path.get()); } return zret; diff --git a/proxy/logging/YamlLogConfig.cc b/proxy/logging/YamlLogConfig.cc index ec44d1a3aa3..25cefe914d5 100644 --- a/proxy/logging/YamlLogConfig.cc +++ b/proxy/logging/YamlLogConfig.cc @@ -54,14 +54,14 @@ YamlLogConfig::loadLogConfig(const char *cfgFilename) } if (!config.IsMap()) { - Error("malformed logging.yaml file; expected a map"); + Error("malformed %s file; expected a map", cfgFilename); return false; } if (config["logging"]) { config = config["logging"]; } else { - Error("malformed logging.yaml file; expected a toplevel 'logging' node"); + Error("malformed %s file; expected a toplevel 'logging' node", cfgFilename); return false; } From df1ee267bb6dfbefcb7d48550f672c208fdce3ea Mon Sep 17 00:00:00 2001 From: Zizhong Zhang Date: Tue, 15 Oct 2019 23:25:58 -0700 Subject: [PATCH 066/718] make proxy.config.http.request_buffer_enabled configurable and bug fix This PR fixes issue #6021, #6022, #6023 (cherry picked from commit 08089103e05109b978fa5b545b0d35d2a6294b17) --- doc/admin-guide/files/records.config.en.rst | 5 ++--- mgmt/RecordsConfig.cc | 2 ++ proxy/http/HttpSM.cc | 6 ++---- proxy/http/HttpTransact.cc | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst index c8284d54445..81636d717e3 100644 --- a/doc/admin-guide/files/records.config.en.rst +++ b/doc/admin-guide/files/records.config.en.rst @@ -1091,11 +1091,10 @@ mptcp .. ts:cv:: CONFIG proxy.config.http.request_buffer_enabled INT 0 :overridable: - This is a configuration value that is overridable but not configurable. This is most likely an - implementation error. - This enables buffering the content for incoming ``POST`` requests. If enabled no outbound connection is made until the entire ``POST`` request has been buffered. + If enabled, `proxy.config.http.post_copy_size` needs to be set to the maximum of the post body + size allowed, otherwise, the post would fail. .. ts:cv:: CONFIG proxy.config.http.request_line_max_size INT 65535 diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc index f983e96f4fc..ae335765bf8 100644 --- a/mgmt/RecordsConfig.cc +++ b/mgmt/RecordsConfig.cc @@ -339,6 +339,8 @@ static const RecordElement RecordsConfig[] = , {RECT_CONFIG, "proxy.config.http.keep_alive_post_out", RECD_INT, "1", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , + {RECT_CONFIG, "proxy.config.http.request_buffer_enabled", RECD_INT, "0", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} + , {RECT_CONFIG, "proxy.config.http.chunking_enabled", RECD_INT, "1", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , {RECT_CONFIG, "proxy.config.http.chunking.size", RECD_INT, "4096", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc index ec068e52ad5..bded4020920 100644 --- a/proxy/http/HttpSM.cc +++ b/proxy/http/HttpSM.cc @@ -3423,12 +3423,10 @@ HttpSM::tunnel_handler_post_ua(int event, HttpTunnelProducer *p) // server and close the ua p->handler_state = HTTP_SM_POST_UA_FAIL; set_ua_abort(HttpTransact::ABORTED, event); - + p->vc->do_io_write(nullptr, 0, nullptr); + p->vc->do_io_shutdown(IO_SHUTDOWN_READ); tunnel.chain_abort_all(p); server_session = nullptr; - p->read_vio = nullptr; - p->vc->do_io_close(EHTTP_ERROR); - // the in_tunnel status on both the ua & and // it's consumer must already be set to true. Previously // we were setting it again to true but incorrectly in diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc index 20236884b83..4dd837cd929 100644 --- a/proxy/http/HttpTransact.cc +++ b/proxy/http/HttpTransact.cc @@ -1118,7 +1118,7 @@ HttpTransact::HandleRequest(State *s) { TxnDebug("http_trans", "START HttpTransact::HandleRequest"); - if (!s->state_machine->is_waiting_for_full_body) { + if (!s->state_machine->is_waiting_for_full_body && !s->state_machine->is_using_post_buffer) { ink_assert(!s->hdr_info.server_request.valid()); HTTP_INCREMENT_DYN_STAT(http_incoming_requests_stat); From 79eddf6d9ac9f4a8de41e1c019fee70bb0e763d0 Mon Sep 17 00:00:00 2001 From: bneradt Date: Fri, 4 Oct 2019 14:48:37 +0000 Subject: [PATCH 067/718] ssl_multicert.config -> params->configFilePath SSLCertificateConfig::reconfigure() had a couple messages that used a hard-coded config name for SSL multicert. This filename, however, is configurable per records.config. This change makes use of the name at runtime per SSLConfig params variable rather than the hard-coded value. (cherry picked from commit 63d964df7933e2172523d7c7758013ab25d2b5b8) --- iocore/net/SSLConfig.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/iocore/net/SSLConfig.cc b/iocore/net/SSLConfig.cc index c4492e85a3d..a87eba3df84 100644 --- a/iocore/net/SSLConfig.cc +++ b/iocore/net/SSLConfig.cc @@ -530,9 +530,9 @@ SSLCertificateConfig::reconfigure() } if (retStatus) { - Note("ssl_multicert.config finished loading"); + Note("%s finished loading", params->configFilePath); } else { - Error("ssl_multicert.config failed to load"); + Error("%s failed to load", params->configFilePath); } return retStatus; From a6a12962218cb627cfa9988c8ec4ee7ab9c39ccf Mon Sep 17 00:00:00 2001 From: Susan Hinrichs Date: Mon, 16 Sep 2019 16:21:58 +0000 Subject: [PATCH 068/718] Update TSVConnSslConnectionGet name to match others in the TSVConnSsl* family (cherry picked from commit 52944ce144d1de64ae31509f0e94745957af8bdd) --- example/plugins/c-api/disable_http2/disable_http2.cc | 2 +- example/plugins/c-api/ssl_sni/ssl_sni.cc | 2 +- example/plugins/c-api/ssl_sni_whitelist/ssl_sni_whitelist.cc | 2 +- example/plugins/c-api/verify_cert/verify_cert.cc | 2 +- include/ts/ts.h | 2 +- plugins/certifier/certifier.cc | 4 ++-- plugins/experimental/ja3_fingerprint/ja3_fingerprint.cc | 2 +- plugins/experimental/sslheaders/sslheaders.cc | 2 +- src/traffic_server/InkAPI.cc | 2 +- src/tscpp/api/InterceptPlugin.cc | 2 +- tests/tools/plugins/ssl_verify_test.cc | 2 +- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/example/plugins/c-api/disable_http2/disable_http2.cc b/example/plugins/c-api/disable_http2/disable_http2.cc index 0169bc4f05c..036c991a1b1 100644 --- a/example/plugins/c-api/disable_http2/disable_http2.cc +++ b/example/plugins/c-api/disable_http2/disable_http2.cc @@ -42,7 +42,7 @@ int CB_SNI(TSCont contp, TSEvent, void *cb_data) { auto vc = static_cast(cb_data); - TSSslConnection ssl_conn = TSVConnSSLConnectionGet(vc); + TSSslConnection ssl_conn = TSVConnSslConnectionGet(vc); auto *ssl = reinterpret_cast(ssl_conn); char const *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); if (sni) { diff --git a/example/plugins/c-api/ssl_sni/ssl_sni.cc b/example/plugins/c-api/ssl_sni/ssl_sni.cc index f835edc3423..a0b676be081 100644 --- a/example/plugins/c-api/ssl_sni/ssl_sni.cc +++ b/example/plugins/c-api/ssl_sni/ssl_sni.cc @@ -49,7 +49,7 @@ int CB_servername(TSCont /* contp */, TSEvent /* event */, void *edata) { TSVConn ssl_vc = reinterpret_cast(edata); - TSSslConnection sslobj = TSVConnSSLConnectionGet(ssl_vc); + TSSslConnection sslobj = TSVConnSslConnectionGet(ssl_vc); SSL *ssl = reinterpret_cast(sslobj); const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); if (servername != nullptr) { diff --git a/example/plugins/c-api/ssl_sni_whitelist/ssl_sni_whitelist.cc b/example/plugins/c-api/ssl_sni_whitelist/ssl_sni_whitelist.cc index f0217b06c3d..af35fe5d1c3 100644 --- a/example/plugins/c-api/ssl_sni_whitelist/ssl_sni_whitelist.cc +++ b/example/plugins/c-api/ssl_sni_whitelist/ssl_sni_whitelist.cc @@ -40,7 +40,7 @@ int CB_servername_whitelist(TSCont /* contp */, TSEvent /* event */, void *edata) { TSVConn ssl_vc = reinterpret_cast(edata); - TSSslConnection sslobj = TSVConnSSLConnectionGet(ssl_vc); + TSSslConnection sslobj = TSVConnSslConnectionGet(ssl_vc); SSL *ssl = reinterpret_cast(sslobj); const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); diff --git a/example/plugins/c-api/verify_cert/verify_cert.cc b/example/plugins/c-api/verify_cert/verify_cert.cc index e245fdb4436..4682379c09f 100644 --- a/example/plugins/c-api/verify_cert/verify_cert.cc +++ b/example/plugins/c-api/verify_cert/verify_cert.cc @@ -62,7 +62,7 @@ int CB_clientcert(TSCont /* contp */, TSEvent /* event */, void *edata) { TSVConn ssl_vc = reinterpret_cast(edata); - TSSslConnection sslobj = TSVConnSSLConnectionGet(ssl_vc); + TSSslConnection sslobj = TSVConnSslConnectionGet(ssl_vc); SSL *ssl = reinterpret_cast(sslobj); X509 *cert = SSL_get_peer_certificate(ssl); TSDebug(PLUGIN_NAME, "plugin verify_cert verifying client certificate"); diff --git a/include/ts/ts.h b/include/ts/ts.h index a59897deb73..a0887dec5da 100644 --- a/include/ts/ts.h +++ b/include/ts/ts.h @@ -1233,7 +1233,7 @@ tsapi void TSVConnReenableEx(TSVConn sslvcp, TSEvent event); /* Set the connection to go into blind tunnel mode */ tsapi TSReturnCode TSVConnTunnel(TSVConn sslp); /* Return the SSL object associated with the connection */ -tsapi TSSslConnection TSVConnSSLConnectionGet(TSVConn sslp); +tsapi TSSslConnection TSVConnSslConnectionGet(TSVConn sslp); /* Return the intermediate X509StoreCTX object that references the certificate being validated */ tsapi TSSslVerifyCTX TSVConnSslVerifyCTXGet(TSVConn sslp); /* Fetch a SSL context from the global lookup table */ diff --git a/plugins/certifier/certifier.cc b/plugins/certifier/certifier.cc index de1469947a8..452b694f3dc 100644 --- a/plugins/certifier/certifier.cc +++ b/plugins/certifier/certifier.cc @@ -534,7 +534,7 @@ shadow_cert_generator(TSCont contp, TSEvent event, void *edata) TSDebug(PLUGIN_NAME, "\tClearing the queue size %lu", localQ.size()); TSVConn ssl_vc = reinterpret_cast(localQ.front()); localQ.pop(); - TSSslConnection sslobj = TSVConnSSLConnectionGet(ssl_vc); + TSSslConnection sslobj = TSVConnSslConnectionGet(ssl_vc); SSL *ssl = reinterpret_cast(sslobj); SSL_set_SSL_CTX(ssl, ref_ctx); TSVConnReenable(ssl_vc); @@ -549,7 +549,7 @@ static int cert_retriever(TSCont contp, TSEvent event, void *edata) { TSVConn ssl_vc = reinterpret_cast(edata); - TSSslConnection sslobj = TSVConnSSLConnectionGet(ssl_vc); + TSSslConnection sslobj = TSVConnSslConnectionGet(ssl_vc); SSL *ssl = reinterpret_cast(sslobj); const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); SSL_CTX *ref_ctx = nullptr; diff --git a/plugins/experimental/ja3_fingerprint/ja3_fingerprint.cc b/plugins/experimental/ja3_fingerprint/ja3_fingerprint.cc index 6b4ecfb0472..dc0486a504c 100644 --- a/plugins/experimental/ja3_fingerprint/ja3_fingerprint.cc +++ b/plugins/experimental/ja3_fingerprint/ja3_fingerprint.cc @@ -302,7 +302,7 @@ client_hello_ja3_handler(TSCont contp, TSEvent event, void *edata) #error OpenSSL cannot be 1.1.0 #endif - TSSslConnection sslobj = TSVConnSSLConnectionGet(ssl_vc); + TSSslConnection sslobj = TSVConnSslConnectionGet(ssl_vc); // OpenSSL handle SSL *ssl = reinterpret_cast(sslobj); diff --git a/plugins/experimental/sslheaders/sslheaders.cc b/plugins/experimental/sslheaders/sslheaders.cc index 0c4dd1fbcfd..92b42992340 100644 --- a/plugins/experimental/sslheaders/sslheaders.cc +++ b/plugins/experimental/sslheaders/sslheaders.cc @@ -36,7 +36,7 @@ SslHdrExpandRequestHook(TSCont cont, TSEvent event, void *edata) txn = static_cast(edata); hdr = static_cast(TSContDataGet(cont)); TSVConn vconn = TSHttpSsnClientVConnGet(TSHttpTxnSsnGet(txn)); - TSSslConnection ssl = TSVConnSSLConnectionGet(vconn); + TSSslConnection ssl = TSVConnSslConnectionGet(vconn); switch (event) { case TS_EVENT_HTTP_READ_REQUEST_HDR: diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc index d6aeeab6b13..174353e50a5 100644 --- a/src/traffic_server/InkAPI.cc +++ b/src/traffic_server/InkAPI.cc @@ -9162,7 +9162,7 @@ TSVConnTunnel(TSVConn sslp) } TSSslConnection -TSVConnSSLConnectionGet(TSVConn sslp) +TSVConnSslConnectionGet(TSVConn sslp) { TSSslConnection ssl = nullptr; NetVConnection *vc = reinterpret_cast(sslp); diff --git a/src/tscpp/api/InterceptPlugin.cc b/src/tscpp/api/InterceptPlugin.cc index abd05731092..2eb76175635 100644 --- a/src/tscpp/api/InterceptPlugin.cc +++ b/src/tscpp/api/InterceptPlugin.cc @@ -190,7 +190,7 @@ InterceptPlugin::getSslConnection() return nullptr; } - return TSVConnSSLConnectionGet(state_->net_vc_); + return TSVConnSslConnectionGet(state_->net_vc_); } bool diff --git a/tests/tools/plugins/ssl_verify_test.cc b/tests/tools/plugins/ssl_verify_test.cc index 4599db99fd1..a0366633377 100644 --- a/tests/tools/plugins/ssl_verify_test.cc +++ b/tests/tools/plugins/ssl_verify_test.cc @@ -47,7 +47,7 @@ CB_server_verify(TSCont cont, TSEvent event, void *edata) // Is this a good name or not? TSEvent reenable_event = TS_EVENT_CONTINUE; - TSSslConnection sslobj = TSVConnSSLConnectionGet(ssl_vc); + TSSslConnection sslobj = TSVConnSslConnectionGet(ssl_vc); SSL *ssl = (SSL *)sslobj; const char *sni_name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); if (sni_name) { From 045de7b852fcb62b8c4b2a88a6ced23828fa1dfd Mon Sep 17 00:00:00 2001 From: Susan Hinrichs Date: Mon, 5 Aug 2019 22:39:39 +0000 Subject: [PATCH 069/718] Updating the default cipher-suite lists for the 9.x release. (cherry picked from commit c8ef42812a585408938ad14b88549feafa963187) --- configs/records.config.default.in | 1 - doc/admin-guide/files/records.config.en.rst | 17 +++++++++++------ mgmt/RecordsConfig.cc | 11 +++++------ 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/configs/records.config.default.in b/configs/records.config.default.in index df417bc4a49..8f1638289bb 100644 --- a/configs/records.config.default.in +++ b/configs/records.config.default.in @@ -166,7 +166,6 @@ CONFIG proxy.config.reverse_proxy.enabled INT 1 CONFIG proxy.config.ssl.client.verify.server.policy STRING PERMISSIVE CONFIG proxy.config.ssl.client.verify.server.properties STRING ALL CONFIG proxy.config.ssl.client.CA.cert.filename STRING NULL -CONFIG proxy.config.ssl.server.cipher_suite STRING ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA ############################################################################## # Debugging. Docs: diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst index 81636d717e3..ea7dfb8642a 100644 --- a/doc/admin-guide/files/records.config.en.rst +++ b/doc/admin-guide/files/records.config.en.rst @@ -3065,14 +3065,15 @@ SSL Termination formatting cipher_suite string, see `OpenSSL Ciphers `_. - The current default, included in the ``records.config.default`` example - configuration is: + The current default is: - ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA + ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-CCM:ECDHE-ECDSA-AES128-CCM:ECDHE-ECDSA-AES256-CCM8:ECDHE-ECDSA-AES128-CCM8:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-CCM8:DHE-RSA-AES128-CCM8:DHE-RSA-AES256-CCM:DHE-RSA-AES128-CCM:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-CCM8:AES128-CCM8:AES256-CCM:AES128-CCM:AES256-SHA256:AES128-SHA2 .. ts:cv:: CONFIG proxy.config.ssl.client.cipher_suite STRING - Configures the cipher_suite which |TS| will use for SSL connections to origin or next hop. + Configures the cipher_suite which |TS| will use for SSL connections to origin or next hop. This currently defaults to: + + ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-CCM8:ECDHE-ECDSA-AES256-CCM:DHE-RSA-AES256-CCM8:DHE-RSA-AES256-CCM:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-ARIA256-GCM-SHA384:ECDHE-ARIA256-GCM-SHA384:DHE-DSS-ARIA256-GCM-SHA384:DHE-RSA-ARIA256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:ECDHE-ECDSA-CAMELLIA256-SHA384:ECDHE-RSA-CAMELLIA256-SHA384:DHE-RSA-CAMELLIA256-SHA256:DHE-DSS-CAMELLIA256-SHA256:RSA-PSK-AES256-GCM-SHA384:RSA-PSK-CHACHA20-POLY1305:RSA-PSK-ARIA256-GCM-SHA384:AES256-GCM-SHA384:AES256-CCM8:AES256-CCM:ARIA256-GCM-SHA384:AES256-SHA256:CAMELLIA256-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-CCM8:ECDHE-ECDSA-AES128-CCM:DHE-RSA-AES128-CCM8:DHE-RSA-AES128-CCM:ECDHE-ECDSA-ARIA128-GCM-SHA256:ECDHE-ARIA128-GCM-SHA256:DHE-DSS-ARIA128-GCM-SHA256:DHE-RSA-ARIA128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:ECDHE-ECDSA-CAMELLIA128-SHA256:ECDHE-RSA-CAMELLIA128-SHA256:DHE-RSA-CAMELLIA128-SHA256:DHE-DSS-CAMELLIA128-SHA256:RSA-PSK-AES128-GCM-SHA256:RSA-PSK-ARIA128-GCM-SHA256:AES128-GCM-SHA256:AES128-CCM8:AES128-CCM:ARIA128-GCM-SHA256:AES128-SHA256:CAMELLIA128-SHA256 .. ts:cv:: CONFIG proxy.config.ssl.server.TLSv1_3.cipher_suites STRING @@ -3081,9 +3082,9 @@ SSL Termination connections. For the list of algorithms and instructions, see The ``-ciphersuites`` section of `OpenSSL Ciphers `_. - The current default value with OpenSSL is: + The current default value is: - TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256 + TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256 This configuration works with OpenSSL v1.1.1 and above. @@ -3098,6 +3099,10 @@ SSL Termination connections to origin or next hop. This configuration works with OpenSSL v1.1.1 and above. + The current default is: + + TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256 + .. ts:cv:: CONFIG proxy.config.ssl.server.groups_list STRING Configures the list of supported groups provided by OpenSSL which diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc index ae335765bf8..62547c08056 100644 --- a/mgmt/RecordsConfig.cc +++ b/mgmt/RecordsConfig.cc @@ -1072,9 +1072,10 @@ static const RecordElement RecordsConfig[] = , {RECT_CONFIG, "proxy.config.ssl.client.TLSv1_3", RECD_INT, "1", RECU_RESTART_TS, RR_NULL, RECC_INT, "[0-1]", RECA_NULL} , - {RECT_CONFIG, "proxy.config.ssl.server.cipher_suite", RECD_STRING, "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA", RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} + {RECT_CONFIG, "proxy.config.ssl.server.cipher_suite", RECD_STRING, "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-CCM:ECDHE-ECDSA-AES128-CCM:ECDHE-ECDSA-AES256-CCM8:ECDHE-ECDSA-AES128-CCM8:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-CCM8:DHE-RSA-AES128-CCM8:DHE-RSA-AES256-CCM:DHE-RSA-AES128-CCM:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-CCM8:AES128-CCM8:AES256-CCM:AES128-CCM:AES256-SHA256:AES128-SHA2", RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , - {RECT_CONFIG, "proxy.config.ssl.client.cipher_suite", RECD_STRING, nullptr, RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} + // Computed from openssl ciphers 'ALL:!aNULL:!aDH:!aECDH:!aPSK:!aSRP:!eNULL:!kSRP:!SSLv2:!SSLv3:!TLSv1:!TLSv1.1:@STRENGTH' + {RECT_CONFIG, "proxy.config.ssl.client.cipher_suite", RECD_STRING, "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-CCM8:ECDHE-ECDSA-AES256-CCM:DHE-RSA-AES256-CCM8:DHE-RSA-AES256-CCM:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-ARIA256-GCM-SHA384:ECDHE-ARIA256-GCM-SHA384:DHE-DSS-ARIA256-GCM-SHA384:DHE-RSA-ARIA256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:ECDHE-ECDSA-CAMELLIA256-SHA384:ECDHE-RSA-CAMELLIA256-SHA384:DHE-RSA-CAMELLIA256-SHA256:DHE-DSS-CAMELLIA256-SHA256:RSA-PSK-AES256-GCM-SHA384:RSA-PSK-CHACHA20-POLY1305:RSA-PSK-ARIA256-GCM-SHA384:AES256-GCM-SHA384:AES256-CCM8:AES256-CCM:ARIA256-GCM-SHA384:AES256-SHA256:CAMELLIA256-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-CCM8:ECDHE-ECDSA-AES128-CCM:DHE-RSA-AES128-CCM8:DHE-RSA-AES128-CCM:ECDHE-ECDSA-ARIA128-GCM-SHA256:ECDHE-ARIA128-GCM-SHA256:DHE-DSS-ARIA128-GCM-SHA256:DHE-RSA-ARIA128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:ECDHE-ECDSA-CAMELLIA128-SHA256:ECDHE-RSA-CAMELLIA128-SHA256:DHE-RSA-CAMELLIA128-SHA256:DHE-DSS-CAMELLIA128-SHA256:RSA-PSK-AES128-GCM-SHA256:RSA-PSK-ARIA128-GCM-SHA256:AES128-GCM-SHA256:AES128-CCM8:AES128-CCM:ARIA128-GCM-SHA256:AES128-SHA256:CAMELLIA128-SHA256", RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , {RECT_CONFIG, "proxy.config.ssl.server.honor_cipher_order", RECD_INT, "1", RECU_RESTART_TS, RR_NULL, RECC_INT, "[0-1]", RECA_NULL} , @@ -1174,11 +1175,9 @@ static const RecordElement RecordsConfig[] = //# Configuration for TLSv1.3 and above //# //############################################################################## - // The default value (nullptr) means the default value of TLS stack will be used. - // - e.g. OpenSSL : "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256" - {RECT_CONFIG, "proxy.config.ssl.server.TLSv1_3.cipher_suites", RECD_STRING, nullptr, RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} + {RECT_CONFIG, "proxy.config.ssl.server.TLSv1_3.cipher_suites", RECD_STRING, "TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256", RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , - {RECT_CONFIG, "proxy.config.ssl.client.TLSv1_3.cipher_suites", RECD_STRING, nullptr, RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} + {RECT_CONFIG, "proxy.config.ssl.client.TLSv1_3.cipher_suites", RECD_STRING, "TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256", RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , //############################################################################ From 5c79a827fa260b368733e9062770510e31abe787 Mon Sep 17 00:00:00 2001 From: Susan Hinrichs Date: Fri, 20 Sep 2019 14:33:05 +0000 Subject: [PATCH 070/718] Fix TSHttpTxnReenable to schedule back to original SM thread (cherry picked from commit 54b8caf6f5b1ddb7b6100d13af6377853bfac489) --- proxy/http/HttpSM.cc | 3 +++ src/traffic_server/InkAPI.cc | 18 +++++++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc index bded4020920..56e4a4e191a 100644 --- a/proxy/http/HttpSM.cc +++ b/proxy/http/HttpSM.cc @@ -325,6 +325,9 @@ HttpSM::init() SET_HANDLER(&HttpSM::main_handler); + // Remember where this SM is running so it gets returned correctly + this->setThreadAffinity(this_ethread()); + #ifdef USE_HTTP_DEBUG_LISTS ink_mutex_acquire(&debug_sm_list_mutex); debug_sm_list.push(this); diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc index 174353e50a5..7b0a07bd97d 100644 --- a/src/traffic_server/InkAPI.cc +++ b/src/traffic_server/InkAPI.cc @@ -6087,20 +6087,20 @@ TSHttpTxnReenable(TSHttpTxn txnp, TSEvent event) // created using the ATS EThread API, eth will be NULL, and the // continuation needs to be called back on a REGULAR thread. // - // If this function is being executed on a thread created by the API - // which is DEDICATED, the continuation needs to be called back on a - // REGULAR thread. - if (eth == nullptr || eth->tt != REGULAR || !eth->is_event_type(ET_NET)) { - eventProcessor.schedule_imm(new TSHttpSMCallback(sm, event), ET_NET); - } else { + // If we are not coming from the thread associated with the state machine, + // reschedule. Also reschedule if we cannot get the state machine lock. + if (eth != nullptr && sm->getThreadAffinity() == eth) { MUTEX_TRY_LOCK(trylock, sm->mutex, eth); - if (!trylock.is_locked()) { - eventProcessor.schedule_imm(new TSHttpSMCallback(sm, event), ET_NET); - } else { + if (trylock.is_locked()) { ink_assert(eth->is_event_type(ET_NET)); sm->state_api_callback((int)event, nullptr); + return; } } + // Couldn't call the handler directly, schedule to the original SM thread + TSHttpSMCallback *cb = new TSHttpSMCallback(sm, event); + cb->setThreadAffinity(sm->getThreadAffinity()); + eventProcessor.schedule_imm(cb, ET_NET); } TSReturnCode TSHttpArgIndexNameLookup(UserArg::Type type, const char *name, int *arg_idx, const char **description); From 8c0f3ddb8947ffa9d7470ca7f4fad6c1805558dd Mon Sep 17 00:00:00 2001 From: Aaron Canary Date: Wed, 21 Aug 2019 11:28:22 -0500 Subject: [PATCH 071/718] Replaced ProxyTxn::outbound vars with accept::options Each session gets a reference, each transaction gets a copy so it can be overwritten. fixed H3 Http09App fix (cherry picked from commit de9b3a6fac2970401bddd67e20ecaf716ab0ea48) --- proxy/ProxySession.cc | 25 ----------------------- proxy/ProxySession.h | 9 ++------- proxy/ProxyTransaction.cc | 33 ++++++++++++++++++------------- proxy/ProxyTransaction.h | 11 +++++------ proxy/http/Http1ClientSession.h | 8 -------- proxy/http/Http1Transaction.cc | 16 --------------- proxy/http/Http1Transaction.h | 13 ------------ proxy/http/HttpSessionAccept.cc | 13 +++++------- proxy/http2/Http2SessionAccept.cc | 4 +--- proxy/http3/Http09App.cc | 4 +--- proxy/http3/Http3App.cc | 4 +--- src/traffic_server/InkAPI.cc | 2 +- 12 files changed, 35 insertions(+), 107 deletions(-) diff --git a/proxy/ProxySession.cc b/proxy/ProxySession.cc index 3d037bc960e..af7c30ee2ca 100644 --- a/proxy/ProxySession.cc +++ b/proxy/ProxySession.cc @@ -222,13 +222,6 @@ ProxySession::is_draining() const return TSSystemState::is_draining(); } -// Override if your session protocol allows this. -bool -ProxySession::is_transparent_passthrough_allowed() const -{ - return false; -} - bool ProxySession::is_chunked_encoding_supported() const { @@ -247,24 +240,6 @@ ProxySession::get_half_close_flag() const return false; } -in_port_t -ProxySession::get_outbound_port() const -{ - return outbound_port; -} - -IpAddr -ProxySession::get_outbound_ip4() const -{ - return outbound_ip4; -} - -IpAddr -ProxySession::get_outbound_ip6() const -{ - return outbound_ip6; -} - int64_t ProxySession::connection_id() const { diff --git a/proxy/ProxySession.h b/proxy/ProxySession.h index 5f40af71829..3689f3fdba6 100644 --- a/proxy/ProxySession.h +++ b/proxy/ProxySession.h @@ -30,6 +30,7 @@ #include "P_Net.h" #include "InkAPIInternal.h" #include "http/Http1ServerSession.h" +#include "http/HttpSessionAccept.h" #include "IPAllow.h" // Emit a debug message conditional on whether this particular client session @@ -99,7 +100,6 @@ class ProxySession : public VConnection virtual NetVConnection *get_netvc() const = 0; virtual int get_transact_count() const = 0; virtual const char *get_protocol_string() const = 0; - virtual bool is_transparent_passthrough_allowed() const; virtual void hook_add(TSHttpHookID id, INKContInternal *cont); @@ -108,9 +108,6 @@ class ProxySession : public VConnection virtual void set_half_close_flag(bool flag); virtual bool get_half_close_flag() const; - virtual in_port_t get_outbound_port() const; - virtual IpAddr get_outbound_ip4() const; - virtual IpAddr get_outbound_ip6() const; virtual Http1ServerSession *get_server_session() const; // Replicate NetVConnection API @@ -151,9 +148,7 @@ class ProxySession : public VConnection IpAllow::ACL acl; ///< IpAllow based method ACL. - IpAddr outbound_ip4; ///< Local address for outbound connection. - IpAddr outbound_ip6; ///< Local address for outbound connection. - in_port_t outbound_port{0}; ///< Local port for outbound connection. + HttpSessionAccept::Options const *accept_options; ///< connection info // L7R TODO: set in constructor HostResStyle host_res_style = HOST_RES_NONE; ///< DNS resolution preferences. diff --git a/proxy/ProxyTransaction.cc b/proxy/ProxyTransaction.cc index 67b9c842e15..53a77e42d75 100644 --- a/proxy/ProxyTransaction.cc +++ b/proxy/ProxyTransaction.cc @@ -128,7 +128,7 @@ ProxyTransaction::is_first_transaction() const bool ProxyTransaction::is_transparent_passthrough_allowed() { - return proxy_ssn ? proxy_ssn->is_transparent_passthrough_allowed() : false; + return upstream_outbound_options.f_transparent_passthrough; } bool @@ -215,43 +215,48 @@ ProxyTransaction::get_acl() const in_port_t ProxyTransaction::get_outbound_port() const { - return outbound_port; + return upstream_outbound_options.outbound_port; } +void +ProxyTransaction::set_outbound_port(in_port_t port) +{ + upstream_outbound_options.outbound_port = port; +} + IpAddr ProxyTransaction::get_outbound_ip4() const { - return outbound_ip4; + return upstream_outbound_options.outbound_ip4; } + IpAddr ProxyTransaction::get_outbound_ip6() const { - return outbound_ip6; -} -void -ProxyTransaction::set_outbound_port(in_port_t port) -{ - outbound_port = port; + return upstream_outbound_options.outbound_ip6; } + void ProxyTransaction::set_outbound_ip(const IpAddr &new_addr) { if (new_addr.isIp4()) { - outbound_ip4 = new_addr; + upstream_outbound_options.outbound_ip4 = new_addr; } else if (new_addr.isIp6()) { - outbound_ip6 = new_addr; + upstream_outbound_options.outbound_ip6 = new_addr; } else { - outbound_ip4.invalidate(); - outbound_ip6.invalidate(); + upstream_outbound_options.outbound_ip4.invalidate(); + upstream_outbound_options.outbound_ip6.invalidate(); } } bool ProxyTransaction::is_outbound_transparent() const { - return false; + return upstream_outbound_options.f_outbound_transparent; } + void ProxyTransaction::set_outbound_transparent(bool flag) { + upstream_outbound_options.f_outbound_transparent = flag; } ProxySession * diff --git a/proxy/ProxyTransaction.h b/proxy/ProxyTransaction.h index 7b16646f472..874bcd05f99 100644 --- a/proxy/ProxyTransaction.h +++ b/proxy/ProxyTransaction.h @@ -111,6 +111,10 @@ class ProxyTransaction : public VConnection void set_rx_error_code(ProxyError e); void set_tx_error_code(ProxyError e); + /// Variables + // + HttpSessionAccept::Options upstream_outbound_options; // overwritable copy of options + protected: ProxySession *proxy_ssn = nullptr; HttpSM *current_reader = nullptr; @@ -118,12 +122,7 @@ class ProxyTransaction : public VConnection /// DNS resolution preferences. HostResStyle host_res_style = HOST_RES_NONE; - /// Local outbound address control. - in_port_t outbound_port{0}; - IpAddr outbound_ip4; - IpAddr outbound_ip6; - - bool restart_immediate = false; + bool restart_immediate = false; private: }; diff --git a/proxy/http/Http1ClientSession.h b/proxy/http/Http1ClientSession.h index f6a1de0445a..60542ee1b8b 100644 --- a/proxy/http/Http1ClientSession.h +++ b/proxy/http/Http1ClientSession.h @@ -156,12 +156,6 @@ class Http1ClientSession : public ProxySession return "http"; } - bool - is_transparent_passthrough_allowed() const override - { - return f_transparent_passthrough; - } - void increment_current_active_client_connections_stat() override; void decrement_current_active_client_connections_stat() override; @@ -206,8 +200,6 @@ class Http1ClientSession : public ProxySession /// Set outbound connection to transparent. bool f_outbound_transparent = false; - /// Transparently pass-through non-HTTP traffic. - bool f_transparent_passthrough = false; Http1Transaction trans; }; diff --git a/proxy/http/Http1Transaction.cc b/proxy/http/Http1Transaction.cc index a3d811cddf8..6ccd2910339 100644 --- a/proxy/http/Http1Transaction.cc +++ b/proxy/http/Http1Transaction.cc @@ -46,22 +46,6 @@ Http1Transaction::release(IOBufferReader *r) } } -void -Http1Transaction::set_proxy_ssn(ProxySession *new_proxy_ssn) -{ - Http1ClientSession *http1_proxy_ssn = dynamic_cast(new_proxy_ssn); - - if (http1_proxy_ssn) { - outbound_port = http1_proxy_ssn->outbound_port; - outbound_ip4 = http1_proxy_ssn->outbound_ip4; - outbound_ip6 = http1_proxy_ssn->outbound_ip6; - outbound_transparent = http1_proxy_ssn->f_outbound_transparent; - super_type::set_proxy_ssn(new_proxy_ssn); - } else { - proxy_ssn = nullptr; - } -} - void Http1Transaction::transaction_done() { diff --git a/proxy/http/Http1Transaction.h b/proxy/http/Http1Transaction.h index dfc9e3ab522..eccd8334752 100644 --- a/proxy/http/Http1Transaction.h +++ b/proxy/http/Http1Transaction.h @@ -83,19 +83,6 @@ class Http1Transaction : public ProxyTransaction bool allow_half_open() const override; - void set_proxy_ssn(ProxySession *new_proxy_ssn) override; - - bool - is_outbound_transparent() const override - { - return outbound_transparent; - } - void - set_outbound_transparent(bool flag) override - { - outbound_transparent = flag; - } - // Pass on the timeouts to the netvc void set_active_timeout(ink_hrtime timeout_in) override diff --git a/proxy/http/HttpSessionAccept.cc b/proxy/http/HttpSessionAccept.cc index ecad5c5a719..5c6b9a91b38 100644 --- a/proxy/http/HttpSessionAccept.cc +++ b/proxy/http/HttpSessionAccept.cc @@ -51,17 +51,14 @@ HttpSessionAccept::accept(NetVConnection *netvc, MIOBuffer *iobuf, IOBufferReade Http1ClientSession *new_session = THREAD_ALLOC_INIT(http1ClientSessionAllocator, this_ethread()); - // copy over session related data. - new_session->f_outbound_transparent = f_outbound_transparent; - new_session->f_transparent_passthrough = f_transparent_passthrough; - new_session->outbound_ip4 = outbound_ip4; - new_session->outbound_ip6 = outbound_ip6; - new_session->outbound_port = outbound_port; - new_session->host_res_style = ats_host_res_from(client_ip->sa_family, host_res_preference); - new_session->acl = std::move(acl); + new_session->accept_options = static_cast(this); + new_session->host_res_style = ats_host_res_from(client_ip->sa_family, host_res_preference); + new_session->acl = std::move(acl); new_session->new_connection(netvc, iobuf, reader); + new_session->trans.upstream_outbound_options = *new_session->accept_options; + return true; } diff --git a/proxy/http2/Http2SessionAccept.cc b/proxy/http2/Http2SessionAccept.cc index 291a4fadcf8..a21cc253f41 100644 --- a/proxy/http2/Http2SessionAccept.cc +++ b/proxy/http2/Http2SessionAccept.cc @@ -56,9 +56,7 @@ Http2SessionAccept::accept(NetVConnection *netvc, MIOBuffer *iobuf, IOBufferRead Http2ClientSession *new_session = THREAD_ALLOC_INIT(http2ClientSessionAllocator, this_ethread()); new_session->acl = std::move(session_acl); new_session->host_res_style = ats_host_res_from(client_ip->sa_family, options.host_res_preference); - new_session->outbound_ip4 = options.outbound_ip4; - new_session->outbound_ip6 = options.outbound_ip6; - new_session->outbound_port = options.outbound_port; + new_session->accept_options = &options; new_session->new_connection(netvc, iobuf, reader); return true; diff --git a/proxy/http3/Http09App.cc b/proxy/http3/Http09App.cc index 0b317ff0816..1749723d873 100644 --- a/proxy/http3/Http09App.cc +++ b/proxy/http3/Http09App.cc @@ -43,9 +43,7 @@ Http09App::Http09App(QUICNetVConnection *client_vc, IpAllow::ACL &&session_acl, // TODO: avoid const cast this->_ssn->host_res_style = ats_host_res_from(client_vc->get_remote_addr()->sa_family, const_cast(options.host_res_preference)); - this->_ssn->outbound_ip4 = options.outbound_ip4; - this->_ssn->outbound_ip6 = options.outbound_ip6; - this->_ssn->outbound_port = options.outbound_port; + this->_ssn->accept_options = &options; this->_ssn->new_connection(client_vc, nullptr, nullptr); this->_qc->stream_manager()->set_default_application(this); diff --git a/proxy/http3/Http3App.cc b/proxy/http3/Http3App.cc index 946a73d7a59..53ec6d4ad5a 100644 --- a/proxy/http3/Http3App.cc +++ b/proxy/http3/Http3App.cc @@ -45,9 +45,7 @@ Http3App::Http3App(QUICNetVConnection *client_vc, IpAllow::ACL &&session_acl, co // TODO: avoid const cast this->_ssn->host_res_style = ats_host_res_from(client_vc->get_remote_addr()->sa_family, const_cast(options.host_res_preference)); - this->_ssn->outbound_ip4 = options.outbound_ip4; - this->_ssn->outbound_ip6 = options.outbound_ip6; - this->_ssn->outbound_port = options.outbound_port; + this->_ssn->accept_options = &options; this->_ssn->new_connection(client_vc, nullptr, nullptr); diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc index 7b0a07bd97d..49ae84326e6 100644 --- a/src/traffic_server/InkAPI.cc +++ b/src/traffic_server/InkAPI.cc @@ -5725,7 +5725,7 @@ TSHttpTxnOutgoingAddrSet(TSHttpTxn txnp, const struct sockaddr *addr) sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS); HttpSM *sm = (HttpSM *)txnp; - sm->ua_txn->set_outbound_port(ats_ip_port_host_order(addr)); + sm->ua_txn->upstream_outbound_options.outbound_port = ats_ip_port_host_order(addr); sm->ua_txn->set_outbound_ip(IpAddr(addr)); return TS_SUCCESS; } From 5d07f7d8a0eecb2a61bb5772f1b92afa6cc3ea34 Mon Sep 17 00:00:00 2001 From: Aaron Canary Date: Fri, 23 Aug 2019 11:14:26 -0500 Subject: [PATCH 072/718] ProxyTxn refactor: moved host_res_style to t_state.dns_info + (cherry picked from commit 71c99b8058663eaf3a7dfbaf6119dcae3d30a413) --- include/tscore/ink_resolver.h | 4 ++-- proxy/ProxySession.h | 2 -- proxy/ProxyTransaction.cc | 15 +-------------- proxy/ProxyTransaction.h | 4 +--- proxy/http/HttpSM.cc | 12 +++++++++--- proxy/http/HttpSessionAccept.cc | 1 - proxy/http/HttpTransact.cc | 2 +- proxy/http/HttpTransact.h | 4 +++- proxy/http2/Http2SessionAccept.cc | 1 - proxy/http3/Http09App.cc | 7 ++----- proxy/http3/Http3App.cc | 8 ++------ src/tscore/ink_res_mkquery.cc | 2 +- 12 files changed, 22 insertions(+), 40 deletions(-) diff --git a/include/tscore/ink_resolver.h b/include/tscore/ink_resolver.h index b9af473f772..0969fa7dfa1 100644 --- a/include/tscore/ink_resolver.h +++ b/include/tscore/ink_resolver.h @@ -182,8 +182,8 @@ enum HostResStyle { extern const char *const HOST_RES_STYLE_STRING[]; /// Calculate the effective resolution preferences. -extern HostResStyle ats_host_res_from(int family, ///< Connection family - HostResPreferenceOrder ///< Preference ordering. +extern HostResStyle ats_host_res_from(int family, ///< Connection family + HostResPreferenceOrder const & ///< Preference ordering. ); /// Calculate the host resolution style to force a family match to @a addr. extern HostResStyle ats_host_res_match(sockaddr const *addr); diff --git a/proxy/ProxySession.h b/proxy/ProxySession.h index 3689f3fdba6..4770683f2bd 100644 --- a/proxy/ProxySession.h +++ b/proxy/ProxySession.h @@ -150,8 +150,6 @@ class ProxySession : public VConnection HttpSessionAccept::Options const *accept_options; ///< connection info // L7R TODO: set in constructor - HostResStyle host_res_style = HOST_RES_NONE; ///< DNS resolution preferences. - ink_hrtime ssn_start_time = 0; ink_hrtime ssn_last_txn_time = 0; diff --git a/proxy/ProxyTransaction.cc b/proxy/ProxyTransaction.cc index 53a77e42d75..0177924f577 100644 --- a/proxy/ProxyTransaction.cc +++ b/proxy/ProxyTransaction.cc @@ -193,18 +193,6 @@ ProxyTransaction::clear_session_active() } } -/// DNS resolution preferences. -HostResStyle -ProxyTransaction::get_host_res_style() const -{ - return host_res_style; -} -void -ProxyTransaction::set_host_res_style(HostResStyle style) -{ - host_res_style = style; -} - const IpAllow::ACL & ProxyTransaction::get_acl() const { @@ -268,8 +256,7 @@ ProxyTransaction::get_proxy_ssn() void ProxyTransaction::set_proxy_ssn(ProxySession *new_proxy_ssn) { - proxy_ssn = new_proxy_ssn; - host_res_style = proxy_ssn->host_res_style; + proxy_ssn = new_proxy_ssn; } void diff --git a/proxy/ProxyTransaction.h b/proxy/ProxyTransaction.h index 874bcd05f99..245c05b5672 100644 --- a/proxy/ProxyTransaction.h +++ b/proxy/ProxyTransaction.h @@ -120,9 +120,7 @@ class ProxyTransaction : public VConnection HttpSM *current_reader = nullptr; IOBufferReader *sm_reader = nullptr; - /// DNS resolution preferences. - HostResStyle host_res_style = HOST_RES_NONE; - bool restart_immediate = false; + bool restart_immediate = false; private: }; diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc index 56e4a4e191a..c03060590f7 100644 --- a/proxy/http/HttpSM.cc +++ b/proxy/http/HttpSM.cc @@ -481,6 +481,12 @@ HttpSM::attach_client_session(ProxyTransaction *client_vc, IOBufferReader *buffe debug_on = true; } + ink_assert(ua_txn->get_proxy_ssn()); + ink_assert(ua_txn->get_proxy_ssn()->accept_options); + // default the upstream IP style host resolution from inbound + t_state.dns_info.host_res_style = + ats_host_res_from(netvc->get_local_addr()->sa_family, ua_txn->get_proxy_ssn()->accept_options->host_res_preference); + start_sub_sm(); // Allocate a user agent entry in the state machine's @@ -2217,7 +2223,7 @@ HttpSM::state_hostdb_lookup(int event, void *data) opt.flags = (t_state.cache_info.directives.does_client_permit_dns_storing) ? HostDBProcessor::HOSTDB_DO_NOT_FORCE_DNS : HostDBProcessor::HOSTDB_FORCE_DNS_RELOAD; opt.timeout = (t_state.api_txn_dns_timeout_value != -1) ? t_state.api_txn_dns_timeout_value : 0; - opt.host_res_style = ua_txn->get_host_res_style(); + opt.host_res_style = t_state.dns_info.host_res_style; Action *dns_lookup_action_handle = hostDBProcessor.getbyname_imm(this, (cb_process_result_pfn)&HttpSM::process_hostdb_info, host_name, 0, opt); @@ -3996,7 +4002,7 @@ HttpSM::do_hostdb_lookup() opt.flags = (t_state.cache_info.directives.does_client_permit_dns_storing) ? HostDBProcessor::HOSTDB_DO_NOT_FORCE_DNS : HostDBProcessor::HOSTDB_FORCE_DNS_RELOAD; opt.timeout = (t_state.api_txn_dns_timeout_value != -1) ? t_state.api_txn_dns_timeout_value : 0; - opt.host_res_style = ua_txn->get_host_res_style(); + opt.host_res_style = t_state.dns_info.host_res_style; Action *dns_lookup_action_handle = hostDBProcessor.getbyname_imm(this, (cb_process_result_pfn)&HttpSM::process_hostdb_info, host_name, 0, opt); @@ -4031,7 +4037,7 @@ HttpSM::do_hostdb_lookup() opt.flags = (t_state.cache_info.directives.does_client_permit_dns_storing) ? HostDBProcessor::HOSTDB_DO_NOT_FORCE_DNS : HostDBProcessor::HOSTDB_FORCE_DNS_RELOAD; opt.timeout = (t_state.api_txn_dns_timeout_value != -1) ? t_state.api_txn_dns_timeout_value : 0; - opt.host_res_style = ua_txn->get_host_res_style(); + opt.host_res_style = t_state.dns_info.host_res_style; Action *dns_lookup_action_handle = hostDBProcessor.getbyname_imm(this, (cb_process_result_pfn)&HttpSM::process_hostdb_info, t_state.dns_info.lookup_name, 0, opt); diff --git a/proxy/http/HttpSessionAccept.cc b/proxy/http/HttpSessionAccept.cc index 5c6b9a91b38..e7fd20fb4d5 100644 --- a/proxy/http/HttpSessionAccept.cc +++ b/proxy/http/HttpSessionAccept.cc @@ -52,7 +52,6 @@ HttpSessionAccept::accept(NetVConnection *netvc, MIOBuffer *iobuf, IOBufferReade Http1ClientSession *new_session = THREAD_ALLOC_INIT(http1ClientSessionAllocator, this_ethread()); new_session->accept_options = static_cast(this); - new_session->host_res_style = ats_host_res_from(client_ip->sa_family, host_res_preference); new_session->acl = std::move(acl); new_session->new_connection(netvc, iobuf, reader); diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc index 4dd837cd929..f5898f01676 100644 --- a/proxy/http/HttpTransact.cc +++ b/proxy/http/HttpTransact.cc @@ -3515,7 +3515,7 @@ HttpTransact::handle_response_from_server(State *s) // Force host resolution to have the same family as the client. // Because this is a transparent connection, we can't switch address // families - that is locked in by the client source address. - s->state_machine->ua_txn->set_host_res_style(ats_host_res_match(&s->current.server->dst_addr.sa)); + s->dns_info.host_res_style = ats_host_res_match(&s->current.server->dst_addr.sa); return CallOSDNSLookup(s); } else if ((s->dns_info.srv_lookup_success || s->host_db_info.is_rr_elt()) && (s->txn_conf->connect_attempts_rr_retries > 0) && diff --git a/proxy/http/HttpTransact.h b/proxy/http/HttpTransact.h index 6c713d3e046..f7bfef58cad 100644 --- a/proxy/http/HttpTransact.h +++ b/proxy/http/HttpTransact.h @@ -629,7 +629,8 @@ class HttpTransact OS_ADDR_USE_CLIENT ///< Use client target addr, no fallback. }; - OS_Addr os_addr_style = OS_Addr::OS_ADDR_TRY_DEFAULT; + OS_Addr os_addr_style = OS_Addr::OS_ADDR_TRY_DEFAULT; + HostResStyle host_res_style = HOST_RES_IPV4; bool lookup_success = false; char *lookup_name = nullptr; @@ -638,6 +639,7 @@ class HttpTransact bool srv_lookup_success = false; short srv_port = 0; HostDBApplicationInfo srv_app; + /*** Set to true by default. If use_client_target_address is set * to 1, this value will be set to false if the client address is * not in the DNS pool */ diff --git a/proxy/http2/Http2SessionAccept.cc b/proxy/http2/Http2SessionAccept.cc index a21cc253f41..7f68e64fd85 100644 --- a/proxy/http2/Http2SessionAccept.cc +++ b/proxy/http2/Http2SessionAccept.cc @@ -55,7 +55,6 @@ Http2SessionAccept::accept(NetVConnection *netvc, MIOBuffer *iobuf, IOBufferRead Http2ClientSession *new_session = THREAD_ALLOC_INIT(http2ClientSessionAllocator, this_ethread()); new_session->acl = std::move(session_acl); - new_session->host_res_style = ats_host_res_from(client_ip->sa_family, options.host_res_preference); new_session->accept_options = &options; new_session->new_connection(netvc, iobuf, reader); diff --git a/proxy/http3/Http09App.cc b/proxy/http3/Http09App.cc index 1749723d873..5635f7594c0 100644 --- a/proxy/http3/Http09App.cc +++ b/proxy/http3/Http09App.cc @@ -38,11 +38,8 @@ static constexpr char debug_tag_v[] = "v_quic_simple_app"; Http09App::Http09App(QUICNetVConnection *client_vc, IpAllow::ACL &&session_acl, const HttpSessionAccept::Options &options) : QUICApplication(client_vc) { - this->_ssn = new Http09Session(client_vc); - this->_ssn->acl = std::move(session_acl); - // TODO: avoid const cast - this->_ssn->host_res_style = - ats_host_res_from(client_vc->get_remote_addr()->sa_family, const_cast(options.host_res_preference)); + this->_ssn = new Http09Session(client_vc); + this->_ssn->acl = std::move(session_acl); this->_ssn->accept_options = &options; this->_ssn->new_connection(client_vc, nullptr, nullptr); diff --git a/proxy/http3/Http3App.cc b/proxy/http3/Http3App.cc index 53ec6d4ad5a..38f7fccabda 100644 --- a/proxy/http3/Http3App.cc +++ b/proxy/http3/Http3App.cc @@ -40,13 +40,9 @@ static constexpr char debug_tag_v[] = "v_http3"; Http3App::Http3App(QUICNetVConnection *client_vc, IpAllow::ACL &&session_acl, const HttpSessionAccept::Options &options) : QUICApplication(client_vc) { - this->_ssn = new Http3Session(client_vc); - this->_ssn->acl = std::move(session_acl); - // TODO: avoid const cast - this->_ssn->host_res_style = - ats_host_res_from(client_vc->get_remote_addr()->sa_family, const_cast(options.host_res_preference)); + this->_ssn = new Http3Session(client_vc); + this->_ssn->acl = std::move(session_acl); this->_ssn->accept_options = &options; - this->_ssn->new_connection(client_vc, nullptr, nullptr); this->_qc->stream_manager()->set_default_application(this); diff --git a/src/tscore/ink_res_mkquery.cc b/src/tscore/ink_res_mkquery.cc index 4615816832d..5e9db633142 100644 --- a/src/tscore/ink_res_mkquery.cc +++ b/src/tscore/ink_res_mkquery.cc @@ -510,7 +510,7 @@ ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) } HostResStyle -ats_host_res_from(int family, HostResPreferenceOrder order) +ats_host_res_from(int family, HostResPreferenceOrder const &order) { bool v4 = false, v6 = false; HostResPreference client = AF_INET6 == family ? HOST_RES_PREFER_IPV6 : HOST_RES_PREFER_IPV4; From dc03fc862d652c7583e0d9625e4a28d9921c8aa3 Mon Sep 17 00:00:00 2001 From: Aaron Canary Date: Fri, 23 Aug 2019 17:09:09 -0500 Subject: [PATCH 073/718] ProxyTxn: removed restart_immediate because it didn't do anything. + (cherry picked from commit dc1df9981a176cec2ca3de4b6f33e34807575bdb) --- proxy/ProxyTransaction.cc | 11 ----------- proxy/ProxyTransaction.h | 5 ----- proxy/http/Http1ClientSession.cc | 2 -- 3 files changed, 18 deletions(-) diff --git a/proxy/ProxyTransaction.cc b/proxy/ProxyTransaction.cc index 0177924f577..fb5a49a52ad 100644 --- a/proxy/ProxyTransaction.cc +++ b/proxy/ProxyTransaction.cc @@ -282,17 +282,6 @@ ProxyTransaction::get_protocol_string() return proxy_ssn ? proxy_ssn->get_protocol_string() : nullptr; } -void -ProxyTransaction::set_restart_immediate(bool val) -{ - restart_immediate = true; -} -bool -ProxyTransaction::get_restart_immediate() const -{ - return restart_immediate; -} - int ProxyTransaction::populate_protocol(std::string_view *result, int size) const { diff --git a/proxy/ProxyTransaction.h b/proxy/ProxyTransaction.h index 245c05b5672..d40e559dfd2 100644 --- a/proxy/ProxyTransaction.h +++ b/proxy/ProxyTransaction.h @@ -102,9 +102,6 @@ class ProxyTransaction : public VConnection Http1ServerSession *get_server_session() const; HttpSM *get_sm() const; - void set_restart_immediate(bool val); - bool get_restart_immediate() const; - // This function must return a non-negative number that is different for two in-progress transactions with the same proxy_ssn // session. // @@ -120,7 +117,5 @@ class ProxyTransaction : public VConnection HttpSM *current_reader = nullptr; IOBufferReader *sm_reader = nullptr; - bool restart_immediate = false; - private: }; diff --git a/proxy/http/Http1ClientSession.cc b/proxy/http/Http1ClientSession.cc index de6c81e9044..42583624580 100644 --- a/proxy/http/Http1ClientSession.cc +++ b/proxy/http/Http1ClientSession.cc @@ -424,12 +424,10 @@ Http1ClientSession::release(ProxyTransaction *trans) bool more_to_read = this->sm_reader->is_read_avail_more_than(0); if (more_to_read) { trans->destroy(); - trans->set_restart_immediate(true); HttpSsnDebug("[%" PRId64 "] data already in buffer, starting new transaction", con_id); new_transaction(); } else { HttpSsnDebug("[%" PRId64 "] initiating io for next header", con_id); - trans->set_restart_immediate(false); read_state = HCS_KEEP_ALIVE; SET_HANDLER(&Http1ClientSession::state_keep_alive); ka_vio = this->do_io_read(this, INT64_MAX, read_buffer); From a0d955185085f10df7d887c5bd7bcea52b8bc1e5 Mon Sep 17 00:00:00 2001 From: Aaron Canary Date: Tue, 27 Aug 2019 15:48:03 -0500 Subject: [PATCH 074/718] ProxySsn Refactor move code to cc Organizing Header files into something readable + + (cherry picked from commit c8ca9f69a777eab01953b6cb16c91e8d6ddcbca2) --- proxy/http/Http1ClientSession.cc | 83 +++++++++++++ proxy/http/Http1ClientSession.h | 108 +++------------- proxy/http/Http1ServerSession.cc | 40 ++++++ proxy/http/Http1ServerSession.h | 68 +++------- proxy/http/Http1Transaction.cc | 71 +++++++++++ proxy/http/Http1Transaction.h | 96 +++----------- proxy/http2/Http2ClientSession.cc | 122 ++++++++++++++++++ proxy/http2/Http2ClientSession.h | 166 ++++++------------------- proxy/http2/Http2Stream.cc | 125 +++++++++++++++++++ proxy/http2/Http2Stream.h | 200 ++++++++---------------------- 10 files changed, 583 insertions(+), 496 deletions(-) diff --git a/proxy/http/Http1ClientSession.cc b/proxy/http/Http1ClientSession.cc index 42583624580..87edda3934d 100644 --- a/proxy/http/Http1ClientSession.cc +++ b/proxy/http/Http1ClientSession.cc @@ -514,3 +514,86 @@ Http1ClientSession::decrement_current_active_client_connections_stat() { HTTP_DECREMENT_DYN_STAT(http_current_active_client_connections_stat); } + +void +Http1ClientSession::start() +{ + // Troll for data to get a new transaction + this->release(&trans); +} + +bool +Http1ClientSession::allow_half_open() const +{ + // Only allow half open connections if the not over TLS + return (client_vc && dynamic_cast(client_vc) == nullptr); +} + +void +Http1ClientSession::set_half_close_flag(bool flag) +{ + half_close = flag; +} + +bool +Http1ClientSession::get_half_close_flag() const +{ + return half_close; +} + +bool +Http1ClientSession::is_chunked_encoding_supported() const +{ + return true; +} + +NetVConnection * +Http1ClientSession::get_netvc() const +{ + return client_vc; +} + +int +Http1ClientSession::get_transact_count() const +{ + return transact_count; +} + +bool +Http1ClientSession::is_outbound_transparent() const +{ + return f_outbound_transparent; +} + +Http1ServerSession * +Http1ClientSession::get_server_session() const +{ + return bound_ss; +} + +void +Http1ClientSession::set_active_timeout(ink_hrtime timeout_in) +{ + if (client_vc) + client_vc->set_active_timeout(timeout_in); +} + +void +Http1ClientSession::set_inactivity_timeout(ink_hrtime timeout_in) +{ + if (client_vc) + client_vc->set_inactivity_timeout(timeout_in); +} + +void +Http1ClientSession::cancel_inactivity_timeout() +{ + if (client_vc) + client_vc->cancel_inactivity_timeout(); +} + +const char * +Http1ClientSession::get_protocol_string() const +{ + return "http"; +} diff --git a/proxy/http/Http1ClientSession.h b/proxy/http/Http1ClientSession.h index 60542ee1b8b..7403d42bba0 100644 --- a/proxy/http/Http1ClientSession.h +++ b/proxy/http/Http1ClientSession.h @@ -53,18 +53,14 @@ class Http1ClientSession : public ProxySession Http1ClientSession(); // Implement ProxySession interface. + void new_connection(NetVConnection *new_vc, MIOBuffer *iobuf, IOBufferReader *reader) override; + void start() override; + void release(ProxyTransaction *trans) override; // Indicate we are done with a transaction + void release_transaction(); void destroy() override; void free() override; - void release_transaction(); - void - start() override - { - // Troll for data to get a new transaction - this->release(&trans); - } - - void new_connection(NetVConnection *new_vc, MIOBuffer *iobuf, IOBufferReader *reader) override; + void attach_server_session(Http1ServerSession *ssession, bool transaction_done = true) override; // Implement VConnection interface. VIO *do_io_read(Continuation *c, int64_t nbytes = INT64_MAX, MIOBuffer *buf = nullptr) override; @@ -75,86 +71,20 @@ class Http1ClientSession : public ProxySession void do_io_shutdown(ShutdownHowTo_t howto) override; void reenable(VIO *vio) override; - bool - allow_half_open() - { - // Only allow half open connections if the not over TLS - return (client_vc && dynamic_cast(client_vc) == nullptr); - } - - void - set_half_close_flag(bool flag) override - { - half_close = flag; - } - - bool - get_half_close_flag() const override - { - return half_close; - } - - bool - is_chunked_encoding_supported() const override - { - return true; - } - - NetVConnection * - get_netvc() const override - { - return client_vc; - } - - int - get_transact_count() const override - { - return transact_count; - } - - virtual bool - is_outbound_transparent() const - { - return f_outbound_transparent; - } - - // Indicate we are done with a transaction - void release(ProxyTransaction *trans) override; - - void attach_server_session(Http1ServerSession *ssession, bool transaction_done = true) override; - - Http1ServerSession * - get_server_session() const override - { - return bound_ss; - } - - void - set_active_timeout(ink_hrtime timeout_in) override - { - if (client_vc) - client_vc->set_active_timeout(timeout_in); - } - - void - set_inactivity_timeout(ink_hrtime timeout_in) override - { - if (client_vc) - client_vc->set_inactivity_timeout(timeout_in); - } - - void - cancel_inactivity_timeout() override - { - if (client_vc) - client_vc->cancel_inactivity_timeout(); - } - - const char * - get_protocol_string() const override - { - return "http"; - } + // Accessor Methods + bool allow_half_open() const; + void set_half_close_flag(bool flag) override; + bool get_half_close_flag() const override; + bool is_chunked_encoding_supported() const override; + NetVConnection *get_netvc() const override; + int get_transact_count() const override; + virtual bool is_outbound_transparent() const; + + Http1ServerSession *get_server_session() const override; + void set_active_timeout(ink_hrtime timeout_in) override; + void set_inactivity_timeout(ink_hrtime timeout_in) override; + void cancel_inactivity_timeout() override; + const char *get_protocol_string() const override; void increment_current_active_client_connections_stat() override; void decrement_current_active_client_connections_stat() override; diff --git a/proxy/http/Http1ServerSession.cc b/proxy/http/Http1ServerSession.cc index 23d7b53c228..23ba7b3dbc3 100644 --- a/proxy/http/Http1ServerSession.cc +++ b/proxy/http/Http1ServerSession.cc @@ -203,3 +203,43 @@ Http1ServerSession::release() ink_assert(r == HSM_DONE); } } + +IOBufferReader * +Http1ServerSession::get_reader() +{ + return buf_reader; +}; + +NetVConnection * +Http1ServerSession::get_netvc() const +{ + return server_vc; +}; + +void +Http1ServerSession::set_netvc(NetVConnection *new_vc) +{ + server_vc = new_vc; +} + +// Keys for matching hostnames +IpEndpoint const & +Http1ServerSession::get_server_ip() const +{ + ink_release_assert(server_vc != nullptr); + return server_vc->get_remote_endpoint(); +} + +int +Http1ServerSession::populate_protocol(std::string_view *result, int size) const +{ + auto vc = this->get_netvc(); + return vc ? vc->populate_protocol(result, size) : 0; +} + +const char * +Http1ServerSession::protocol_contains(std::string_view tag_prefix) const +{ + auto vc = this->get_netvc(); + return vc ? vc->protocol_contains(tag_prefix) : nullptr; +} diff --git a/proxy/http/Http1ServerSession.h b/proxy/http/Http1ServerSession.h index e1851ef6f73..f558f3a7914 100644 --- a/proxy/http/Http1ServerSession.h +++ b/proxy/http/Http1ServerSession.h @@ -63,55 +63,32 @@ class Http1ServerSession : public VConnection Http1ServerSession(self_type const &) = delete; self_type &operator=(self_type const &) = delete; - void destroy(); + //////////////////// + // Methods void new_connection(NetVConnection *new_vc); + void release(); + void destroy(); - /** Enable tracking the number of outbound session. - * - * @param group The connection tracking group. - * - * The @a group must have already incremented the connection count. It will be cleaned up when the - * session terminates. - */ - void enable_outbound_connection_tracking(OutboundConnTrack::Group *group); - - IOBufferReader * - get_reader() - { - return buf_reader; - }; - + // VConnection Methods VIO *do_io_read(Continuation *c, int64_t nbytes = INT64_MAX, MIOBuffer *buf = nullptr) override; - VIO *do_io_write(Continuation *c = nullptr, int64_t nbytes = INT64_MAX, IOBufferReader *buf = nullptr, bool owner = false) override; - void do_io_close(int lerrno = -1) override; void do_io_shutdown(ShutdownHowTo_t howto) override; void reenable(VIO *vio) override; - void release(); + void enable_outbound_connection_tracking(OutboundConnTrack::Group *group); + IOBufferReader *get_reader(); void attach_hostname(const char *hostname); - NetVConnection * - get_netvc() const - { - return server_vc; - }; - void - set_netvc(NetVConnection *new_vc) - { - server_vc = new_vc; - } - - // Keys for matching hostnames - IpEndpoint const & - get_server_ip() const - { - ink_release_assert(server_vc != nullptr); - return server_vc->get_remote_endpoint(); - } - + NetVConnection *get_netvc() const; + void set_netvc(NetVConnection *new_vc); + IpEndpoint const &get_server_ip() const; + int populate_protocol(std::string_view *result, int size) const; + const char *protocol_contains(std::string_view tag_prefix) const; + + //////////////////// + // Variables CryptoHash hostname_hash; int64_t con_id = 0; @@ -136,7 +113,6 @@ class Http1ServerSession : public VConnection // Copy of the owning SM's server session sharing settings TSServerSessionSharingMatchType sharing_match = TS_SERVER_SESSION_SHARING_MATCH_BOTH; TSServerSessionSharingPoolType sharing_pool = TS_SERVER_SESSION_SHARING_POOL_GLOBAL; - // int share_session; /// Hash map descriptor class for IP map. struct IPLinkage { @@ -178,20 +154,6 @@ class Http1ServerSession : public VConnection // an asynchronous cancel on NT MIOBuffer *read_buffer = nullptr; - virtual int - populate_protocol(std::string_view *result, int size) const - { - auto vc = this->get_netvc(); - return vc ? vc->populate_protocol(result, size) : 0; - } - - virtual const char * - protocol_contains(std::string_view tag_prefix) const - { - auto vc = this->get_netvc(); - return vc ? vc->protocol_contains(tag_prefix) : nullptr; - } - private: NetVConnection *server_vc = nullptr; int magic = HTTP_SS_MAGIC_DEAD; diff --git a/proxy/http/Http1Transaction.cc b/proxy/http/Http1Transaction.cc index 6ccd2910339..e69991e5167 100644 --- a/proxy/http/Http1Transaction.cc +++ b/proxy/http/Http1Transaction.cc @@ -46,6 +46,11 @@ Http1Transaction::release(IOBufferReader *r) } } +void Http1Transaction::destroy() // todo make ~Http1Transaction() +{ + current_reader = nullptr; +} + void Http1Transaction::transaction_done() { @@ -54,6 +59,12 @@ Http1Transaction::transaction_done() } } +void +Http1Transaction::reenable(VIO *vio) +{ + proxy_ssn->reenable(vio); +} + bool Http1Transaction::allow_half_open() const { @@ -76,3 +87,63 @@ Http1Transaction::decrement_client_transactions_stat() { HTTP_DECREMENT_DYN_STAT(http_current_client_transactions_stat); } + +// Implement VConnection interface. +VIO * +Http1Transaction::do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf) +{ + return proxy_ssn->do_io_read(c, nbytes, buf); +} +VIO * +Http1Transaction::do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *buf, bool owner) +{ + return proxy_ssn->do_io_write(c, nbytes, buf, owner); +} + +void +Http1Transaction::do_io_close(int lerrno) +{ + proxy_ssn->do_io_close(lerrno); + // this->destroy(); Parent owns this data structure. No need for separate destroy. +} + +void +Http1Transaction::do_io_shutdown(ShutdownHowTo_t howto) +{ + proxy_ssn->do_io_shutdown(howto); +} + +void +Http1Transaction::set_reader(IOBufferReader *reader) +{ + sm_reader = reader; +} + +void +Http1Transaction::set_active_timeout(ink_hrtime timeout_in) +{ + if (proxy_ssn) + proxy_ssn->set_active_timeout(timeout_in); +} +void +Http1Transaction::set_inactivity_timeout(ink_hrtime timeout_in) +{ + if (proxy_ssn) + proxy_ssn->set_inactivity_timeout(timeout_in); +} +void +Http1Transaction::cancel_inactivity_timeout() +{ + if (proxy_ssn) + proxy_ssn->cancel_inactivity_timeout(); +} +// +int +Http1Transaction::get_transaction_id() const +{ + // For HTTP/1 there is only one on-going transaction at a time per session/connection. Therefore, the transaction count can be + // presumed not to increase during the lifetime of a transaction, thus this function will return a consistent unique transaction + // identifier. + // + return proxy_ssn->get_transact_count(); +} diff --git a/proxy/http/Http1Transaction.h b/proxy/http/Http1Transaction.h index eccd8334752..3c3215d7580 100644 --- a/proxy/http/Http1Transaction.h +++ b/proxy/http/Http1Transaction.h @@ -33,90 +33,34 @@ class Http1Transaction : public ProxyTransaction using super_type = ProxyTransaction; Http1Transaction() {} - // Implement VConnection interface. - VIO * - do_io_read(Continuation *c, int64_t nbytes = INT64_MAX, MIOBuffer *buf = nullptr) override - { - return proxy_ssn->do_io_read(c, nbytes, buf); - } - VIO * - do_io_write(Continuation *c = nullptr, int64_t nbytes = INT64_MAX, IOBufferReader *buf = nullptr, bool owner = false) override - { - return proxy_ssn->do_io_write(c, nbytes, buf, owner); - } - - void - do_io_close(int lerrno = -1) override - { - proxy_ssn->do_io_close(lerrno); - // this->destroy(); Parent owns this data structure. No need for separate destroy. - } - - // Don't destroy your elements. Rely on the Http1ClientSession to clean up the - // Http1Transaction class as necessary. The super::destroy() clears the - // mutex, which Http1ClientSession owns. - void - destroy() override - { - current_reader = nullptr; - } - - void - do_io_shutdown(ShutdownHowTo_t howto) override - { - proxy_ssn->do_io_shutdown(howto); - } - - void - reenable(VIO *vio) override - { - proxy_ssn->reenable(vio); - } - - void - set_reader(IOBufferReader *reader) - { - sm_reader = reader; - } + //////////////////// + // Methods void release(IOBufferReader *r) override; + void destroy() override; // todo make ~Http1Transaction() - bool allow_half_open() const override; + // Implement VConnection interface. + VIO *do_io_read(Continuation *c, int64_t nbytes = INT64_MAX, MIOBuffer *buf = nullptr) override; + VIO *do_io_write(Continuation *c = nullptr, int64_t nbytes = INT64_MAX, IOBufferReader *buf = nullptr, + bool owner = false) override; + void do_io_close(int lerrno = -1) override; + void do_io_shutdown(ShutdownHowTo_t howto) override; + void reenable(VIO *vio) override; - // Pass on the timeouts to the netvc - void - set_active_timeout(ink_hrtime timeout_in) override - { - if (proxy_ssn) - proxy_ssn->set_active_timeout(timeout_in); - } - void - set_inactivity_timeout(ink_hrtime timeout_in) override - { - if (proxy_ssn) - proxy_ssn->set_inactivity_timeout(timeout_in); - } - void - cancel_inactivity_timeout() override - { - if (proxy_ssn) - proxy_ssn->cancel_inactivity_timeout(); - } + bool allow_half_open() const override; + void set_active_timeout(ink_hrtime timeout_in) override; + void set_inactivity_timeout(ink_hrtime timeout_in) override; + void cancel_inactivity_timeout() override; void transaction_done() override; - - int - get_transaction_id() const override - { - // For HTTP/1 there is only one on-going transaction at a time per session/connection. Therefore, the transaction count can be - // presumed not to increase during the lifetime of a transaction, thus this function will return a consistent unique transaction - // identifier. - // - return proxy_ssn->get_transact_count(); - } - + int get_transaction_id() const override; void increment_client_transactions_stat() override; void decrement_client_transactions_stat() override; + void set_reader(IOBufferReader *reader); + + //////////////////// + // Variables + protected: bool outbound_transparent{false}; }; diff --git a/proxy/http2/Http2ClientSession.cc b/proxy/http2/Http2ClientSession.cc index a4658d5b319..f52155c2bbe 100644 --- a/proxy/http2/Http2ClientSession.cc +++ b/proxy/http2/Http2ClientSession.cc @@ -649,3 +649,125 @@ Http2ClientSession::_should_do_something_else() // Do something else every 128 incoming frames return (this->_n_frame_read & 0x7F) == 0; } + +bool +Http2ClientSession::ready_to_free() const +{ + return kill_me; +} + +NetVConnection * +Http2ClientSession::get_netvc() const +{ + return client_vc; +} + +sockaddr const * +Http2ClientSession::get_client_addr() +{ + return client_vc ? client_vc->get_remote_addr() : &cached_client_addr.sa; +} + +sockaddr const * +Http2ClientSession::get_local_addr() +{ + return client_vc ? client_vc->get_local_addr() : &cached_local_addr.sa; +} +void +Http2ClientSession::write_reenable() +{ + write_vio->reenable(); +} + +const Http2UpgradeContext & +Http2ClientSession::get_upgrade_context() const +{ + return upgrade_context; +} + +int +Http2ClientSession::get_transact_count() const +{ + return connection_state.get_stream_requests(); +} + +void +Http2ClientSession::release(ProxyTransaction *trans) +{ +} + +void +Http2ClientSession::set_dying_event(int event) +{ + dying_event = event; +} + +int +Http2ClientSession::get_dying_event() const +{ + return dying_event; +} + +bool +Http2ClientSession::is_recursing() const +{ + return recursion > 0; +} + +const char * +Http2ClientSession::get_protocol_string() const +{ + return "http/2"; +} + +int +Http2ClientSession::populate_protocol(std::string_view *result, int size) const +{ + int retval = 0; + if (size > retval) { + result[retval++] = IP_PROTO_TAG_HTTP_2_0; + if (size > retval) { + retval += super::populate_protocol(result + retval, size - retval); + } + } + return retval; +} + +const char * +Http2ClientSession::protocol_contains(std::string_view prefix) const +{ + const char *retval = nullptr; + + if (prefix.size() <= IP_PROTO_TAG_HTTP_2_0.size() && strncmp(IP_PROTO_TAG_HTTP_2_0.data(), prefix.data(), prefix.size()) == 0) { + retval = IP_PROTO_TAG_HTTP_2_0.data(); + } else { + retval = super::protocol_contains(prefix); + } + return retval; +} + +bool +Http2ClientSession::get_half_close_local_flag() const +{ + return half_close_local; +} + +bool +Http2ClientSession::is_url_pushed(const char *url, int url_len) +{ + return h2_pushed_urls.find(url) != h2_pushed_urls.end(); +} + +void +Http2ClientSession::add_url_to_pushed_table(const char *url, int url_len) +{ + if (h2_pushed_urls.size() < Http2::push_diary_size) { + h2_pushed_urls.emplace(url); + } +} + +int64_t +Http2ClientSession::write_buffer_size() +{ + return write_buffer->max_read_avail(); +} diff --git a/proxy/http2/Http2ClientSession.h b/proxy/http2/Http2ClientSession.h index 433be890b73..48df0f00b61 100644 --- a/proxy/http2/Http2ClientSession.h +++ b/proxy/http2/Http2ClientSession.h @@ -160,148 +160,54 @@ class Http2Frame class Http2ClientSession : public ProxySession { public: - typedef ProxySession super; ///< Parent type. - typedef int (Http2ClientSession::*SessionHandler)(int, void *); + using super = ProxySession; ///< Parent type. + using SessionHandler = int (Http2ClientSession::*)(int, void *); Http2ClientSession(); - // Implement ProxySession interface. - void start() override; - void destroy() override; - void free() override; - void new_connection(NetVConnection *new_vc, MIOBuffer *iobuf, IOBufferReader *reader) override; + ///////////////////// + // Methods - bool - ready_to_free() const - { - return kill_me; - } - - // Implement VConnection interface. + // Implement VConnection interface VIO *do_io_read(Continuation *c, int64_t nbytes = INT64_MAX, MIOBuffer *buf = nullptr) override; - VIO *do_io_write(Continuation *c = nullptr, int64_t nbytes = INT64_MAX, IOBufferReader *buf = nullptr, - bool owner = false) override; + VIO *do_io_write(Continuation *c = nullptr, int64_t nbytes = INT64_MAX, IOBufferReader *buf = 0, bool owner = false) override; void do_io_close(int lerrno = -1) override; void do_io_shutdown(ShutdownHowTo_t howto) override; void reenable(VIO *vio) override; - NetVConnection * - get_netvc() const override - { - return client_vc; - } - - sockaddr const * - get_client_addr() override - { - return client_vc ? client_vc->get_remote_addr() : &cached_client_addr.sa; - } - - sockaddr const * - get_local_addr() override - { - return client_vc ? client_vc->get_local_addr() : &cached_local_addr.sa; - } - - void - write_reenable() - { - write_vio->reenable(); - } - - void set_upgrade_context(HTTPHdr *h); - - const Http2UpgradeContext & - get_upgrade_context() const - { - return upgrade_context; - } - - int - get_transact_count() const override - { - return connection_state.get_stream_requests(); - } - - void - release(ProxyTransaction *trans) override - { - } - - Http2ConnectionState connection_state; - void - set_dying_event(int event) - { - dying_event = event; - } - - int - get_dying_event() const - { - return dying_event; - } - - bool - is_recursing() const - { - return recursion > 0; - } - - const char * - get_protocol_string() const override - { - return "http/2"; - } - - int - populate_protocol(std::string_view *result, int size) const override - { - int retval = 0; - if (size > retval) { - result[retval++] = IP_PROTO_TAG_HTTP_2_0; - if (size > retval) { - retval += super::populate_protocol(result + retval, size - retval); - } - } - return retval; - } - - const char * - protocol_contains(std::string_view prefix) const override - { - const char *retval = nullptr; - - if (prefix.size() <= IP_PROTO_TAG_HTTP_2_0.size() && strncmp(IP_PROTO_TAG_HTTP_2_0.data(), prefix.data(), prefix.size()) == 0) { - retval = IP_PROTO_TAG_HTTP_2_0.data(); - } else { - retval = super::protocol_contains(prefix); - } - return retval; - } + // Implement ProxySession interface + void new_connection(NetVConnection *new_vc, MIOBuffer *iobuf, IOBufferReader *reader) override; + void start() override; + void destroy() override; + void release(ProxyTransaction *trans) override; + void free() override; + // more methods + void write_reenable(); + + //////////////////// + // Accessors + NetVConnection *get_netvc() const override; + sockaddr const *get_client_addr() override; + sockaddr const *get_local_addr() override; + int get_transact_count() const override; + const char *get_protocol_string() const override; + int populate_protocol(std::string_view *result, int size) const override; + const char *protocol_contains(std::string_view prefix) const override; void increment_current_active_client_connections_stat() override; void decrement_current_active_client_connections_stat() override; + void set_upgrade_context(HTTPHdr *h); + const Http2UpgradeContext &get_upgrade_context() const; + void set_dying_event(int event); + int get_dying_event() const; + bool ready_to_free() const; + bool is_recursing() const; void set_half_close_local_flag(bool flag); - bool - get_half_close_local_flag() const - { - return half_close_local; - } - - bool - is_url_pushed(const char *url, int url_len) - { - return h2_pushed_urls.find(url) != h2_pushed_urls.end(); - } - - void - add_url_to_pushed_table(const char *url, int url_len) - { - if (h2_pushed_urls.size() < Http2::push_diary_size) { - h2_pushed_urls.emplace(url); - } - } + bool get_half_close_local_flag() const; + bool is_url_pushed(const char *url, int url_len); + void add_url_to_pushed_table(const char *url, int url_len); + int64_t write_buffer_size(); // Record history from Http2ConnectionState void remember(const SourceLocation &location, int event, int reentrant = NO_REENTRANT); @@ -310,6 +216,10 @@ class Http2ClientSession : public ProxySession Http2ClientSession(Http2ClientSession &) = delete; Http2ClientSession &operator=(const Http2ClientSession &) = delete; + /////////////////// + // Variables + Http2ConnectionState connection_state; + private: int main_event_handler(int, void *); diff --git a/proxy/http2/Http2Stream.cc b/proxy/http2/Http2Stream.cc index 8bdb1633d7c..2694a334b51 100644 --- a/proxy/http2/Http2Stream.cc +++ b/proxy/http2/Http2Stream.cc @@ -38,6 +38,27 @@ ClassAllocator http2StreamAllocator("http2StreamAllocator"); +Http2Stream::Http2Stream(Http2StreamId sid, ssize_t initial_rwnd) : _id(sid), _client_rwnd(initial_rwnd) +{ + SET_HANDLER(&Http2Stream::main_event_handler); +} + +void +Http2Stream::init(Http2StreamId sid, ssize_t initial_rwnd) +{ + this->mark_milestone(Http2StreamMilestone::OPEN); + + this->_id = sid; + this->_thread = this_ethread(); + this->_client_rwnd = initial_rwnd; + + sm_reader = request_reader = request_buffer.alloc_reader(); + // FIXME: Are you sure? every "stream" needs request_header? + _req_header.create(HTTP_TYPE_REQUEST); + response_header.create(HTTP_TYPE_RESPONSE); + http_parser_init(&http_parser); +} + int Http2Stream::main_event_handler(int event, void *edata) { @@ -1037,3 +1058,107 @@ Http2Stream::_switch_thread_if_not_on_right_thread(int event, void *edata) } return true; } + +bool +Http2Stream::is_body_done() const +{ + return body_done; +} + +void +Http2Stream::mark_body_done() +{ + body_done = true; + if (response_is_chunked()) { + ink_assert(chunked_handler.state == ChunkedHandler::CHUNK_READ_DONE || + chunked_handler.state == ChunkedHandler::CHUNK_READ_ERROR); + this->write_vio.nbytes = response_header.length_get() + chunked_handler.dechunked_size; + } +} + +void +Http2Stream::update_sent_count(unsigned num_bytes) +{ + bytes_sent += num_bytes; + this->write_vio.ndone += num_bytes; +} + +Http2StreamId +Http2Stream::get_id() const +{ + return _id; +} + +int +Http2Stream::get_transaction_id() const +{ + return _id; +} + +Http2StreamState +Http2Stream::get_state() const +{ + return _state; +} + +void +Http2Stream::update_initial_rwnd(Http2WindowSize new_size) +{ + this->_client_rwnd = new_size; +} + +bool +Http2Stream::has_trailing_header() const +{ + return trailing_header; +} + +void +Http2Stream::set_request_headers(HTTPHdr &h2_headers) +{ + _req_header.copy(&h2_headers); +} + +// Check entire DATA payload length if content-length: header is exist +void +Http2Stream::increment_data_length(uint64_t length) +{ + data_length += length; +} + +bool +Http2Stream::payload_length_is_valid() const +{ + uint32_t content_length = _req_header.get_content_length(); + return content_length == 0 || content_length == data_length; +} + +bool +Http2Stream::response_is_chunked() const +{ + return chunked; +} + +bool +Http2Stream::allow_half_open() const +{ + return false; +} + +bool +Http2Stream::is_client_state_writeable() const +{ + return _state == Http2StreamState::HTTP2_STREAM_STATE_OPEN || _state == Http2StreamState::HTTP2_STREAM_STATE_HALF_CLOSED_REMOTE || + _state == Http2StreamState::HTTP2_STREAM_STATE_RESERVED_LOCAL; +} +bool +Http2Stream::is_closed() const +{ + return closed; +} + +bool +Http2Stream::is_first_transaction() const +{ + return is_first_transaction_flag; +} diff --git a/proxy/http2/Http2Stream.h b/proxy/http2/Http2Stream.h index 8b747bd560c..8b0489b0c7d 100644 --- a/proxy/http2/Http2Stream.h +++ b/proxy/http2/Http2Stream.h @@ -50,122 +50,31 @@ enum class Http2StreamMilestone { class Http2Stream : public ProxyTransaction { public: - typedef ProxyTransaction super; ///< Parent type. - Http2Stream(Http2StreamId sid = 0, ssize_t initial_rwnd = Http2::initial_window_size) : _id(sid), _client_rwnd(initial_rwnd) - { - SET_HANDLER(&Http2Stream::main_event_handler); - } - - void - init(Http2StreamId sid, ssize_t initial_rwnd) - { - this->mark_milestone(Http2StreamMilestone::OPEN); - - this->_id = sid; - this->_thread = this_ethread(); - this->_client_rwnd = initial_rwnd; - - sm_reader = request_reader = request_buffer.alloc_reader(); - // FIXME: Are you sure? every "stream" needs request_header? - _req_header.create(HTTP_TYPE_REQUEST); - response_header.create(HTTP_TYPE_RESPONSE); - http_parser_init(&http_parser); - } + using super = ProxyTransaction; ///< Parent type. - int main_event_handler(int event, void *edata); - - void destroy() override; + Http2Stream(Http2StreamId sid = 0, ssize_t initial_rwnd = Http2::initial_window_size); - bool - is_body_done() const - { - return body_done; - } - - void - mark_body_done() - { - body_done = true; - if (response_is_chunked()) { - ink_assert(chunked_handler.state == ChunkedHandler::CHUNK_READ_DONE || - chunked_handler.state == ChunkedHandler::CHUNK_READ_ERROR); - this->write_vio.nbytes = response_header.length_get() + chunked_handler.dechunked_size; - } - } - - void - update_sent_count(unsigned num_bytes) - { - bytes_sent += num_bytes; - this->write_vio.ndone += num_bytes; - } - - Http2StreamId - get_id() const - { - return _id; - } - - int - get_transaction_id() const override - { - return _id; - } - - Http2StreamState - get_state() const - { - return _state; - } + void init(Http2StreamId sid, ssize_t initial_rwnd); - bool change_state(uint8_t type, uint8_t flags); + int main_event_handler(int event, void *edata); - void - update_initial_rwnd(Http2WindowSize new_size) - { - this->_client_rwnd = new_size; - } - - bool - has_trailing_header() const - { - return trailing_header; - } - - void - set_request_headers(HTTPHdr &h2_headers) - { - _req_header.copy(&h2_headers); - } - - // Check entire DATA payload length if content-length: header is exist - void - increment_data_length(uint64_t length) - { - data_length += length; - } - - bool - payload_length_is_valid() const - { - uint32_t content_length = _req_header.get_content_length(); - return content_length == 0 || content_length == data_length; - } + void destroy() override; + void release(IOBufferReader *r) override; + void reenable(VIO *vio) override; + void transaction_done() override; - Http2ErrorCode decode_header_blocks(HpackHandle &hpack_handle, uint32_t maximum_table_size); - void send_request(Http2ConnectionState &cstate); + void do_io_shutdown(ShutdownHowTo_t) override {} VIO *do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf) override; VIO *do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *abuffer, bool owner = false) override; void do_io_close(int lerrno = -1) override; + + Http2ErrorCode decode_header_blocks(HpackHandle &hpack_handle, uint32_t maximum_table_size); + void send_request(Http2ConnectionState &cstate); void initiating_close(); void terminate_if_possible(); - void do_io_shutdown(ShutdownHowTo_t) override {} void update_read_request(int64_t read_len, bool send_update, bool check_eos = false); void update_write_request(IOBufferReader *buf_reader, int64_t write_len, bool send_update); void signal_write_event(bool call_update); - void reenable(VIO *vio) override; - void transaction_done() override; - void restart_sending(); void push_promise(URL &url, const MIMEField *accept_encoding); @@ -177,6 +86,44 @@ class Http2Stream : public ProxyTransaction Http2ErrorCode increment_server_rwnd(size_t amount); Http2ErrorCode decrement_server_rwnd(size_t amount); + ///////////////// + // Accessors + void set_active_timeout(ink_hrtime timeout_in) override; + void set_inactivity_timeout(ink_hrtime timeout_in) override; + void cancel_inactivity_timeout() override; + + bool allow_half_open() const override; + bool is_first_transaction() const override; + void increment_client_transactions_stat() override; + void decrement_client_transactions_stat() override; + int get_transaction_id() const override; + + void clear_inactive_timer(); + void clear_active_timer(); + void clear_timers(); + void clear_io_events(); + + bool is_client_state_writeable() const; + bool is_closed() const; + bool response_is_chunked() const; + IOBufferReader *response_get_data_reader() const; + + void mark_milestone(Http2StreamMilestone type); + + void increment_data_length(uint64_t length); + bool payload_length_is_valid() const; + bool is_body_done() const; + void mark_body_done(); + void update_sent_count(unsigned num_bytes); + Http2StreamId get_id() const; + Http2StreamState get_state() const; + bool change_state(uint8_t type, uint8_t flags); + void update_initial_rwnd(Http2WindowSize new_size); + bool has_trailing_header() const; + void set_request_headers(HTTPHdr &h2_headers); + + ////////////////// + // Variables uint8_t *header_blocks = nullptr; uint32_t header_blocks_length = 0; // total length of header blocks (not include // Padding or other fields) @@ -196,53 +143,6 @@ class Http2Stream : public ProxyTransaction MIOBuffer request_buffer = CLIENT_CONNECTION_FIRST_READ_BUFFER_SIZE_INDEX; Http2DependencyTree::Node *priority_node = nullptr; - IOBufferReader *response_get_data_reader() const; - bool - response_is_chunked() const - { - return chunked; - } - - void release(IOBufferReader *r) override; - - bool - allow_half_open() const override - { - return false; - } - - void set_active_timeout(ink_hrtime timeout_in) override; - void set_inactivity_timeout(ink_hrtime timeout_in) override; - void cancel_inactivity_timeout() override; - void clear_inactive_timer(); - void clear_active_timer(); - void clear_timers(); - void clear_io_events(); - bool - is_client_state_writeable() const - { - return _state == Http2StreamState::HTTP2_STREAM_STATE_OPEN || - _state == Http2StreamState::HTTP2_STREAM_STATE_HALF_CLOSED_REMOTE || - _state == Http2StreamState::HTTP2_STREAM_STATE_RESERVED_LOCAL; - } - - bool - is_closed() const - { - return closed; - } - - bool - is_first_transaction() const override - { - return is_first_transaction_flag; - } - - void increment_client_transactions_stat() override; - void decrement_client_transactions_stat() override; - - void mark_milestone(Http2StreamMilestone type); - private: void response_initialize_data_handling(bool &is_done); void response_process_data(bool &is_done); From 3715017cbe8ef08becad05193edd6cebf8785ed0 Mon Sep 17 00:00:00 2001 From: Aaron Canary Date: Fri, 23 Aug 2019 11:33:04 -0500 Subject: [PATCH 075/718] ProxySsn renaming member vars to be more accurate and use naming conventions. (cherry picked from commit 7831fb058d8703edd681134dc0574758bac4d3fa) --- .../client-session-architecture.en.rst | 2 +- proxy/ProxyTransaction.cc | 82 ++++++++--------- proxy/ProxyTransaction.h | 6 +- proxy/http/Http1ClientSession.cc | 10 +- proxy/http/Http1ClientSession.h | 4 +- proxy/http/Http1Transaction.cc | 46 +++++----- proxy/http/HttpUpdateTester.cc | 6 +- proxy/http2/Http2ClientSession.cc | 32 +++---- proxy/http2/Http2ClientSession.h | 2 +- proxy/http2/Http2ConnectionState.cc | 10 +- proxy/http2/Http2Stream.cc | 92 +++++++++---------- proxy/http3/Http3Transaction.cc | 38 ++++---- 12 files changed, 165 insertions(+), 165 deletions(-) diff --git a/doc/developer-guide/client-session-architecture.en.rst b/doc/developer-guide/client-session-architecture.en.rst index fb32a81a0ef..65696df7fff 100644 --- a/doc/developer-guide/client-session-architecture.en.rst +++ b/doc/developer-guide/client-session-architecture.en.rst @@ -80,7 +80,7 @@ When the Http1Transaction object is instantiated via :code:`ProxyTransaction::ne new HttpSM object, initializes it, and calls :code:`HttpSM::attach_client_session()` to associate the Http1Transaction object with the new HttpSM. -The ProxyTransaction object refers to the HttpSM via the current_reader member variable. The HttpSM object +The ProxyTransaction object refers to the HttpSM via the _sm member variable. The HttpSM object refers to ProxyTransaction via the ua_session member variable (session in the member name is historical because the HttpSM used to refer directly to the ClientSession object). diff --git a/proxy/ProxyTransaction.cc b/proxy/ProxyTransaction.cc index fb5a49a52ad..47099a90ac0 100644 --- a/proxy/ProxyTransaction.cc +++ b/proxy/ProxyTransaction.cc @@ -32,51 +32,51 @@ ProxyTransaction::ProxyTransaction() : VConnection(nullptr) {} void ProxyTransaction::new_transaction() { - ink_assert(current_reader == nullptr); + ink_assert(_sm == nullptr); // Defensive programming, make sure nothing persists across // connection re-use - ink_release_assert(proxy_ssn != nullptr); - current_reader = HttpSM::allocate(); - current_reader->init(); - HttpTxnDebug("[%" PRId64 "] Starting transaction %d using sm [%" PRId64 "]", proxy_ssn->connection_id(), - proxy_ssn->get_transact_count(), current_reader->sm_id); + ink_release_assert(_proxy_ssn != nullptr); + _sm = HttpSM::allocate(); + _sm->init(); + HttpTxnDebug("[%" PRId64 "] Starting transaction %d using sm [%" PRId64 "]", _proxy_ssn->connection_id(), + _proxy_ssn->get_transact_count(), _sm->sm_id); PluginIdentity *pi = dynamic_cast(this->get_netvc()); if (pi) { - current_reader->plugin_tag = pi->getPluginTag(); - current_reader->plugin_id = pi->getPluginId(); + _sm->plugin_tag = pi->getPluginTag(); + _sm->plugin_id = pi->getPluginId(); } this->increment_client_transactions_stat(); - current_reader->attach_client_session(this, sm_reader); + _sm->attach_client_session(this, _reader); } void ProxyTransaction::release(IOBufferReader *r) { - HttpTxnDebug("[%" PRId64 "] session released by sm [%" PRId64 "]", proxy_ssn ? proxy_ssn->connection_id() : 0, - current_reader ? current_reader->sm_id : 0); + HttpTxnDebug("[%" PRId64 "] session released by sm [%" PRId64 "]", _proxy_ssn ? _proxy_ssn->connection_id() : 0, + _sm ? _sm->sm_id : 0); this->decrement_client_transactions_stat(); // Pass along the release to the session - if (proxy_ssn) { - proxy_ssn->release(this); + if (_proxy_ssn) { + _proxy_ssn->release(this); } } void ProxyTransaction::attach_server_session(Http1ServerSession *ssession, bool transaction_done) { - proxy_ssn->attach_server_session(ssession, transaction_done); + _proxy_ssn->attach_server_session(ssession, transaction_done); } void ProxyTransaction::destroy() { - current_reader = nullptr; + _sm = nullptr; this->mutex.clear(); } @@ -100,29 +100,29 @@ ProxyTransaction::adjust_thread(Continuation *cont, int event, void *data) void ProxyTransaction::set_rx_error_code(ProxyError e) { - if (this->current_reader) { - this->current_reader->t_state.client_info.rx_error_code = e; + if (this->_sm) { + this->_sm->t_state.client_info.rx_error_code = e; } } void ProxyTransaction::set_tx_error_code(ProxyError e) { - if (this->current_reader) { - this->current_reader->t_state.client_info.tx_error_code = e; + if (this->_sm) { + this->_sm->t_state.client_info.tx_error_code = e; } } NetVConnection * ProxyTransaction::get_netvc() const { - return (proxy_ssn) ? proxy_ssn->get_netvc() : nullptr; + return (_proxy_ssn) ? _proxy_ssn->get_netvc() : nullptr; } bool ProxyTransaction::is_first_transaction() const { - return proxy_ssn->get_transact_count() == 1; + return _proxy_ssn->get_transact_count() == 1; } // Ask your session if this is allowed bool @@ -134,21 +134,21 @@ ProxyTransaction::is_transparent_passthrough_allowed() bool ProxyTransaction::is_chunked_encoding_supported() const { - return proxy_ssn ? proxy_ssn->is_chunked_encoding_supported() : false; + return _proxy_ssn ? _proxy_ssn->is_chunked_encoding_supported() : false; } void ProxyTransaction::set_half_close_flag(bool flag) { - if (proxy_ssn) { - proxy_ssn->set_half_close_flag(flag); + if (_proxy_ssn) { + _proxy_ssn->set_half_close_flag(flag); } } bool ProxyTransaction::get_half_close_flag() const { - return proxy_ssn ? proxy_ssn->get_half_close_flag() : false; + return _proxy_ssn ? _proxy_ssn->get_half_close_flag() : false; } // What are the debug and hooks_enabled used for? How are they set? @@ -156,47 +156,47 @@ ProxyTransaction::get_half_close_flag() const bool ProxyTransaction::debug() const { - return proxy_ssn ? proxy_ssn->debug() : false; + return _proxy_ssn ? _proxy_ssn->debug() : false; } APIHook * ProxyTransaction::hook_get(TSHttpHookID id) const { - return proxy_ssn ? proxy_ssn->hook_get(id) : nullptr; + return _proxy_ssn ? _proxy_ssn->hook_get(id) : nullptr; } HttpAPIHooks const * ProxyTransaction::feature_hooks() const { - return proxy_ssn ? proxy_ssn->feature_hooks() : nullptr; + return _proxy_ssn ? _proxy_ssn->feature_hooks() : nullptr; } bool ProxyTransaction::has_hooks() const { - return proxy_ssn->has_hooks(); + return _proxy_ssn->has_hooks(); } void ProxyTransaction::set_session_active() { - if (proxy_ssn) { - proxy_ssn->set_session_active(); + if (_proxy_ssn) { + _proxy_ssn->set_session_active(); } } void ProxyTransaction::clear_session_active() { - if (proxy_ssn) { - proxy_ssn->clear_session_active(); + if (_proxy_ssn) { + _proxy_ssn->clear_session_active(); } } const IpAllow::ACL & ProxyTransaction::get_acl() const { - return proxy_ssn ? proxy_ssn->acl : IpAllow::DENY_ALL_ACL; + return _proxy_ssn ? _proxy_ssn->acl : IpAllow::DENY_ALL_ACL; } // outbound values Set via the server port definition. Really only used for Http1 at the moment @@ -250,13 +250,13 @@ ProxyTransaction::set_outbound_transparent(bool flag) ProxySession * ProxyTransaction::get_proxy_ssn() { - return proxy_ssn; + return _proxy_ssn; } void ProxyTransaction::set_proxy_ssn(ProxySession *new_proxy_ssn) { - proxy_ssn = new_proxy_ssn; + _proxy_ssn = new_proxy_ssn; } void @@ -267,29 +267,29 @@ ProxyTransaction::set_h2c_upgrade_flag() Http1ServerSession * ProxyTransaction::get_server_session() const { - return proxy_ssn ? proxy_ssn->get_server_session() : nullptr; + return _proxy_ssn ? _proxy_ssn->get_server_session() : nullptr; } HttpSM * ProxyTransaction::get_sm() const { - return current_reader; + return _sm; } const char * ProxyTransaction::get_protocol_string() { - return proxy_ssn ? proxy_ssn->get_protocol_string() : nullptr; + return _proxy_ssn ? _proxy_ssn->get_protocol_string() : nullptr; } int ProxyTransaction::populate_protocol(std::string_view *result, int size) const { - return proxy_ssn ? proxy_ssn->populate_protocol(result, size) : 0; + return _proxy_ssn ? _proxy_ssn->populate_protocol(result, size) : 0; } const char * ProxyTransaction::protocol_contains(std::string_view tag_prefix) const { - return proxy_ssn ? proxy_ssn->protocol_contains(tag_prefix) : nullptr; + return _proxy_ssn ? _proxy_ssn->protocol_contains(tag_prefix) : nullptr; } diff --git a/proxy/ProxyTransaction.h b/proxy/ProxyTransaction.h index d40e559dfd2..47999df2ff2 100644 --- a/proxy/ProxyTransaction.h +++ b/proxy/ProxyTransaction.h @@ -113,9 +113,9 @@ class ProxyTransaction : public VConnection HttpSessionAccept::Options upstream_outbound_options; // overwritable copy of options protected: - ProxySession *proxy_ssn = nullptr; - HttpSM *current_reader = nullptr; - IOBufferReader *sm_reader = nullptr; + ProxySession *_proxy_ssn = nullptr; + HttpSM *_sm = nullptr; + IOBufferReader *_reader = nullptr; private: }; diff --git a/proxy/http/Http1ClientSession.cc b/proxy/http/Http1ClientSession.cc index 87edda3934d..d5b2269ba20 100644 --- a/proxy/http/Http1ClientSession.cc +++ b/proxy/http/Http1ClientSession.cc @@ -186,8 +186,8 @@ Http1ClientSession::new_connection(NetVConnection *new_vc, MIOBuffer *iobuf, IOB client_vc->set_tcp_congestion_control(CLIENT_SIDE); read_buffer = iobuf ? iobuf : new_MIOBuffer(HTTP_HEADER_BUFFER_SIZE_INDEX); - sm_reader = reader ? reader : read_buffer->alloc_reader(); - trans.set_reader(sm_reader); + _reader = reader ? reader : read_buffer->alloc_reader(); + trans.set_reader(_reader); // INKqa11186: Use a local pointer to the mutex as // when we return from do_api_callout, the ClientSession may @@ -272,7 +272,7 @@ Http1ClientSession::do_io_close(int alerrno) // [bug 2610799] Drain any data read. // If the buffer is full and the client writes again, we will not receive a // READ_READY event. - sm_reader->consume(sm_reader->read_avail()); + _reader->consume(_reader->read_avail()); } else { read_state = HCS_CLOSED; HttpSsnDebug("[%" PRId64 "] session closed", con_id); @@ -312,7 +312,7 @@ Http1ClientSession::state_wait_for_close(int event, void *data) break; case VC_EVENT_READ_READY: // Drain any data read - sm_reader->consume(sm_reader->read_avail()); + _reader->consume(_reader->read_avail()); break; default: @@ -421,7 +421,7 @@ Http1ClientSession::release(ProxyTransaction *trans) // buffer. If there is, spin up a new state // machine to process it. Otherwise, issue an // IO to wait for new data - bool more_to_read = this->sm_reader->is_read_avail_more_than(0); + bool more_to_read = this->_reader->is_read_avail_more_than(0); if (more_to_read) { trans->destroy(); HttpSsnDebug("[%" PRId64 "] data already in buffer, starting new transaction", con_id); diff --git a/proxy/http/Http1ClientSession.h b/proxy/http/Http1ClientSession.h index 7403d42bba0..fd9afda0494 100644 --- a/proxy/http/Http1ClientSession.h +++ b/proxy/http/Http1ClientSession.h @@ -112,8 +112,8 @@ class Http1ClientSession : public ProxySession bool half_close = false; bool conn_decrease = false; - MIOBuffer *read_buffer = nullptr; - IOBufferReader *sm_reader = nullptr; + MIOBuffer *read_buffer = nullptr; + IOBufferReader *_reader = nullptr; C_Read_State read_state = HCS_INIT; diff --git a/proxy/http/Http1Transaction.cc b/proxy/http/Http1Transaction.cc index e69991e5167..73a161b4642 100644 --- a/proxy/http/Http1Transaction.cc +++ b/proxy/http/Http1Transaction.cc @@ -30,16 +30,16 @@ Http1Transaction::release(IOBufferReader *r) { // Must set this inactivity count here rather than in the session because the state machine // is not available then - MgmtInt ka_in = current_reader->t_state.txn_conf->keep_alive_no_activity_timeout_in; + MgmtInt ka_in = _sm->t_state.txn_conf->keep_alive_no_activity_timeout_in; set_inactivity_timeout(HRTIME_SECONDS(ka_in)); - proxy_ssn->clear_session_active(); - proxy_ssn->ssn_last_txn_time = Thread::get_hrtime(); + _proxy_ssn->clear_session_active(); + _proxy_ssn->ssn_last_txn_time = Thread::get_hrtime(); // Make sure that the state machine is returning // correct buffer reader - ink_assert(r == sm_reader); - if (r != sm_reader) { + ink_assert(r == _reader); + if (r != _reader) { this->do_io_close(); } else { super_type::release(r); @@ -48,30 +48,30 @@ Http1Transaction::release(IOBufferReader *r) void Http1Transaction::destroy() // todo make ~Http1Transaction() { - current_reader = nullptr; + _sm = nullptr; } void Http1Transaction::transaction_done() { - if (proxy_ssn) { - static_cast(proxy_ssn)->release_transaction(); + if (_proxy_ssn) { + static_cast(_proxy_ssn)->release_transaction(); } } void Http1Transaction::reenable(VIO *vio) { - proxy_ssn->reenable(vio); + _proxy_ssn->reenable(vio); } bool Http1Transaction::allow_half_open() const { - bool config_allows_it = (current_reader) ? current_reader->t_state.txn_conf->allow_half_open > 0 : true; + bool config_allows_it = (_sm) ? _sm->t_state.txn_conf->allow_half_open > 0 : true; if (config_allows_it) { // Check with the session to make sure the underlying transport allows the half open scenario - return static_cast(proxy_ssn)->allow_half_open(); + return static_cast(_proxy_ssn)->allow_half_open(); } return false; } @@ -92,50 +92,50 @@ Http1Transaction::decrement_client_transactions_stat() VIO * Http1Transaction::do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf) { - return proxy_ssn->do_io_read(c, nbytes, buf); + return _proxy_ssn->do_io_read(c, nbytes, buf); } VIO * Http1Transaction::do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *buf, bool owner) { - return proxy_ssn->do_io_write(c, nbytes, buf, owner); + return _proxy_ssn->do_io_write(c, nbytes, buf, owner); } void Http1Transaction::do_io_close(int lerrno) { - proxy_ssn->do_io_close(lerrno); + _proxy_ssn->do_io_close(lerrno); // this->destroy(); Parent owns this data structure. No need for separate destroy. } void Http1Transaction::do_io_shutdown(ShutdownHowTo_t howto) { - proxy_ssn->do_io_shutdown(howto); + _proxy_ssn->do_io_shutdown(howto); } void Http1Transaction::set_reader(IOBufferReader *reader) { - sm_reader = reader; + _reader = reader; } void Http1Transaction::set_active_timeout(ink_hrtime timeout_in) { - if (proxy_ssn) - proxy_ssn->set_active_timeout(timeout_in); + if (_proxy_ssn) + _proxy_ssn->set_active_timeout(timeout_in); } void Http1Transaction::set_inactivity_timeout(ink_hrtime timeout_in) { - if (proxy_ssn) - proxy_ssn->set_inactivity_timeout(timeout_in); + if (_proxy_ssn) + _proxy_ssn->set_inactivity_timeout(timeout_in); } void Http1Transaction::cancel_inactivity_timeout() { - if (proxy_ssn) - proxy_ssn->cancel_inactivity_timeout(); + if (_proxy_ssn) + _proxy_ssn->cancel_inactivity_timeout(); } // int @@ -145,5 +145,5 @@ Http1Transaction::get_transaction_id() const // presumed not to increase during the lifetime of a transaction, thus this function will return a consistent unique transaction // identifier. // - return proxy_ssn->get_transact_count(); + return _proxy_ssn->get_transact_count(); } diff --git a/proxy/http/HttpUpdateTester.cc b/proxy/http/HttpUpdateTester.cc index 581eafbe150..3841aa2b0f6 100644 --- a/proxy/http/HttpUpdateTester.cc +++ b/proxy/http/HttpUpdateTester.cc @@ -87,9 +87,9 @@ UpTest::make_requests() test_req.parse_req(&http_parser, &req, req + strlen(req), false); http_parser_clear(&http_parser); - HttpUpdateSM *current_reader = HttpUpdateSM::allocate(); - current_reader->init(); - Action *a = current_reader->start_scheduled_update(this, test_req); + HttpUpdateSM *_sm = HttpUpdateSM::allocate(); + _sm->init(); + Action *a = _sm->start_scheduled_update(this, test_req); (void)a; active_req++; diff --git a/proxy/http2/Http2ClientSession.cc b/proxy/http2/Http2ClientSession.cc index f52155c2bbe..3f754868ef1 100644 --- a/proxy/http2/Http2ClientSession.cc +++ b/proxy/http2/Http2ClientSession.cc @@ -176,7 +176,7 @@ Http2ClientSession::start() this->connection_state.init(); send_connection_event(&this->connection_state, HTTP2_SESSION_EVENT_INIT, this); - if (this->sm_reader->is_read_avail_more_than(0)) { + if (this->_reader->is_read_avail_more_than(0)) { this->handleEvent(VC_EVENT_READ_READY, read_vio); } } @@ -205,7 +205,7 @@ Http2ClientSession::new_connection(NetVConnection *new_vc, MIOBuffer *iobuf, IOB this->read_buffer = iobuf ? iobuf : new_MIOBuffer(HTTP2_HEADER_BUFFER_SIZE_INDEX); this->read_buffer->water_mark = connection_state.server_settings.get(HTTP2_SETTINGS_MAX_FRAME_SIZE); - this->sm_reader = reader ? reader : this->read_buffer->alloc_reader(); + this->_reader = reader ? reader : this->read_buffer->alloc_reader(); this->write_buffer = new_MIOBuffer(HTTP2_HEADER_BUFFER_SIZE_INDEX); this->sm_writer = this->write_buffer->alloc_reader(); @@ -430,11 +430,11 @@ Http2ClientSession::state_read_connection_preface(int event, void *edata) STATE_ENTER(&Http2ClientSession::state_read_connection_preface, event); ink_assert(event == VC_EVENT_READ_COMPLETE || event == VC_EVENT_READ_READY); - if (this->sm_reader->read_avail() >= static_cast(HTTP2_CONNECTION_PREFACE_LEN)) { + if (this->_reader->read_avail() >= static_cast(HTTP2_CONNECTION_PREFACE_LEN)) { char buf[HTTP2_CONNECTION_PREFACE_LEN]; unsigned nbytes; - nbytes = copy_from_buffer_reader(buf, this->sm_reader, sizeof(buf)); + nbytes = copy_from_buffer_reader(buf, this->_reader, sizeof(buf)); ink_release_assert(nbytes == HTTP2_CONNECTION_PREFACE_LEN); if (memcmp(HTTP2_CONNECTION_PREFACE, buf, nbytes) != 0) { @@ -444,7 +444,7 @@ Http2ClientSession::state_read_connection_preface(int event, void *edata) } Http2SsnDebug("received connection preface"); - this->sm_reader->consume(nbytes); + this->_reader->consume(nbytes); HTTP2_SET_SESSION_HANDLER(&Http2ClientSession::state_start_frame_read); client_vc->set_inactivity_timeout(HRTIME_SECONDS(Http2::no_activity_timeout_in)); @@ -453,7 +453,7 @@ Http2ClientSession::state_read_connection_preface(int event, void *edata) // XXX start the write VIO ... // If we have unconsumed data, start tranferring frames now. - if (this->sm_reader->is_read_avail_more_than(0)) { + if (this->_reader->is_read_avail_more_than(0)) { return this->handleEvent(VC_EVENT_READ_READY, vio); } } @@ -481,13 +481,13 @@ int Http2ClientSession::do_start_frame_read(Http2ErrorCode &ret_error) { ret_error = Http2ErrorCode::HTTP2_ERROR_NO_ERROR; - ink_release_assert(this->sm_reader->read_avail() >= (int64_t)HTTP2_FRAME_HEADER_LEN); + ink_release_assert(this->_reader->read_avail() >= (int64_t)HTTP2_FRAME_HEADER_LEN); uint8_t buf[HTTP2_FRAME_HEADER_LEN]; unsigned nbytes; Http2SsnDebug("receiving frame header"); - nbytes = copy_from_buffer_reader(buf, this->sm_reader, sizeof(buf)); + nbytes = copy_from_buffer_reader(buf, this->_reader, sizeof(buf)); if (!http2_parse_frame_header(make_iovec(buf), this->current_hdr)) { Http2SsnDebug("frame header parse failure"); @@ -498,7 +498,7 @@ Http2ClientSession::do_start_frame_read(Http2ErrorCode &ret_error) Http2SsnDebug("frame header length=%u, type=%u, flags=0x%x, streamid=%u", (unsigned)this->current_hdr.length, (unsigned)this->current_hdr.type, (unsigned)this->current_hdr.flags, this->current_hdr.streamid); - this->sm_reader->consume(nbytes); + this->_reader->consume(nbytes); if (!http2_frame_header_is_valid(this->current_hdr, this->connection_state.server_settings.get(HTTP2_SETTINGS_MAX_FRAME_SIZE))) { ret_error = Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR; @@ -528,7 +528,7 @@ Http2ClientSession::state_complete_frame_read(int event, void *edata) VIO *vio = static_cast(edata); STATE_ENTER(&Http2ClientSession::state_complete_frame_read, event); ink_assert(event == VC_EVENT_READ_COMPLETE || event == VC_EVENT_READ_READY); - if (this->sm_reader->read_avail() < this->current_hdr.length) { + if (this->_reader->read_avail() < this->current_hdr.length) { if (this->_should_do_something_else()) { if (this->_reenable_event == nullptr) { vio->disable(); @@ -541,7 +541,7 @@ Http2ClientSession::state_complete_frame_read(int event, void *edata) } return 0; } - Http2SsnDebug("completed frame read, %" PRId64 " bytes available", this->sm_reader->read_avail()); + Http2SsnDebug("completed frame read, %" PRId64 " bytes available", this->_reader->read_avail()); return state_process_frame_read(event, vio, true); } @@ -550,11 +550,11 @@ int Http2ClientSession::do_complete_frame_read() { // XXX parse the frame and handle it ... - ink_release_assert(this->sm_reader->read_avail() >= this->current_hdr.length); + ink_release_assert(this->_reader->read_avail() >= this->current_hdr.length); - Http2Frame frame(this->current_hdr, this->sm_reader); + Http2Frame frame(this->current_hdr, this->_reader); send_connection_event(&this->connection_state, HTTP2_SESSION_EVENT_RECV, &frame); - this->sm_reader->consume(this->current_hdr.length); + this->_reader->consume(this->current_hdr.length); ++(this->_n_frame_read); // Set the event handler if there is no more data to process a new frame @@ -570,7 +570,7 @@ Http2ClientSession::state_process_frame_read(int event, VIO *vio, bool inside_fr do_complete_frame_read(); } - while (this->sm_reader->read_avail() >= static_cast(HTTP2_FRAME_HEADER_LEN)) { + while (this->_reader->read_avail() >= static_cast(HTTP2_FRAME_HEADER_LEN)) { // Cancel reading if there was an error or connection is closed if (connection_state.tx_error_code.code != static_cast(Http2ErrorCode::HTTP2_ERROR_NO_ERROR) || connection_state.is_state_closed()) { @@ -603,7 +603,7 @@ Http2ClientSession::state_process_frame_read(int event, VIO *vio, bool inside_fr } // If there is no more data to finish the frame, set up the event handler and reenable - if (this->sm_reader->read_avail() < this->current_hdr.length) { + if (this->_reader->read_avail() < this->current_hdr.length) { HTTP2_SET_SESSION_HANDLER(&Http2ClientSession::state_complete_frame_read); break; } diff --git a/proxy/http2/Http2ClientSession.h b/proxy/http2/Http2ClientSession.h index 48df0f00b61..0bb9755485d 100644 --- a/proxy/http2/Http2ClientSession.h +++ b/proxy/http2/Http2ClientSession.h @@ -239,7 +239,7 @@ class Http2ClientSession : public ProxySession SessionHandler session_handler = nullptr; NetVConnection *client_vc = nullptr; MIOBuffer *read_buffer = nullptr; - IOBufferReader *sm_reader = nullptr; + IOBufferReader *_reader = nullptr; MIOBuffer *write_buffer = nullptr; IOBufferReader *sm_writer = nullptr; Http2FrameHeader current_hdr = {0, 0, 0, 0}; diff --git a/proxy/http2/Http2ConnectionState.cc b/proxy/http2/Http2ConnectionState.cc index ddf39ed4750..7fb41ce6f64 100644 --- a/proxy/http2/Http2ConnectionState.cc +++ b/proxy/http2/Http2ConnectionState.cc @@ -1451,17 +1451,17 @@ Http2ConnectionState::send_a_data_frame(Http2Stream *stream, size_t &payload_len uint8_t flags = 0x00; uint8_t payload_buffer[buf_len]; - IOBufferReader *current_reader = stream->response_get_data_reader(); + IOBufferReader *_sm = stream->response_get_data_reader(); SCOPED_MUTEX_LOCK(stream_lock, stream->mutex, this_ethread()); - if (!current_reader) { + if (!_sm) { Http2StreamDebug(this->ua_session, stream->get_id(), "couldn't get data reader"); return Http2SendDataFrameResult::ERROR; } // Select appropriate payload length - if (current_reader->is_read_avail_more_than(0)) { + if (_sm->is_read_avail_more_than(0)) { // We only need to check for window size when there is a payload if (window_size <= 0) { Http2StreamDebug(this->ua_session, stream->get_id(), "No window"); @@ -1469,7 +1469,7 @@ Http2ConnectionState::send_a_data_frame(Http2Stream *stream, size_t &payload_len } // Copy into the payload buffer. Seems like we should be able to skip this copy step payload_length = write_available_size; - payload_length = current_reader->read(payload_buffer, static_cast(write_available_size)); + payload_length = _sm->read(payload_buffer, static_cast(write_available_size)); } else { payload_length = 0; } @@ -1482,7 +1482,7 @@ Http2ConnectionState::send_a_data_frame(Http2Stream *stream, size_t &payload_len return Http2SendDataFrameResult::NO_PAYLOAD; } - if (stream->is_body_done() && !current_reader->is_read_avail_more_than(0)) { + if (stream->is_body_done() && !_sm->is_read_avail_more_than(0)) { flags |= HTTP2_FLAGS_DATA_END_STREAM; } diff --git a/proxy/http2/Http2Stream.cc b/proxy/http2/Http2Stream.cc index 2694a334b51..e4d6542cb0b 100644 --- a/proxy/http2/Http2Stream.cc +++ b/proxy/http2/Http2Stream.cc @@ -34,7 +34,7 @@ } #define Http2StreamDebug(fmt, ...) \ - SsnDebug(proxy_ssn, "http2_stream", "[%" PRId64 "] [%u] " fmt, proxy_ssn->connection_id(), this->get_id(), ##__VA_ARGS__); + SsnDebug(_proxy_ssn, "http2_stream", "[%" PRId64 "] [%u] " fmt, _proxy_ssn->connection_id(), this->get_id(), ##__VA_ARGS__); ClassAllocator http2StreamAllocator("http2StreamAllocator"); @@ -52,7 +52,7 @@ Http2Stream::init(Http2StreamId sid, ssize_t initial_rwnd) this->_thread = this_ethread(); this->_client_rwnd = initial_rwnd; - sm_reader = request_reader = request_buffer.alloc_reader(); + _reader = request_reader = request_buffer.alloc_reader(); // FIXME: Are you sure? every "stream" needs request_header? _req_header.create(HTTP_TYPE_REQUEST); response_header.create(HTTP_TYPE_RESPONSE); @@ -94,7 +94,7 @@ Http2Stream::main_event_handler(int event, void *edata) switch (event) { case VC_EVENT_ACTIVE_TIMEOUT: case VC_EVENT_INACTIVITY_TIMEOUT: - if (current_reader && read_vio.ntodo() > 0) { + if (_sm && read_vio.ntodo() > 0) { MUTEX_TRY_LOCK(lock, read_vio.mutex, this_ethread()); if (lock.is_locked()) { read_vio.cont->handleEvent(event, &read_vio); @@ -104,7 +104,7 @@ Http2Stream::main_event_handler(int event, void *edata) } this->_read_vio_event = this_ethread()->schedule_imm(read_vio.cont, event, &read_vio); } - } else if (current_reader && write_vio.ntodo() > 0) { + } else if (_sm && write_vio.ntodo() > 0) { MUTEX_TRY_LOCK(lock, write_vio.mutex, this_ethread()); if (lock.is_locked()) { write_vio.cont->handleEvent(event, &write_vio); @@ -120,7 +120,7 @@ Http2Stream::main_event_handler(int event, void *edata) case VC_EVENT_WRITE_COMPLETE: inactive_timeout_at = Thread::get_hrtime() + inactive_timeout; if (e->cookie == &write_vio) { - if (write_vio.mutex && write_vio.cont && this->current_reader) { + if (write_vio.mutex && write_vio.cont && this->_sm) { MUTEX_TRY_LOCK(lock, write_vio.mutex, this_ethread()); if (lock.is_locked()) { write_vio.cont->handleEvent(event, &write_vio); @@ -139,7 +139,7 @@ Http2Stream::main_event_handler(int event, void *edata) case VC_EVENT_READ_READY: inactive_timeout_at = Thread::get_hrtime() + inactive_timeout; if (e->cookie == &read_vio) { - if (read_vio.mutex && read_vio.cont && this->current_reader) { + if (read_vio.mutex && read_vio.cont && this->_sm) { MUTEX_TRY_LOCK(lock, read_vio.mutex, this_ethread()); if (lock.is_locked()) { read_vio.cont->handleEvent(event, &read_vio); @@ -181,8 +181,8 @@ Http2Stream::decode_header_blocks(HpackHandle &hpack_handle, uint32_t maximum_ta void Http2Stream::send_request(Http2ConnectionState &cstate) { - ink_release_assert(this->current_reader != nullptr); - this->_http_sm_id = this->current_reader->sm_id; + ink_release_assert(this->_sm != nullptr); + this->_http_sm_id = this->_sm->sm_id; // Convert header to HTTP/1.1 format http2_convert_header_from_2_to_1_1(&_req_header); @@ -374,10 +374,10 @@ Http2Stream::do_io_close(int /* flags */) // by the time this is called from transaction_done. closed = true; - if (proxy_ssn && this->is_client_state_writeable()) { + if (_proxy_ssn && this->is_client_state_writeable()) { // Make sure any trailing end of stream frames are sent // Wee will be removed at send_data_frames or closing connection phase - static_cast(proxy_ssn)->connection_state.send_data_frames(this); + static_cast(_proxy_ssn)->connection_state.send_data_frames(this); } clear_timers(); @@ -400,10 +400,10 @@ Http2Stream::transaction_done() } if (!closed) { - do_io_close(); // Make sure we've been closed. If we didn't close the proxy_ssn session better still be open + do_io_close(); // Make sure we've been closed. If we didn't close the _proxy_ssn session better still be open } - ink_release_assert(closed || !static_cast(proxy_ssn)->connection_state.is_state_closed()); - current_reader = nullptr; + ink_release_assert(closed || !static_cast(_proxy_ssn)->connection_state.is_state_closed()); + _sm = nullptr; if (closed) { // Safe to initiate SSN_CLOSE if this is the last stream @@ -420,7 +420,7 @@ Http2Stream::terminate_if_possible() if (terminate_stream && reentrancy_count == 0) { REMEMBER(NO_EVENT, this->reentrancy_count); - Http2ClientSession *h2_parent = static_cast(proxy_ssn); + Http2ClientSession *h2_parent = static_cast(_proxy_ssn); SCOPED_MUTEX_LOCK(lock, h2_parent->connection_state.mutex, this_ethread()); h2_parent->connection_state.delete_stream(this); destroy(); @@ -442,10 +442,10 @@ Http2Stream::initiating_close() _state = Http2StreamState::HTTP2_STREAM_STATE_CLOSED; // leaving the reference to the SM, so we can detach from the SM when we actually destroy - // current_reader = NULL; + // _sm = NULL; // Leaving reference to client session as well, so we can signal once the // TXN_CLOSE has been sent - // proxy_ssn = NULL; + // _proxy_ssn = NULL; clear_timers(); clear_io_events(); @@ -456,7 +456,7 @@ Http2Stream::initiating_close() // We are sending signals rather than calling the handlers directly to avoid the case where // the HttpTunnel handler causes the HttpSM to be deleted on the stack. bool sent_write_complete = false; - if (current_reader) { + if (_sm) { // Push out any last IO events if (write_vio.cont) { SCOPED_MUTEX_LOCK(lock, write_vio.mutex, this_ethread()); @@ -472,16 +472,16 @@ Http2Stream::initiating_close() } } // Send EOS to let SM know that we aren't sticking around - if (current_reader && read_vio.cont) { + if (_sm && read_vio.cont) { // Only bother with the EOS if we haven't sent the write complete if (!sent_write_complete) { SCOPED_MUTEX_LOCK(lock, read_vio.mutex, this_ethread()); Http2StreamDebug("send EOS to read cont"); read_event = send_tracked_event(read_event, VC_EVENT_EOS, &read_vio); } - } else if (current_reader) { - SCOPED_MUTEX_LOCK(lock, current_reader->mutex, this_ethread()); - current_reader->handleEvent(VC_EVENT_ERROR); + } else if (_sm) { + SCOPED_MUTEX_LOCK(lock, _sm->mutex, this_ethread()); + _sm->handleEvent(VC_EVENT_ERROR); } else if (!sent_write_complete) { // Transaction is already gone or not started. Kill yourself do_io_close(); @@ -512,7 +512,7 @@ Http2Stream::send_tracked_event(Event *event, int send_event, VIO *vio) void Http2Stream::update_read_request(int64_t read_len, bool call_update, bool check_eos) { - if (closed || proxy_ssn == nullptr || current_reader == nullptr || read_vio.mutex == nullptr) { + if (closed || _proxy_ssn == nullptr || _sm == nullptr || read_vio.mutex == nullptr) { return; } @@ -539,7 +539,7 @@ Http2Stream::update_read_request(int64_t read_len, bool call_update, bool check_ int send_event = (read_vio.nbytes == read_vio.ndone || recv_end_stream) ? VC_EVENT_READ_COMPLETE : VC_EVENT_READ_READY; if (call_update) { // Safe to call vio handler directly inactive_timeout_at = Thread::get_hrtime() + inactive_timeout; - if (read_vio.cont && this->current_reader) { + if (read_vio.cont && this->_sm) { read_vio.cont->handleEvent(send_event, &read_vio); } } else { // Called from do_io_read. Still setting things up. Send event to handle this after the dust settles @@ -553,7 +553,7 @@ Http2Stream::update_read_request(int64_t read_len, bool call_update, bool check_ if (request_reader->read_avail() > 0 || send_event == VC_EVENT_READ_COMPLETE) { if (call_update) { // Safe to call vio handler directly inactive_timeout_at = Thread::get_hrtime() + inactive_timeout; - if (read_vio.cont && this->current_reader) { + if (read_vio.cont && this->_sm) { read_vio.cont->handleEvent(send_event, &read_vio); } } else { // Called from do_io_read. Still setting things up. Send event @@ -574,7 +574,7 @@ Http2Stream::restart_sending() void Http2Stream::update_write_request(IOBufferReader *buf_reader, int64_t write_len, bool call_update) { - if (!this->is_client_state_writeable() || closed || proxy_ssn == nullptr || write_vio.mutex == nullptr || + if (!this->is_client_state_writeable() || closed || _proxy_ssn == nullptr || write_vio.mutex == nullptr || (buf_reader == nullptr && write_len == 0)) { return; } @@ -585,7 +585,7 @@ Http2Stream::update_write_request(IOBufferReader *buf_reader, int64_t write_len, } ink_release_assert(this->_thread == this_ethread()); - Http2ClientSession *proxy_ssn = static_cast(this->get_proxy_ssn()); + Http2ClientSession *_proxy_ssn = static_cast(this->get_proxy_ssn()); SCOPED_MUTEX_LOCK(lock, write_vio.mutex, this_ethread()); @@ -641,17 +641,17 @@ Http2Stream::update_write_request(IOBufferReader *buf_reader, int64_t write_len, int len; const char *value = field->value_get(&len); if (memcmp(HTTP_VALUE_CLOSE, value, HTTP_LEN_CLOSE) == 0) { - SCOPED_MUTEX_LOCK(lock, proxy_ssn->connection_state.mutex, this_ethread()); - if (proxy_ssn->connection_state.get_shutdown_state() == HTTP2_SHUTDOWN_NONE) { - proxy_ssn->connection_state.set_shutdown_state(HTTP2_SHUTDOWN_NOT_INITIATED, Http2ErrorCode::HTTP2_ERROR_NO_ERROR); + SCOPED_MUTEX_LOCK(lock, _proxy_ssn->connection_state.mutex, this_ethread()); + if (_proxy_ssn->connection_state.get_shutdown_state() == HTTP2_SHUTDOWN_NONE) { + _proxy_ssn->connection_state.set_shutdown_state(HTTP2_SHUTDOWN_NOT_INITIATED, Http2ErrorCode::HTTP2_ERROR_NO_ERROR); } } } { - SCOPED_MUTEX_LOCK(lock, proxy_ssn->connection_state.mutex, this_ethread()); + SCOPED_MUTEX_LOCK(lock, _proxy_ssn->connection_state.mutex, this_ethread()); // Send the response header back - proxy_ssn->connection_state.send_headers_frame(this); + _proxy_ssn->connection_state.send_headers_frame(this); } // See if the response is chunked. Set up the dechunking logic if it is @@ -702,7 +702,7 @@ Http2Stream::signal_write_event(bool call_update) if (call_update) { // Coming from reenable. Safe to call the handler directly - if (write_vio.cont && this->current_reader) { + if (write_vio.cont && this->_sm) { write_vio.cont->handleEvent(send_event, &write_vio); } } else { @@ -714,25 +714,25 @@ Http2Stream::signal_write_event(bool call_update) void Http2Stream::push_promise(URL &url, const MIMEField *accept_encoding) { - Http2ClientSession *proxy_ssn = static_cast(this->get_proxy_ssn()); - SCOPED_MUTEX_LOCK(lock, proxy_ssn->connection_state.mutex, this_ethread()); - proxy_ssn->connection_state.send_push_promise_frame(this, url, accept_encoding); + Http2ClientSession *_proxy_ssn = static_cast(this->get_proxy_ssn()); + SCOPED_MUTEX_LOCK(lock, _proxy_ssn->connection_state.mutex, this_ethread()); + _proxy_ssn->connection_state.send_push_promise_frame(this, url, accept_encoding); } void Http2Stream::send_response_body(bool call_update) { - Http2ClientSession *proxy_ssn = static_cast(this->get_proxy_ssn()); - inactive_timeout_at = Thread::get_hrtime() + inactive_timeout; + Http2ClientSession *_proxy_ssn = static_cast(this->get_proxy_ssn()); + inactive_timeout_at = Thread::get_hrtime() + inactive_timeout; if (Http2::stream_priority_enabled) { - SCOPED_MUTEX_LOCK(lock, proxy_ssn->connection_state.mutex, this_ethread()); - proxy_ssn->connection_state.schedule_stream(this); + SCOPED_MUTEX_LOCK(lock, _proxy_ssn->connection_state.mutex, this_ethread()); + _proxy_ssn->connection_state.schedule_stream(this); // signal_write_event() will be called from `Http2ConnectionState::send_data_frames_depends_on_priority()` // when write_vio is consumed } else { - SCOPED_MUTEX_LOCK(lock, proxy_ssn->connection_state.mutex, this_ethread()); - proxy_ssn->connection_state.send_data_frames(this); + SCOPED_MUTEX_LOCK(lock, _proxy_ssn->connection_state.mutex, this_ethread()); + _proxy_ssn->connection_state.send_data_frames(this); this->signal_write_event(call_update); // XXX The call to signal_write_event can destroy/free the Http2Stream. // Don't modify the Http2Stream after calling this method. @@ -742,7 +742,7 @@ Http2Stream::send_response_body(bool call_update) void Http2Stream::reenable(VIO *vio) { - if (this->proxy_ssn) { + if (this->_proxy_ssn) { if (vio->op == VIO::WRITE) { SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread()); update_write_request(vio->get_reader(), INT64_MAX, true); @@ -766,8 +766,8 @@ Http2Stream::destroy() uint64_t cid = 0; // Safe to initiate SSN_CLOSE if this is the last stream - if (proxy_ssn) { - Http2ClientSession *h2_proxy_ssn = static_cast(proxy_ssn); + if (_proxy_ssn) { + Http2ClientSession *h2_proxy_ssn = static_cast(_proxy_ssn); SCOPED_MUTEX_LOCK(lock, h2_proxy_ssn->connection_state.mutex, this_ethread()); // Make sure the stream is removed from the stream list and priority tree // In many cases, this has been called earlier, so this call is a no-op @@ -776,7 +776,7 @@ Http2Stream::destroy() // Update session's stream counts, so it accurately goes into keep-alive state h2_proxy_ssn->connection_state.release_stream(this); - cid = proxy_ssn->connection_id(); + cid = _proxy_ssn->connection_id(); } // Clean up the write VIO in case of inactivity timeout @@ -965,7 +965,7 @@ void Http2Stream::release(IOBufferReader *r) { super::release(r); - current_reader = nullptr; // State machine is on its own way down. + _sm = nullptr; // State machine is on its own way down. this->do_io_close(); } diff --git a/proxy/http3/Http3Transaction.cc b/proxy/http3/Http3Transaction.cc index b72f33a9b02..519ef76d39e 100644 --- a/proxy/http3/Http3Transaction.cc +++ b/proxy/http3/Http3Transaction.cc @@ -33,14 +33,14 @@ #include "HttpSM.h" #include "HTTP2.h" -#define Http3TransDebug(fmt, ...) \ - Debug("http3_trans", "[%s] [%" PRIx32 "] " fmt, \ - static_cast(reinterpret_cast(this->proxy_ssn->get_netvc()))->cids().data(), \ +#define Http3TransDebug(fmt, ...) \ + Debug("http3_trans", "[%s] [%" PRIx32 "] " fmt, \ + static_cast(reinterpret_cast(this->_proxy_ssn->get_netvc()))->cids().data(), \ this->get_transaction_id(), ##__VA_ARGS__) -#define Http3TransVDebug(fmt, ...) \ - Debug("v_http3_trans", "[%s] [%" PRIx32 "] " fmt, \ - static_cast(reinterpret_cast(this->proxy_ssn->get_netvc()))->cids().data(), \ +#define Http3TransVDebug(fmt, ...) \ + Debug("v_http3_trans", "[%s] [%" PRIx32 "] " fmt, \ + static_cast(reinterpret_cast(this->_proxy_ssn->get_netvc()))->cids().data(), \ this->get_transaction_id(), ##__VA_ARGS__) // static void @@ -63,7 +63,7 @@ HQTransaction::HQTransaction(HQSession *session, QUICStreamIO *stream_io) : supe this->set_proxy_ssn(session); - this->sm_reader = this->_read_vio_buf.alloc_reader(); + this->_reader = this->_read_vio_buf.alloc_reader(); HTTPType http_type = HTTP_TYPE_UNKNOWN; if (this->direction() == NET_VCONNECTION_OUT) { @@ -83,24 +83,24 @@ HQTransaction::~HQTransaction() void HQTransaction::set_active_timeout(ink_hrtime timeout_in) { - if (this->proxy_ssn) { - this->proxy_ssn->set_active_timeout(timeout_in); + if (this->_proxy_ssn) { + this->_proxy_ssn->set_active_timeout(timeout_in); } } void HQTransaction::set_inactivity_timeout(ink_hrtime timeout_in) { - if (this->proxy_ssn) { - this->proxy_ssn->set_inactivity_timeout(timeout_in); + if (this->_proxy_ssn) { + this->_proxy_ssn->set_inactivity_timeout(timeout_in); } } void HQTransaction::cancel_inactivity_timeout() { - if (this->proxy_ssn) { - this->proxy_ssn->cancel_inactivity_timeout(); + if (this->_proxy_ssn) { + this->_proxy_ssn->cancel_inactivity_timeout(); } } @@ -109,7 +109,7 @@ HQTransaction::release(IOBufferReader *r) { super::release(r); this->do_io_close(); - this->current_reader = nullptr; + this->_sm = nullptr; } bool @@ -185,7 +185,7 @@ HQTransaction::do_io_close(int lerrno) this->_write_vio.op = VIO::NONE; this->_write_vio.cont = nullptr; - this->proxy_ssn->do_io_close(lerrno); + this->_proxy_ssn->do_io_close(lerrno); } void @@ -217,7 +217,7 @@ HQTransaction::reenable(VIO *vio) void HQTransaction::destroy() { - current_reader = nullptr; + _sm = nullptr; } void @@ -248,7 +248,7 @@ HQTransaction::decrement_client_transactions_stat() NetVConnectionContext_t HQTransaction::direction() const { - return this->proxy_ssn->get_netvc()->get_context(); + return this->_proxy_ssn->get_netvc()->get_context(); } /** @@ -318,7 +318,7 @@ HQTransaction::_signal_write_event() // Http3Transaction::Http3Transaction(Http3Session *session, QUICStreamIO *stream_io) : super(session, stream_io) { - static_cast(this->proxy_ssn)->add_transaction(static_cast(this)); + static_cast(this->_proxy_ssn)->add_transaction(static_cast(this)); this->_header_framer = new Http3HeaderFramer(this, &this->_write_vio, session->local_qpack(), stream_io->stream_id()); this->_data_framer = new Http3DataFramer(this, &this->_write_vio); @@ -597,7 +597,7 @@ Http3Transaction::_on_qpack_decode_complete() // Http09Transaction::Http09Transaction(Http09Session *session, QUICStreamIO *stream_io) : super(session, stream_io) { - static_cast(this->proxy_ssn)->add_transaction(static_cast(this)); + static_cast(this->_proxy_ssn)->add_transaction(static_cast(this)); SET_HANDLER(&Http09Transaction::state_stream_open); } From 815b58314c47df8891be3cf21ee70fb5367154ff Mon Sep 17 00:00:00 2001 From: Aaron Canary Date: Wed, 4 Sep 2019 14:36:37 -0500 Subject: [PATCH 076/718] ProxySession cleanup: moving inline functions to .h moving non-virtual, one-liner functions to the .h with "inline" keyword. (cherry picked from commit 3a44862d203571443672f089c7f294ba81f18e6b) --- proxy/ProxySession.cc | 84 ------------------------ proxy/ProxySession.h | 86 ++++++++++++++++++++++++ proxy/ProxyTransaction.cc | 94 --------------------------- proxy/ProxyTransaction.h | 104 ++++++++++++++++++++++++++++-- proxy/http/Http1ServerSession.cc | 6 -- proxy/http/Http1ServerSession.h | 12 +++- proxy/http/Http1Transaction.cc | 6 -- proxy/http/Http1Transaction.h | 9 +++ proxy/http2/Http2ClientSession.cc | 48 -------------- proxy/http2/Http2ClientSession.h | 51 +++++++++++++++ proxy/http2/Http2Stream.cc | 99 ---------------------------- proxy/http2/Http2Stream.h | 103 +++++++++++++++++++++++++++++ 12 files changed, 358 insertions(+), 344 deletions(-) diff --git a/proxy/ProxySession.cc b/proxy/ProxySession.cc index af7c30ee2ca..d3b7eb433eb 100644 --- a/proxy/ProxySession.cc +++ b/proxy/ProxySession.cc @@ -25,8 +25,6 @@ #include "HttpDebugNames.h" #include "ProxySession.h" -static int64_t next_cs_id = 0; - ProxySession::ProxySession() : VConnection(nullptr) { ink_zero(this->user_args); @@ -50,12 +48,6 @@ ProxySession::clear_session_active() } } -int64_t -ProxySession::next_connection_id() -{ - return ink_atomic_increment(&next_cs_id, 1); -} - static const TSEvent eventmap[TS_HTTP_LAST_HOOK + 1] = { TS_EVENT_HTTP_READ_REQUEST_HDR, // TS_HTTP_READ_REQUEST_HDR_HOOK TS_EVENT_HTTP_OS_DNS, // TS_HTTP_OS_DNS_HOOK @@ -182,46 +174,6 @@ ProxySession::handle_api_return(int event) } } -void * - -ProxySession::get_user_arg(unsigned ix) const -{ - ink_assert(ix < countof(user_args)); - return this->user_args[ix]; -} - -void -ProxySession::set_user_arg(unsigned ix, void *arg) -{ - ink_assert(ix < countof(user_args)); - user_args[ix] = arg; -} - -void -ProxySession::set_debug(bool flag) -{ - debug_on = flag; -} - -// Return whether debugging is enabled for this session. -bool -ProxySession::debug() const -{ - return this->debug_on; -} - -bool -ProxySession::is_active() const -{ - return m_active; -} - -bool -ProxySession::is_draining() const -{ - return TSSystemState::is_draining(); -} - bool ProxySession::is_chunked_encoding_supported() const { @@ -257,12 +209,6 @@ ProxySession::get_server_session() const return nullptr; } -TSHttpHookID -ProxySession::get_hookid() const -{ - return hook_state.id(); -} - void ProxySession::set_active_timeout(ink_hrtime timeout_in) { @@ -278,12 +224,6 @@ ProxySession::cancel_inactivity_timeout() { } -bool -ProxySession::is_client_closed() const -{ - return get_netvc() == nullptr; -} - int ProxySession::populate_protocol(std::string_view *result, int size) const { @@ -310,27 +250,3 @@ ProxySession::get_local_addr() NetVConnection *netvc = get_netvc(); return netvc ? netvc->get_local_addr() : nullptr; } - -void -ProxySession::hook_add(TSHttpHookID id, INKContInternal *cont) -{ - this->api_hooks.append(id, cont); -} - -APIHook * -ProxySession::hook_get(TSHttpHookID id) const -{ - return this->api_hooks.get(id); -} - -HttpAPIHooks const * -ProxySession::feature_hooks() const -{ - return &api_hooks; -} - -bool -ProxySession::has_hooks() const -{ - return this->api_hooks.has_hooks() || http_global_hooks->has_hooks(); -} diff --git a/proxy/ProxySession.h b/proxy/ProxySession.h index 4770683f2bd..478c59249b8 100644 --- a/proxy/ProxySession.h +++ b/proxy/ProxySession.h @@ -181,3 +181,89 @@ class ProxySession : public VConnection // aborts. bool m_active = false; }; + +/////////////////// +// INLINE + +static inline int64_t next_cs_id = 0; + +inline int64_t +ProxySession::next_connection_id() +{ + return ink_atomic_increment(&next_cs_id, 1); +} + +inline void * +ProxySession::get_user_arg(unsigned ix) const +{ + ink_assert(ix < countof(user_args)); + return this->user_args[ix]; +} + +inline void +ProxySession::set_user_arg(unsigned ix, void *arg) +{ + ink_assert(ix < countof(user_args)); + user_args[ix] = arg; +} + +inline void +ProxySession::set_debug(bool flag) +{ + debug_on = flag; +} + +// Return whether debugging is enabled for this session. +inline bool +ProxySession::debug() const +{ + return this->debug_on; +} + +inline bool +ProxySession::is_active() const +{ + return m_active; +} + +inline bool +ProxySession::is_draining() const +{ + return TSSystemState::is_draining(); +} + +inline bool +ProxySession::is_client_closed() const +{ + return get_netvc() == nullptr; +} + +inline TSHttpHookID +ProxySession::get_hookid() const +{ + return hook_state.id(); +} + +inline void +ProxySession::hook_add(TSHttpHookID id, INKContInternal *cont) +{ + this->api_hooks.append(id, cont); +} + +inline APIHook * +ProxySession::hook_get(TSHttpHookID id) const +{ + return this->api_hooks.get(id); +} + +inline HttpAPIHooks const * +ProxySession::feature_hooks() const +{ + return &api_hooks; +} + +inline bool +ProxySession::has_hooks() const +{ + return this->api_hooks.has_hooks() || http_global_hooks->has_hooks(); +} diff --git a/proxy/ProxyTransaction.cc b/proxy/ProxyTransaction.cc index 47099a90ac0..6cce239b622 100644 --- a/proxy/ProxyTransaction.cc +++ b/proxy/ProxyTransaction.cc @@ -124,58 +124,6 @@ ProxyTransaction::is_first_transaction() const { return _proxy_ssn->get_transact_count() == 1; } -// Ask your session if this is allowed -bool -ProxyTransaction::is_transparent_passthrough_allowed() -{ - return upstream_outbound_options.f_transparent_passthrough; -} - -bool -ProxyTransaction::is_chunked_encoding_supported() const -{ - return _proxy_ssn ? _proxy_ssn->is_chunked_encoding_supported() : false; -} - -void -ProxyTransaction::set_half_close_flag(bool flag) -{ - if (_proxy_ssn) { - _proxy_ssn->set_half_close_flag(flag); - } -} - -bool -ProxyTransaction::get_half_close_flag() const -{ - return _proxy_ssn ? _proxy_ssn->get_half_close_flag() : false; -} - -// What are the debug and hooks_enabled used for? How are they set? -// Just calling through to proxy session for now -bool -ProxyTransaction::debug() const -{ - return _proxy_ssn ? _proxy_ssn->debug() : false; -} - -APIHook * -ProxyTransaction::hook_get(TSHttpHookID id) const -{ - return _proxy_ssn ? _proxy_ssn->hook_get(id) : nullptr; -} - -HttpAPIHooks const * -ProxyTransaction::feature_hooks() const -{ - return _proxy_ssn ? _proxy_ssn->feature_hooks() : nullptr; -} - -bool -ProxyTransaction::has_hooks() const -{ - return _proxy_ssn->has_hooks(); -} void ProxyTransaction::set_session_active() @@ -247,49 +195,7 @@ ProxyTransaction::set_outbound_transparent(bool flag) upstream_outbound_options.f_outbound_transparent = flag; } -ProxySession * -ProxyTransaction::get_proxy_ssn() -{ - return _proxy_ssn; -} - -void -ProxyTransaction::set_proxy_ssn(ProxySession *new_proxy_ssn) -{ - _proxy_ssn = new_proxy_ssn; -} - void ProxyTransaction::set_h2c_upgrade_flag() { } - -Http1ServerSession * -ProxyTransaction::get_server_session() const -{ - return _proxy_ssn ? _proxy_ssn->get_server_session() : nullptr; -} - -HttpSM * -ProxyTransaction::get_sm() const -{ - return _sm; -} - -const char * -ProxyTransaction::get_protocol_string() -{ - return _proxy_ssn ? _proxy_ssn->get_protocol_string() : nullptr; -} - -int -ProxyTransaction::populate_protocol(std::string_view *result, int size) const -{ - return _proxy_ssn ? _proxy_ssn->populate_protocol(result, size) : 0; -} - -const char * -ProxyTransaction::protocol_contains(std::string_view tag_prefix) const -{ - return _proxy_ssn ? _proxy_ssn->protocol_contains(tag_prefix) : nullptr; -} diff --git a/proxy/ProxyTransaction.h b/proxy/ProxyTransaction.h index 47999df2ff2..085e6042001 100644 --- a/proxy/ProxyTransaction.h +++ b/proxy/ProxyTransaction.h @@ -73,14 +73,11 @@ class ProxyTransaction : public VConnection virtual void set_proxy_ssn(ProxySession *set_proxy_ssn); virtual void set_h2c_upgrade_flag(); - virtual const char *get_protocol_string(); - - virtual int populate_protocol(std::string_view *result, int size) const; - - virtual const char *protocol_contains(std::string_view tag_prefix) const; - /// Non-Virtual Methods // + const char *get_protocol_string(); + int populate_protocol(std::string_view *result, int size) const; + const char *protocol_contains(std::string_view tag_prefix) const; /// Non-Virtual Accessors // @@ -119,3 +116,98 @@ class ProxyTransaction : public VConnection private: }; + +//////////////////////////////////////////////////////////// +// INLINE + +inline bool +ProxyTransaction::is_transparent_passthrough_allowed() +{ + return upstream_outbound_options.f_transparent_passthrough; +} +inline bool +ProxyTransaction::is_chunked_encoding_supported() const +{ + return _proxy_ssn ? _proxy_ssn->is_chunked_encoding_supported() : false; +} +inline void +ProxyTransaction::set_half_close_flag(bool flag) +{ + if (_proxy_ssn) { + _proxy_ssn->set_half_close_flag(flag); + } +} + +inline bool +ProxyTransaction::get_half_close_flag() const +{ + return _proxy_ssn ? _proxy_ssn->get_half_close_flag() : false; +} + +// What are the debug and hooks_enabled used for? How are they set? +// Just calling through to proxy session for now +inline bool +ProxyTransaction::debug() const +{ + return _proxy_ssn ? _proxy_ssn->debug() : false; +} + +inline APIHook * +ProxyTransaction::hook_get(TSHttpHookID id) const +{ + return _proxy_ssn ? _proxy_ssn->hook_get(id) : nullptr; +} + +inline HttpAPIHooks const * +ProxyTransaction::feature_hooks() const +{ + return _proxy_ssn ? _proxy_ssn->feature_hooks() : nullptr; +} + +inline bool +ProxyTransaction::has_hooks() const +{ + return _proxy_ssn->has_hooks(); +} + +inline ProxySession * +ProxyTransaction::get_proxy_ssn() +{ + return _proxy_ssn; +} + +inline void +ProxyTransaction::set_proxy_ssn(ProxySession *new_proxy_ssn) +{ + _proxy_ssn = new_proxy_ssn; +} + +inline Http1ServerSession * +ProxyTransaction::get_server_session() const +{ + return _proxy_ssn ? _proxy_ssn->get_server_session() : nullptr; +} + +inline HttpSM * +ProxyTransaction::get_sm() const +{ + return _sm; +} + +inline const char * +ProxyTransaction::get_protocol_string() +{ + return _proxy_ssn ? _proxy_ssn->get_protocol_string() : nullptr; +} + +inline int +ProxyTransaction::populate_protocol(std::string_view *result, int size) const +{ + return _proxy_ssn ? _proxy_ssn->populate_protocol(result, size) : 0; +} + +inline const char * +ProxyTransaction::protocol_contains(std::string_view tag_prefix) const +{ + return _proxy_ssn ? _proxy_ssn->protocol_contains(tag_prefix) : nullptr; +} diff --git a/proxy/http/Http1ServerSession.cc b/proxy/http/Http1ServerSession.cc index 23ba7b3dbc3..50b9e5e38c3 100644 --- a/proxy/http/Http1ServerSession.cc +++ b/proxy/http/Http1ServerSession.cc @@ -204,12 +204,6 @@ Http1ServerSession::release() } } -IOBufferReader * -Http1ServerSession::get_reader() -{ - return buf_reader; -}; - NetVConnection * Http1ServerSession::get_netvc() const { diff --git a/proxy/http/Http1ServerSession.h b/proxy/http/Http1ServerSession.h index f558f3a7914..c909b3c8a9f 100644 --- a/proxy/http/Http1ServerSession.h +++ b/proxy/http/Http1ServerSession.h @@ -163,7 +163,8 @@ class Http1ServerSession : public VConnection extern ClassAllocator httpServerSessionAllocator; -// --- Implementation --- +//////////////////////////////////////////// +// INLINE inline void Http1ServerSession::attach_hostname(const char *hostname) @@ -173,6 +174,15 @@ Http1ServerSession::attach_hostname(const char *hostname) } } +inline IOBufferReader * +Http1ServerSession::get_reader() +{ + return buf_reader; +}; + +// +// LINKAGE + inline Http1ServerSession *& Http1ServerSession::IPLinkage::next_ptr(self_type *ssn) { diff --git a/proxy/http/Http1Transaction.cc b/proxy/http/Http1Transaction.cc index 73a161b4642..8a2790c29b7 100644 --- a/proxy/http/Http1Transaction.cc +++ b/proxy/http/Http1Transaction.cc @@ -113,12 +113,6 @@ Http1Transaction::do_io_shutdown(ShutdownHowTo_t howto) _proxy_ssn->do_io_shutdown(howto); } -void -Http1Transaction::set_reader(IOBufferReader *reader) -{ - _reader = reader; -} - void Http1Transaction::set_active_timeout(ink_hrtime timeout_in) { diff --git a/proxy/http/Http1Transaction.h b/proxy/http/Http1Transaction.h index 3c3215d7580..407d73ec030 100644 --- a/proxy/http/Http1Transaction.h +++ b/proxy/http/Http1Transaction.h @@ -64,3 +64,12 @@ class Http1Transaction : public ProxyTransaction protected: bool outbound_transparent{false}; }; + +////////////////////////////////// +// INLINE + +inline void +Http1Transaction::set_reader(IOBufferReader *reader) +{ + _reader = reader; +} diff --git a/proxy/http2/Http2ClientSession.cc b/proxy/http2/Http2ClientSession.cc index 3f754868ef1..ed5069c3c47 100644 --- a/proxy/http2/Http2ClientSession.cc +++ b/proxy/http2/Http2ClientSession.cc @@ -650,12 +650,6 @@ Http2ClientSession::_should_do_something_else() return (this->_n_frame_read & 0x7F) == 0; } -bool -Http2ClientSession::ready_to_free() const -{ - return kill_me; -} - NetVConnection * Http2ClientSession::get_netvc() const { @@ -679,12 +673,6 @@ Http2ClientSession::write_reenable() write_vio->reenable(); } -const Http2UpgradeContext & -Http2ClientSession::get_upgrade_context() const -{ - return upgrade_context; -} - int Http2ClientSession::get_transact_count() const { @@ -696,24 +684,6 @@ Http2ClientSession::release(ProxyTransaction *trans) { } -void -Http2ClientSession::set_dying_event(int event) -{ - dying_event = event; -} - -int -Http2ClientSession::get_dying_event() const -{ - return dying_event; -} - -bool -Http2ClientSession::is_recursing() const -{ - return recursion > 0; -} - const char * Http2ClientSession::get_protocol_string() const { @@ -746,18 +716,6 @@ Http2ClientSession::protocol_contains(std::string_view prefix) const return retval; } -bool -Http2ClientSession::get_half_close_local_flag() const -{ - return half_close_local; -} - -bool -Http2ClientSession::is_url_pushed(const char *url, int url_len) -{ - return h2_pushed_urls.find(url) != h2_pushed_urls.end(); -} - void Http2ClientSession::add_url_to_pushed_table(const char *url, int url_len) { @@ -765,9 +723,3 @@ Http2ClientSession::add_url_to_pushed_table(const char *url, int url_len) h2_pushed_urls.emplace(url); } } - -int64_t -Http2ClientSession::write_buffer_size() -{ - return write_buffer->max_read_avail(); -} diff --git a/proxy/http2/Http2ClientSession.h b/proxy/http2/Http2ClientSession.h index 0bb9755485d..eee6a3b6a2f 100644 --- a/proxy/http2/Http2ClientSession.h +++ b/proxy/http2/Http2ClientSession.h @@ -267,3 +267,54 @@ class Http2ClientSession : public ProxySession }; extern ClassAllocator http2ClientSessionAllocator; + +/////////////////////////////////////////////// +// INLINE + +inline const Http2UpgradeContext & +Http2ClientSession::get_upgrade_context() const +{ + return upgrade_context; +} + +inline bool +Http2ClientSession::ready_to_free() const +{ + return kill_me; +} + +inline void +Http2ClientSession::set_dying_event(int event) +{ + dying_event = event; +} + +inline int +Http2ClientSession::get_dying_event() const +{ + return dying_event; +} + +inline bool +Http2ClientSession::is_recursing() const +{ + return recursion > 0; +} + +inline bool +Http2ClientSession::get_half_close_local_flag() const +{ + return half_close_local; +} + +inline bool +Http2ClientSession::is_url_pushed(const char *url, int url_len) +{ + return h2_pushed_urls.find(url) != h2_pushed_urls.end(); +} + +inline int64_t +Http2ClientSession::write_buffer_size() +{ + return write_buffer->max_read_avail(); +} diff --git a/proxy/http2/Http2Stream.cc b/proxy/http2/Http2Stream.cc index e4d6542cb0b..c2e5195a397 100644 --- a/proxy/http2/Http2Stream.cc +++ b/proxy/http2/Http2Stream.cc @@ -1039,12 +1039,6 @@ Http2Stream::decrement_server_rwnd(size_t amount) } } -void -Http2Stream::mark_milestone(Http2StreamMilestone type) -{ - this->_milestones.mark(type); -} - bool Http2Stream::_switch_thread_if_not_on_right_thread(int event, void *edata) { @@ -1059,12 +1053,6 @@ Http2Stream::_switch_thread_if_not_on_right_thread(int event, void *edata) return true; } -bool -Http2Stream::is_body_done() const -{ - return body_done; -} - void Http2Stream::mark_body_done() { @@ -1075,90 +1063,3 @@ Http2Stream::mark_body_done() this->write_vio.nbytes = response_header.length_get() + chunked_handler.dechunked_size; } } - -void -Http2Stream::update_sent_count(unsigned num_bytes) -{ - bytes_sent += num_bytes; - this->write_vio.ndone += num_bytes; -} - -Http2StreamId -Http2Stream::get_id() const -{ - return _id; -} - -int -Http2Stream::get_transaction_id() const -{ - return _id; -} - -Http2StreamState -Http2Stream::get_state() const -{ - return _state; -} - -void -Http2Stream::update_initial_rwnd(Http2WindowSize new_size) -{ - this->_client_rwnd = new_size; -} - -bool -Http2Stream::has_trailing_header() const -{ - return trailing_header; -} - -void -Http2Stream::set_request_headers(HTTPHdr &h2_headers) -{ - _req_header.copy(&h2_headers); -} - -// Check entire DATA payload length if content-length: header is exist -void -Http2Stream::increment_data_length(uint64_t length) -{ - data_length += length; -} - -bool -Http2Stream::payload_length_is_valid() const -{ - uint32_t content_length = _req_header.get_content_length(); - return content_length == 0 || content_length == data_length; -} - -bool -Http2Stream::response_is_chunked() const -{ - return chunked; -} - -bool -Http2Stream::allow_half_open() const -{ - return false; -} - -bool -Http2Stream::is_client_state_writeable() const -{ - return _state == Http2StreamState::HTTP2_STREAM_STATE_OPEN || _state == Http2StreamState::HTTP2_STREAM_STATE_HALF_CLOSED_REMOTE || - _state == Http2StreamState::HTTP2_STREAM_STATE_RESERVED_LOCAL; -} -bool -Http2Stream::is_closed() const -{ - return closed; -} - -bool -Http2Stream::is_first_transaction() const -{ - return is_first_transaction_flag; -} diff --git a/proxy/http2/Http2Stream.h b/proxy/http2/Http2Stream.h index 8b0489b0c7d..20bae58889c 100644 --- a/proxy/http2/Http2Stream.h +++ b/proxy/http2/Http2Stream.h @@ -225,3 +225,106 @@ class Http2Stream : public ProxyTransaction }; extern ClassAllocator http2StreamAllocator; + +//////////////////////////////////////////////////// +// INLINE + +inline void +Http2Stream::mark_milestone(Http2StreamMilestone type) +{ + this->_milestones.mark(type); +} + +inline bool +Http2Stream::is_body_done() const +{ + return body_done; +} + +inline void +Http2Stream::update_sent_count(unsigned num_bytes) +{ + bytes_sent += num_bytes; + this->write_vio.ndone += num_bytes; +} + +inline Http2StreamId +Http2Stream::get_id() const +{ + return _id; +} + +inline int +Http2Stream::get_transaction_id() const +{ + return _id; +} + +inline Http2StreamState +Http2Stream::get_state() const +{ + return _state; +} + +inline void +Http2Stream::update_initial_rwnd(Http2WindowSize new_size) +{ + this->_client_rwnd = new_size; +} + +inline bool +Http2Stream::has_trailing_header() const +{ + return trailing_header; +} + +inline void +Http2Stream::set_request_headers(HTTPHdr &h2_headers) +{ + _req_header.copy(&h2_headers); +} + +inline // Check entire DATA payload length if content-length: header is exist + void + Http2Stream::increment_data_length(uint64_t length) +{ + data_length += length; +} + +inline bool +Http2Stream::payload_length_is_valid() const +{ + uint32_t content_length = _req_header.get_content_length(); + return content_length == 0 || content_length == data_length; +} + +inline bool +Http2Stream::response_is_chunked() const +{ + return chunked; +} + +inline bool +Http2Stream::allow_half_open() const +{ + return false; +} + +inline bool +Http2Stream::is_client_state_writeable() const +{ + return _state == Http2StreamState::HTTP2_STREAM_STATE_OPEN || _state == Http2StreamState::HTTP2_STREAM_STATE_HALF_CLOSED_REMOTE || + _state == Http2StreamState::HTTP2_STREAM_STATE_RESERVED_LOCAL; +} + +inline bool +Http2Stream::is_closed() const +{ + return closed; +} + +inline bool +Http2Stream::is_first_transaction() const +{ + return is_first_transaction_flag; +} From 52973929832eeea746174bcabac480641cb6d9a0 Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Tue, 22 Oct 2019 11:17:55 -0600 Subject: [PATCH 077/718] Updated ChangeLog, lots of changes --- CHANGELOG-9.0.0 | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/CHANGELOG-9.0.0 b/CHANGELOG-9.0.0 index 79959cd01a2..d211d56fbfd 100644 --- a/CHANGELOG-9.0.0 +++ b/CHANGELOG-9.0.0 @@ -456,6 +456,7 @@ Changes with Apache Traffic Server 9.0.0 #5289 - Don't read frames after sending GOAWAY with an error code #5290 - MIMEScanner: Only clear scanner line buffer if at MIME_PARSE_BEFORE state #5292 - Fix a build error in xdebug on macos + #5293 - Destroy MIMEFieldBlockImpl that doesn't have fields in use #5297 - Doc: fix proxy.config.cache.ram_cache.algorithm description #5301 - Slice Plugin: add options for disabling or pacing detailed block stitch error logging. #5302 - Correct config name for proxy.config.dns.connection_mode @@ -732,6 +733,7 @@ Changes with Apache Traffic Server 9.0.0 #5771 - Fixes linker changes for luajit on macOS #5772 - Remove ssl_error stats that aren't really errors. #5773 - Documentation for Autest in Sphinx + #5774 - Updating the default cipher-suite lists for the 9.x release. #5778 - Issue 5604 - fix memory leaks for http parser. #5779 - doc: TSL used instead of TLS in Japanese docs #5780 - Fixed std::array initialization for older compilers @@ -757,6 +759,7 @@ Changes with Apache Traffic Server 9.0.0 #5826 - Cleanup: Signal READ_READY event only if the buffer is readable #5827 - compress plugin: document undocumented options #5828 - Make client_context_dump test resilient to dump order changes + #5829 - fix bugs from log filter feature #5830 - Make proxy.config.http.per_server.min_keep_alive_connections overridable #5831 - Fix QUIC build #5833 - Fix H2 internal counters @@ -766,25 +769,35 @@ Changes with Apache Traffic Server 9.0.0 #5844 - Explain how SRV origin selection works #5847 - Cleanup: Remove unused empty files #5848 - Convert check programs in iocore/eventsystem/ into Catch based unit tests + #5852 - Replaced ProxyTxn::outbound vars with accept::options #5853 - correct the size of DNS buffers #5856 - Fixes 'traffic_ctl server restart' to restart #5857 - Check for nullptr when locking + #5863 - pipe buffer size for log.pipe should be configurable + #5864 - ProxyTxn refactor: moved host_res_style to t_state.dns_info #5865 - cachekey: added --canonical-prefix parameter #5867 - PR#5867: Explain how to use open_con(). #5868 - Update HttpTransact.cc + #5869 - ProxyTxn: removed restart_immediate #5870 - Fix bad limit in poll loop. jtest -c1 now works again. #5872 - cachekey: added --key-type to allow parent selection URL to be modified #5879 - Weak mutex locking macros + #5880 - ProxyTxn Refactor move code to cc #5883 - Add unit tests for MIOBuffer:write() #5885 - Add the ability to static link ASAN, TSAN and LSAN #5887 - Fixed const issue with magick plugin #5888 - Allow disabling HTTP/2 priority frames limit #5889 - Provide stats for the recently introduced HTTP/2 rate limits + #5892 - ProxySsn renaming member vars #5893 - Cleanup: Remove unused AllocType and unused functions #5902 - Ran clang-format #5903 - Reduce unnecesary IOBufferBlock allocation #5905 - Update Server IP in Transaction when attaching a session from the pool + #5906 - Cleanup: unifdef TRACK_BUFFER_USER + #5907 - Fix macOS build + #5908 - ProxySession cleanup: moving inline functions to .h #5915 - Update documentation for connect_attempts_timeout. + #5919 - Rearrange config reload notifications #5920 - Cleanup: VIO #5921 - Cleanup AuTest for HTTP/2 #5922 - Make code buildable with BoringSSL @@ -792,10 +805,28 @@ Changes with Apache Traffic Server 9.0.0 #5930 - Track SSL session cache evictions performed due to full bucket #5934 - Track scheduled events to (read|write)_vio.cont from Http2Stream #5935 - Perform a SSL quiet shutdown when close-notify is not sent + #5937 - Update TSVConnSslConnectionGet name to match other TSVConnSsl* APIs #5939 - Remove hard coded filename in error message + #5945 - cachekey: allow multiple values for `--key-type` + #5949 - Fix TSHttpTxnReenable to schedule back to original SM thread + #5953 - Log H2 priority information #5955 - Fix debug output for global_user_agent_header. #5956 - Turn on certificate verification, in permissive mode for now #5959 - Clear api set bit to avoid crash in following redirect. #5961 - Clarify docs on the change from redirect_enabled. #5962 - Removed hardcoded sni.yaml configuration filename in logs + #5964 - Fix a build issue on enabling FIPS + #5969 - Change the ready checks for ats to use the actual ats port + #5970 - "Plugin (un)used" post reload notification #5977 - YAML config: output erroneous keyword and line number + #5978 - Removed hardcoded logging.yaml filename in logs + #5979 - Revert "Optimize: If failed on migrateToCurrentThread, put the server… + #5980 - Fix use-after-free problem related to logging headers + #5985 - Add filename to error message in header_rewrite + #5986 - Remove hard-coded ssl_multicert.config log reference + #5992 - Cache SSL EC explicitly + #6000 - Add QUIC draft-23 support + #6003 - Cleanup: do not re-define _proxy_ssn variable in local + #6008 - Do not schedule stuff during shutdown + #6016 - Fix host type in host matcher. + #6024 - Make proxy.config.http.request_buffer_enabled configurable and bug fix From 1e4acfd651435993b177549d0cb1f00ffe9d9150 Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Wed, 9 Oct 2019 15:37:33 -0700 Subject: [PATCH 078/718] Cleanup: do not re-define _proxy_ssn variable in local (cherry picked from commit 0ee48a0ccb064226215385bd359d3d6907d97595) --- proxy/http2/Http2Stream.cc | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/proxy/http2/Http2Stream.cc b/proxy/http2/Http2Stream.cc index c2e5195a397..bbd16f0b669 100644 --- a/proxy/http2/Http2Stream.cc +++ b/proxy/http2/Http2Stream.cc @@ -420,9 +420,9 @@ Http2Stream::terminate_if_possible() if (terminate_stream && reentrancy_count == 0) { REMEMBER(NO_EVENT, this->reentrancy_count); - Http2ClientSession *h2_parent = static_cast(_proxy_ssn); - SCOPED_MUTEX_LOCK(lock, h2_parent->connection_state.mutex, this_ethread()); - h2_parent->connection_state.delete_stream(this); + Http2ClientSession *h2_proxy_ssn = static_cast(this->_proxy_ssn); + SCOPED_MUTEX_LOCK(lock, h2_proxy_ssn->connection_state.mutex, this_ethread()); + h2_proxy_ssn->connection_state.delete_stream(this); destroy(); } } @@ -585,7 +585,7 @@ Http2Stream::update_write_request(IOBufferReader *buf_reader, int64_t write_len, } ink_release_assert(this->_thread == this_ethread()); - Http2ClientSession *_proxy_ssn = static_cast(this->get_proxy_ssn()); + Http2ClientSession *h2_proxy_ssn = static_cast(this->_proxy_ssn); SCOPED_MUTEX_LOCK(lock, write_vio.mutex, this_ethread()); @@ -641,17 +641,17 @@ Http2Stream::update_write_request(IOBufferReader *buf_reader, int64_t write_len, int len; const char *value = field->value_get(&len); if (memcmp(HTTP_VALUE_CLOSE, value, HTTP_LEN_CLOSE) == 0) { - SCOPED_MUTEX_LOCK(lock, _proxy_ssn->connection_state.mutex, this_ethread()); - if (_proxy_ssn->connection_state.get_shutdown_state() == HTTP2_SHUTDOWN_NONE) { - _proxy_ssn->connection_state.set_shutdown_state(HTTP2_SHUTDOWN_NOT_INITIATED, Http2ErrorCode::HTTP2_ERROR_NO_ERROR); + SCOPED_MUTEX_LOCK(lock, h2_proxy_ssn->connection_state.mutex, this_ethread()); + if (h2_proxy_ssn->connection_state.get_shutdown_state() == HTTP2_SHUTDOWN_NONE) { + h2_proxy_ssn->connection_state.set_shutdown_state(HTTP2_SHUTDOWN_NOT_INITIATED, Http2ErrorCode::HTTP2_ERROR_NO_ERROR); } } } { - SCOPED_MUTEX_LOCK(lock, _proxy_ssn->connection_state.mutex, this_ethread()); + SCOPED_MUTEX_LOCK(lock, h2_proxy_ssn->connection_state.mutex, this_ethread()); // Send the response header back - _proxy_ssn->connection_state.send_headers_frame(this); + h2_proxy_ssn->connection_state.send_headers_frame(this); } // See if the response is chunked. Set up the dechunking logic if it is @@ -714,25 +714,25 @@ Http2Stream::signal_write_event(bool call_update) void Http2Stream::push_promise(URL &url, const MIMEField *accept_encoding) { - Http2ClientSession *_proxy_ssn = static_cast(this->get_proxy_ssn()); - SCOPED_MUTEX_LOCK(lock, _proxy_ssn->connection_state.mutex, this_ethread()); - _proxy_ssn->connection_state.send_push_promise_frame(this, url, accept_encoding); + Http2ClientSession *h2_proxy_ssn = static_cast(this->_proxy_ssn); + SCOPED_MUTEX_LOCK(lock, h2_proxy_ssn->connection_state.mutex, this_ethread()); + h2_proxy_ssn->connection_state.send_push_promise_frame(this, url, accept_encoding); } void Http2Stream::send_response_body(bool call_update) { - Http2ClientSession *_proxy_ssn = static_cast(this->get_proxy_ssn()); - inactive_timeout_at = Thread::get_hrtime() + inactive_timeout; + Http2ClientSession *h2_proxy_ssn = static_cast(this->_proxy_ssn); + inactive_timeout_at = Thread::get_hrtime() + inactive_timeout; if (Http2::stream_priority_enabled) { - SCOPED_MUTEX_LOCK(lock, _proxy_ssn->connection_state.mutex, this_ethread()); - _proxy_ssn->connection_state.schedule_stream(this); + SCOPED_MUTEX_LOCK(lock, h2_proxy_ssn->connection_state.mutex, this_ethread()); + h2_proxy_ssn->connection_state.schedule_stream(this); // signal_write_event() will be called from `Http2ConnectionState::send_data_frames_depends_on_priority()` // when write_vio is consumed } else { - SCOPED_MUTEX_LOCK(lock, _proxy_ssn->connection_state.mutex, this_ethread()); - _proxy_ssn->connection_state.send_data_frames(this); + SCOPED_MUTEX_LOCK(lock, h2_proxy_ssn->connection_state.mutex, this_ethread()); + h2_proxy_ssn->connection_state.send_data_frames(this); this->signal_write_event(call_update); // XXX The call to signal_write_event can destroy/free the Http2Stream. // Don't modify the Http2Stream after calling this method. From b24544c004108a22ce698abfaea6211d23a03e71 Mon Sep 17 00:00:00 2001 From: Susan Hinrichs Date: Mon, 23 Sep 2019 17:28:27 +0000 Subject: [PATCH 079/718] Log H2 priority information (cherry picked from commit 89cf5afacc6eab8f24eed5ece5eeb2ca36ac5359) Conflicts: proxy/http/HttpSM.h --- doc/admin-guide/logging/formatting.en.rst | 6 +++++ proxy/ProxyTransaction.cc | 12 +++++++++ proxy/ProxyTransaction.h | 8 +++--- proxy/http/HttpSM.cc | 4 ++- proxy/http/HttpSM.h | 18 +++++++++++++ proxy/http2/Http2Stream.cc | 16 ++++++++++++ proxy/http2/Http2Stream.h | 2 ++ proxy/logging/Log.cc | 10 +++++++ proxy/logging/LogAccess.cc | 32 +++++++++++++++++++++++ proxy/logging/LogAccess.h | 20 +++++++------- 10 files changed, 115 insertions(+), 13 deletions(-) diff --git a/doc/admin-guide/logging/formatting.en.rst b/doc/admin-guide/logging/formatting.en.rst index dc416d314b3..43ec49c27d9 100644 --- a/doc/admin-guide/logging/formatting.en.rst +++ b/doc/admin-guide/logging/formatting.en.rst @@ -184,6 +184,8 @@ Connections and Transactions .. _sstc: .. _ccid: .. _ctid: +.. _ctpw: +.. _ctpd: The following log fields are used to list various details of connections and transactions between |TS| proxies and origin servers. @@ -203,6 +205,10 @@ ctid Client Request Client Transaction ID, a non-negative number for a transact which is different for all currently-active transactions on the same client connection. For client HTTP/2 transactions, this value is the stream ID for the transaction. +ctpw Client Request Client Transaction Priority Weight, the priority weight for the + underlying HTTP/2 protocol. +ctpd Client Request Client Transaction Priority Dependence, the transaction ID that + the current transaction depends on for HTTP/2 priority logic. ===== ============== ================================================================== .. _admin-logging-fields-content-type: diff --git a/proxy/ProxyTransaction.cc b/proxy/ProxyTransaction.cc index 6cce239b622..73843e8c7a9 100644 --- a/proxy/ProxyTransaction.cc +++ b/proxy/ProxyTransaction.cc @@ -199,3 +199,15 @@ void ProxyTransaction::set_h2c_upgrade_flag() { } + +int +ProxyTransaction::get_transaction_priority_weight() const +{ + return 0; +} + +int +ProxyTransaction::get_transaction_priority_dependence() const +{ + return 0; +} diff --git a/proxy/ProxyTransaction.h b/proxy/ProxyTransaction.h index 085e6042001..60a99940ffc 100644 --- a/proxy/ProxyTransaction.h +++ b/proxy/ProxyTransaction.h @@ -50,9 +50,11 @@ class ProxyTransaction : public VConnection virtual void set_inactivity_timeout(ink_hrtime timeout_in) = 0; virtual void cancel_inactivity_timeout() = 0; virtual int get_transaction_id() const = 0; - virtual bool allow_half_open() const = 0; - virtual void increment_client_transactions_stat() = 0; - virtual void decrement_client_transactions_stat() = 0; + virtual int get_transaction_priority_weight() const; + virtual int get_transaction_priority_dependence() const; + virtual bool allow_half_open() const = 0; + virtual void increment_client_transactions_stat() = 0; + virtual void decrement_client_transactions_stat() = 0; virtual NetVConnection *get_netvc() const; virtual bool is_first_transaction() const; diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc index c03060590f7..9f3eb4b8505 100644 --- a/proxy/http/HttpSM.cc +++ b/proxy/http/HttpSM.cc @@ -440,7 +440,9 @@ HttpSM::attach_client_session(ProxyTransaction *client_vc, IOBufferReader *buffe // It seems to be possible that the ua_txn pointer will go stale before log entries for this HTTP transaction are // generated. Therefore, collect information that may be needed for logging from the ua_txn object at this point. // - _client_transaction_id = ua_txn->get_transaction_id(); + _client_transaction_id = ua_txn->get_transaction_id(); + _client_transaction_priority_weight = ua_txn->get_transaction_priority_weight(); + _client_transaction_priority_dependence = ua_txn->get_transaction_priority_dependence(); { auto p = ua_txn->get_proxy_ssn(); diff --git a/proxy/http/HttpSM.h b/proxy/http/HttpSM.h index ab26c66eab7..1f237effb2e 100644 --- a/proxy/http/HttpSM.h +++ b/proxy/http/HttpSM.h @@ -612,9 +612,27 @@ class HttpSM : public Continuation return _client_transaction_id; } + int + client_transaction_priority_weight() const + { + return _client_transaction_priority_weight; + } + + int + client_transaction_priority_dependence() const + { + return _client_transaction_priority_dependence; + } + + void set_server_netvc_inactivity_timeout(NetVConnection *netvc); + void set_server_netvc_active_timeout(NetVConnection *netvc); + void set_server_netvc_connect_timeout(NetVConnection *netvc); + void rewind_state_machine(); + private: PostDataBuffers _postbuf; int _client_connection_id = -1, _client_transaction_id = -1; + int _client_transaction_priority_weight = -1, _client_transaction_priority_dependence = -1; }; // Function to get the cache_sm object - YTS Team, yamsat diff --git a/proxy/http2/Http2Stream.cc b/proxy/http2/Http2Stream.cc index bbd16f0b669..fad170cf55e 100644 --- a/proxy/http2/Http2Stream.cc +++ b/proxy/http2/Http2Stream.cc @@ -1063,3 +1063,19 @@ Http2Stream::mark_body_done() this->write_vio.nbytes = response_header.length_get() + chunked_handler.dechunked_size; } } + +int +Http2Stream::get_transaction_priority_weight() const +{ + return priority_node ? priority_node->weight : 0; +} + +int +Http2Stream::get_transaction_priority_dependence() const +{ + if (!priority_node) { + return -1; + } else { + return priority_node->parent ? priority_node->parent->id : 0; + } +} diff --git a/proxy/http2/Http2Stream.h b/proxy/http2/Http2Stream.h index 20bae58889c..759b0f28171 100644 --- a/proxy/http2/Http2Stream.h +++ b/proxy/http2/Http2Stream.h @@ -97,6 +97,8 @@ class Http2Stream : public ProxyTransaction void increment_client_transactions_stat() override; void decrement_client_transactions_stat() override; int get_transaction_id() const override; + int get_transaction_priority_weight() const override; + int get_transaction_priority_dependence() const override; void clear_inactive_timer(); void clear_active_timer(); diff --git a/proxy/logging/Log.cc b/proxy/logging/Log.cc index 6ceeffa1cc9..60a9460ff19 100644 --- a/proxy/logging/Log.cc +++ b/proxy/logging/Log.cc @@ -887,6 +887,16 @@ Log::init_fields() global_field_list.add(field, false); field_symbol_hash.emplace("ctid", field); + field = new LogField("client_transaction_priority_weight", "ctpw", LogField::sINT, + &LogAccess::marshal_client_http_transaction_priority_weight, &LogAccess::unmarshal_int_to_str); + global_field_list.add(field, false); + field_symbol_hash.emplace("ctpw", field); + + field = new LogField("client_transaction_priority_dependence", "ctpd", LogField::sINT, + &LogAccess::marshal_client_http_transaction_priority_dependence, &LogAccess::unmarshal_int_to_str); + global_field_list.add(field, false); + field_symbol_hash.emplace("ctpd", field); + init_status |= FIELDS_INITIALIZED; } diff --git a/proxy/logging/LogAccess.cc b/proxy/logging/LogAccess.cc index c0c6888b400..22c964a70ca 100644 --- a/proxy/logging/LogAccess.cc +++ b/proxy/logging/LogAccess.cc @@ -2552,6 +2552,38 @@ LogAccess::marshal_client_http_transaction_id(char *buf) return INK_MIN_ALIGN; } +/*------------------------------------------------------------------------- + -------------------------------------------------------------------------*/ + +int +LogAccess::marshal_client_http_transaction_priority_weight(char *buf) +{ + if (buf) { + int64_t id = 0; + if (m_http_sm) { + id = m_http_sm->client_transaction_priority_weight(); + } + marshal_int(buf, id); + } + return INK_MIN_ALIGN; +} + +/*------------------------------------------------------------------------- + -------------------------------------------------------------------------*/ + +int +LogAccess::marshal_client_http_transaction_priority_dependence(char *buf) +{ + if (buf) { + int64_t id = 0; + if (m_http_sm) { + id = m_http_sm->client_transaction_priority_dependence(); + } + marshal_int(buf, id); + } + return INK_MIN_ALIGN; +} + /*------------------------------------------------------------------------- -------------------------------------------------------------------------*/ diff --git a/proxy/logging/LogAccess.h b/proxy/logging/LogAccess.h index 1a8a2ef24f7..0cfb333d0f2 100644 --- a/proxy/logging/LogAccess.h +++ b/proxy/logging/LogAccess.h @@ -239,15 +239,17 @@ class LogAccess // other fields // - inkcoreapi int marshal_transfer_time_ms(char *); // INT - inkcoreapi int marshal_transfer_time_s(char *); // INT - inkcoreapi int marshal_file_size(char *); // INT - inkcoreapi int marshal_plugin_identity_id(char *); // INT - inkcoreapi int marshal_plugin_identity_tag(char *); // STR - inkcoreapi int marshal_process_uuid(char *); // STR - inkcoreapi int marshal_client_http_connection_id(char *); // INT - inkcoreapi int marshal_client_http_transaction_id(char *); // INT - inkcoreapi int marshal_cache_lookup_url_canon(char *); // STR + inkcoreapi int marshal_transfer_time_ms(char *); // INT + inkcoreapi int marshal_transfer_time_s(char *); // INT + inkcoreapi int marshal_file_size(char *); // INT + inkcoreapi int marshal_plugin_identity_id(char *); // INT + inkcoreapi int marshal_plugin_identity_tag(char *); // STR + inkcoreapi int marshal_process_uuid(char *); // STR + inkcoreapi int marshal_client_http_connection_id(char *); // INT + inkcoreapi int marshal_client_http_transaction_id(char *); // INT + inkcoreapi int marshal_client_http_transaction_priority_weight(char *); // INT + inkcoreapi int marshal_client_http_transaction_priority_dependence(char *); // INT + inkcoreapi int marshal_cache_lookup_url_canon(char *); // STR // named fields from within a http header // From 067a3d3e3da96bc5f88bd3248374f22e0b4bb90d Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Wed, 4 Sep 2019 11:58:54 +0900 Subject: [PATCH 080/718] Check F_GETPIPE_SZ is defined to fix macOS build (cherry picked from commit 92d4ef1424f547735bfc33ca847c8ac5ab19cd8a) --- doc/admin-guide/logging/examples.en.rst | 4 ++-- proxy/logging/LogFile.cc | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/doc/admin-guide/logging/examples.en.rst b/doc/admin-guide/logging/examples.en.rst index f1d08409ec8..abe12fbb3b2 100644 --- a/doc/admin-guide/logging/examples.en.rst +++ b/doc/admin-guide/logging/examples.en.rst @@ -303,8 +303,8 @@ Configuring ASCII Pipe Buffer Size ================================== This example mirrors the one above but also sets a ```pipe_buffer_size``` of -1024 * 1024 for the pipe. This can be set on a per-pipe basis but is not -available on FreeBSD dists of ATS. If this field is not set, the pipe buffer +1024 * 1024 for the pipe. This can be set on a per-pipe basis but is only +available on Linux (later than 2.6.35). If this field is not set, the pipe buffer will default to the OS default size. .. code:: yaml diff --git a/proxy/logging/LogFile.cc b/proxy/logging/LogFile.cc index 41543298dce..1d7d0a1c8cd 100644 --- a/proxy/logging/LogFile.cc +++ b/proxy/logging/LogFile.cc @@ -188,9 +188,7 @@ LogFile::open_file() return LOG_FILE_NO_PIPE_READERS; } -#ifdef __FreeBSD__ - // we don't do this for FreeBSD -#else +#ifdef F_GETPIPE_SZ // adjust pipe size if necessary if (m_pipe_buffer_size) { long pipe_size = (long)fcntl(m_fd, F_GETPIPE_SZ); @@ -212,7 +210,7 @@ LogFile::open_file() Debug("log-file", "NEW pipe size for pipe %s = %ld", m_name, pipe_size); } } -#endif +#endif // F_GETPIPE_SZ } else { if (m_log) { int status = m_log->open_file(Log::config->logfile_perm); From 00e067ad80a4ecfa76baf747ad1ff9d11fda12d2 Mon Sep 17 00:00:00 2001 From: Bryan Call Date: Tue, 22 Oct 2019 16:48:39 -0700 Subject: [PATCH 081/718] Doc: Fixed the logging mode of pipe to be ascii_pipe (cherry picked from commit f211041a2f1c0ba41789d5a689e1de86d0d1035b) --- doc/admin-guide/logging/examples.en.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/admin-guide/logging/examples.en.rst b/doc/admin-guide/logging/examples.en.rst index abe12fbb3b2..a4895cfea33 100644 --- a/doc/admin-guide/logging/examples.en.rst +++ b/doc/admin-guide/logging/examples.en.rst @@ -293,7 +293,7 @@ for them to a UNIX pipe that the alerting software can constantly read from. accept: cqup MATCH "/nightmare/scenario/dont/touch" logs: - - mode: pipe + - mode: ascii_pipe format: canaryformat filters: - canaryfilter @@ -310,7 +310,7 @@ will default to the OS default size. .. code:: yaml logs: - - mode: pipe + - mode: ascii_pipe format: canaryformat filters: - canaryfilter From f6c888c4d8c18469a572341345527d6affe56b28 Mon Sep 17 00:00:00 2001 From: Gancho Tenev Date: Mon, 21 Oct 2019 19:27:39 -0700 Subject: [PATCH 082/718] Premature DSO unload with "suicidal" continuations Fixed a problem with premature plugin DSO unloading when the following conditions are met: - if a continuation created from inside a plugin outlives the last configuration object that used it and becomes the last object relying on the plugin DSO - if the continuation event handler logic decides to destroy its own continuation with `TSContDestroy()` then the plugin DSO would get unloaded immediately before the event handler function reaches its end. (cherry picked from commit c269a5a8d2bed870f6cf27555a6673041beea655) --- proxy/http/remap/Makefile.am | 26 +++-- proxy/http/remap/PluginDso.cc | 96 ++++++++++++++++--- proxy/http/remap/PluginDso.h | 29 +++++- proxy/http/remap/PluginFactory.cc | 47 +++------ proxy/http/remap/PluginFactory.h | 3 +- proxy/http/remap/RemapConfig.cc | 1 + proxy/http/remap/RemapPluginInfo.cc | 20 ++-- .../remap/unit-tests/plugin_testing_common.h | 5 +- .../remap/unit-tests/test_PluginFactory.cc | 24 +++++ 9 files changed, 183 insertions(+), 68 deletions(-) diff --git a/proxy/http/remap/Makefile.am b/proxy/http/remap/Makefile.am index 8973d1b7710..8275166371d 100644 --- a/proxy/http/remap/Makefile.am +++ b/proxy/http/remap/Makefile.am @@ -54,6 +54,16 @@ libhttp_remap_a_SOURCES = \ UrlRewrite.cc \ UrlRewrite.h +COMMON_PLUGINDSO_LDADDS = \ + $(OPENSSL_LIBS) \ + $(top_builddir)/iocore/eventsystem/libinkevent.a \ + $(top_builddir)/lib/records/librecords_p.a \ + $(top_builddir)/iocore/eventsystem/libinkevent.a \ + $(top_builddir)/src/tscore/libtscore.la \ + $(top_builddir)/mgmt/libmgmt_p.la \ + $(top_builddir)/proxy/shared/libUglyLogStubs.a \ + @HWLOC_LIBS@ + clang-tidy-local: $(libhttp_remap_a_SOURCES) $(CXX_Clang_Tidy) @@ -61,18 +71,20 @@ TESTS = $(check_PROGRAMS) check_PROGRAMS = test_PluginDso test_PluginFactory test_RemapPluginInfo test_PluginDso_CPPFLAGS = $(AM_CPPFLAGS) -I$(abs_top_srcdir)/tests/include -DPLUGIN_DSO_TESTS +test_PluginDso_LIBTOOLFLAGS = --preserve-dup-deps EXTRA_test_PluginDso_DEPENDENCIES = unit-tests/plugin_v1.la -test_PluginDso_LDADD = $(OPENSSL_LIBS) -test_PluginDso_LDFLAGS = $(AM_LDFLAGS) -L$(top_builddir)/src/tscore/.libs -ltscore +test_PluginDso_LDADD = $(COMMON_PLUGINDSO_LDADDS) +test_PluginDso_LDFLAGS = $(AM_LDFLAGS) test_PluginDso_SOURCES = \ unit-tests/test_PluginDso.cc \ unit-tests/plugin_testing_common.cc \ PluginDso.cc test_PluginFactory_CPPFLAGS = $(AM_CPPFLAGS) -I$(abs_top_srcdir)/tests/include -DPLUGIN_DSO_TESTS +test_PluginFactory_LIBTOOLFLAGS = --preserve-dup-deps EXTRA_test_PluginFactory_DEPENDENCIES = unit-tests/plugin_v1.la -test_PluginFactory_LDADD = $(OPENSSL_LIBS) -test_PluginFactory_LDFLAGS = $(AM_LDFLAGS) -L$(top_builddir)/src/tscore/.libs -ltscore +test_PluginFactory_LDADD = $(COMMON_PLUGINDSO_LDADDS) +test_PluginFactory_LDFLAGS = $(AM_LDFLAGS) test_PluginFactory_SOURCES = \ unit-tests/test_PluginFactory.cc \ unit-tests/plugin_testing_common.cc \ @@ -81,6 +93,7 @@ test_PluginFactory_SOURCES = \ RemapPluginInfo.cc test_RemapPluginInfo_CPPFLAGS = $(AM_CPPFLAGS) -I$(abs_top_srcdir)/tests/include -DPLUGIN_DSO_TESTS +test_RemapPluginInfo_LIBTOOLFLAGS = --preserve-dup-deps EXTRA_test_RemapPluginInfo_DEPENDENCIES = \ unit-tests/plugin_missing_init.la \ unit-tests/plugin_missing_doremap.la \ @@ -88,9 +101,8 @@ EXTRA_test_RemapPluginInfo_DEPENDENCIES = \ unit-tests/plugin_required_cb.la \ unit-tests/plugin_missing_newinstance.la \ unit-tests/plugin_testing_calls.la -test_RemapPluginInfo_LDADD = \ - $(OPENSSL_LIBS) -test_RemapPluginInfo_LDFLAGS = $(AM_LDFLAGS) -L$(top_builddir)/src/tscore/.libs -ltscore +test_RemapPluginInfo_LDADD = $(COMMON_PLUGINDSO_LDADDS) +test_RemapPluginInfo_LDFLAGS = $(AM_LDFLAGS) test_RemapPluginInfo_SOURCES = \ unit-tests/plugin_testing_common.cc \ unit-tests/plugin_testing_calls.cc \ diff --git a/proxy/http/remap/PluginDso.cc b/proxy/http/remap/PluginDso.cc index 24490fc044d..7bd4dcf71af 100644 --- a/proxy/http/remap/PluginDso.cc +++ b/proxy/http/remap/PluginDso.cc @@ -28,10 +28,14 @@ */ #include "PluginDso.h" +#include "P_Freer.h" +#include "P_EventSystem.h" #ifdef PLUGIN_DSO_TESTS #include "unit-tests/plugin_testing_common.h" #else #include "tscore/Diags.h" +#define PluginDebug Debug +#define PluginError Error #endif PluginDso::PluginDso(const fs::path &configPath, const fs::path &effectivePath, const fs::path &runtimePath) @@ -58,14 +62,14 @@ PluginDso::load(std::string &error) return false; } - Debug(_tag, "plugin '%s' started loading DSO", _configPath.c_str()); + PluginDebug(_tag, "plugin '%s' started loading DSO", _configPath.c_str()); /* Find plugin DSO looking through the search dirs */ if (_effectivePath.empty()) { error.append("empty effective path"); result = false; } else { - Debug(_tag, "plugin '%s' effective path: %s", _configPath.c_str(), _effectivePath.c_str()); + PluginDebug(_tag, "plugin '%s' effective path: %s", _configPath.c_str(), _effectivePath.c_str()); /* Copy the installed plugin DSO to a runtime directory */ std::error_code ec; @@ -75,13 +79,13 @@ PluginDso::load(std::string &error) error.assign(temp_error); result = false; } else { - Debug(_tag, "plugin '%s' runtime path: %s", _configPath.c_str(), _runtimePath.c_str()); + PluginDebug(_tag, "plugin '%s' runtime path: %s", _configPath.c_str(), _runtimePath.c_str()); /* Save the time for later checking if DSO got modified in consecutive DSO reloads */ std::error_code ec; fs::file_status fs = fs::status(_effectivePath, ec); _mtime = fs::modification_time(fs); - Debug(_tag, "plugin '%s' mоdification time %ld", _configPath.c_str(), _mtime); + PluginDebug(_tag, "plugin '%s' mоdification time %ld", _configPath.c_str(), _mtime); /* Now attemt to load the plugin DSO */ if ((_dlh = dlopen(_runtimePath.c_str(), RTLD_NOW)) == nullptr) { @@ -96,7 +100,7 @@ PluginDso::load(std::string &error) clean(error); result = false; - Error("plugin '%s' failed to load: %s", _configPath.c_str(), error.c_str()); + PluginError("plugin '%s' failed to load: %s", _configPath.c_str(), error.c_str()); } } @@ -105,7 +109,7 @@ PluginDso::load(std::string &error) clean(error); } } - Debug(_tag, "plugin '%s' finished loading DSO", _configPath.c_str()); + PluginDebug(_tag, "plugin '%s' finished loading DSO", _configPath.c_str()); return result; } @@ -229,17 +233,16 @@ void PluginDso::acquire() { this->refcount_inc(); - Debug(_tag, "plugin DSO acquire (ref-count:%d, dso-addr:%p)", this->refcount(), this); + PluginDebug(_tag, "plugin DSO acquire (ref-count:%d, dso-addr:%p)", this->refcount(), this); } void PluginDso::release() { - Debug(_tag, "plugin DSO release (ref-count:%d, dso-addr:%p)", this->refcount() - 1, this); + PluginDebug(_tag, "plugin DSO release (ref-count:%d, dso-addr:%p)", this->refcount() - 1, this); if (0 == this->refcount_dec()) { - Debug(_tag, "unloading plugin DSO '%s' (dso-addr:%p)", _configPath.c_str(), this); - _list.erase(this); - delete this; + PluginDebug(_tag, "unloading plugin DSO '%s' (dso-addr:%p)", _configPath.c_str(), this); + _plugins->remove(this); } } @@ -247,14 +250,14 @@ void PluginDso::incInstanceCount() { _instanceCount.refcount_inc(); - Debug(_tag, "instance count (inst-count:%d, dso-addr:%p)", _instanceCount.refcount(), this); + PluginDebug(_tag, "instance count (inst-count:%d, dso-addr:%p)", _instanceCount.refcount(), this); } void PluginDso::decInstanceCount() { _instanceCount.refcount_dec(); - Debug(_tag, "instance count (inst-count:%d, dso-addr:%p)", _instanceCount.refcount(), this); + PluginDebug(_tag, "instance count (inst-count:%d, dso-addr:%p)", _instanceCount.refcount(), this); } int @@ -263,4 +266,69 @@ PluginDso::instanceCount() return _instanceCount.refcount(); } -PluginDso::PluginList PluginDso::_list; +void +PluginDso::LoadedPlugins::add(PluginDso *plugin) +{ + SCOPED_MUTEX_LOCK(lock, _mutex, this_ethread()); + + _list.append(plugin); +} + +void +PluginDso::LoadedPlugins::remove(PluginDso *plugin) +{ + SCOPED_MUTEX_LOCK(lock, _mutex, this_ethread()); + + _list.erase(plugin); + this_ethread()->schedule_imm(new DeleterContinuation(plugin)); +} + +PluginDso * +PluginDso::LoadedPlugins::findByEffectivePath(const fs::path &path) +{ + struct stat sb; + time_t mtime = 0; + if (0 == stat(path.c_str(), &sb)) { + mtime = sb.st_mtime; + } + + SCOPED_MUTEX_LOCK(lock, _mutex, this_ethread()); + + auto spot = std::find_if(_list.begin(), _list.end(), [&](PluginDso const &plugin) -> bool { + return (0 == path.string().compare(plugin.effectivePath().string()) && (mtime == plugin.modTime())); + }); + return spot == _list.end() ? nullptr : static_cast(spot); +} + +void +PluginDso::LoadedPlugins::indicatePreReload(const char *factoryId) +{ + SCOPED_MUTEX_LOCK(lock, _mutex, this_ethread()); + + PluginDebug(_tag, "indicated config is going to be reloaded by factory '%s' to %zu plugin%s", factoryId, _list.count(), + _list.count() != 1 ? "s" : ""); + + _list.apply([](PluginDso &plugin) -> void { plugin.indicatePreReload(); }); +} + +void +PluginDso::LoadedPlugins::indicatePostReload(bool reloadSuccessful, const std::unordered_map &pluginUsed, + const char *factoryId) +{ + SCOPED_MUTEX_LOCK(lock, _mutex, this_ethread()); + + PluginDebug(_tag, "indicated config is done reloading by factory '%s' to %zu plugin%s", factoryId, _list.count(), + _list.count() != 1 ? "s" : ""); + + for (auto &plugin : _list) { + TSRemapReloadStatus status = TSREMAP_CONFIG_RELOAD_FAILURE; + if (reloadSuccessful) { + /* reload succeeded but was the plugin instantiated by this factory? */ + status = (pluginUsed.end() == pluginUsed.find(&plugin) ? TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED : + TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED); + } + plugin.indicatePostReload(status); + } +} + +Ptr PluginDso::_plugins; diff --git a/proxy/http/remap/PluginDso.h b/proxy/http/remap/PluginDso.h index e5427187323..47fc0801470 100644 --- a/proxy/http/remap/PluginDso.h +++ b/proxy/http/remap/PluginDso.h @@ -29,6 +29,7 @@ #pragma once +#include #include #include #include @@ -39,6 +40,7 @@ namespace fs = ts::file; #include "tscore/Ptr.h" +#include "I_EventSystem.h" #include "tscpp/util/IntrusiveDList.h" class PluginThreadContext : public RefCountObj @@ -88,6 +90,30 @@ class PluginDso : public PluginThreadContext void decInstanceCount(); int instanceCount(); + class LoadedPlugins : public RefCountObj + { + public: + LoadedPlugins() : _mutex(new_ProxyMutex()) {} + void add(PluginDso *plugin); + void remove(PluginDso *plugin); + PluginDso *findByEffectivePath(const fs::path &path); + void indicatePreReload(const char *factoryId); + void indicatePostReload(bool reloadSuccessful, const std::unordered_map &pluginUsed, const char *factoryId); + + private: + PluginList _list; /** @brief plugin list */ + Ptr _mutex; /** @brief mutex used when updating the plugin list from multiple threads */ + }; + + static const Ptr & + loadedPlugins() + { + if (!_plugins) { + _plugins = new LoadedPlugins(); + } + return _plugins; + } + protected: void clean(std::string &error); @@ -102,6 +128,7 @@ class PluginDso : public PluginThreadContext time_t _mtime = 0; /* @brief modification time of the DSO's file, used for checking */ bool _preventiveCleaning = true; - static PluginList _list; /** @brief a global list of plugins, usually maintained by a plugin factory or plugin instance itself */ + static Ptr + _plugins; /** @brief a global list of plugins, usually maintained by a plugin factory or plugin instance itself */ RefCountObj _instanceCount; /** @brief used for properly calling "done" and "indicate config reload" methods by the factory */ }; diff --git a/proxy/http/remap/PluginFactory.cc b/proxy/http/remap/PluginFactory.cc index 9491228df2e..8fc55afda63 100644 --- a/proxy/http/remap/PluginFactory.cc +++ b/proxy/http/remap/PluginFactory.cc @@ -30,7 +30,10 @@ #include "unit-tests/plugin_testing_common.h" #else #include "tscore/Diags.h" +#define PluginDebug Debug +#define PluginError Error #endif +#include "P_EventSystem.h" #include /* std::swap */ @@ -91,7 +94,7 @@ PluginFactory::PluginFactory() } } - Debug(_tag, "created plugin factory %s", getUuid()); + PluginDebug(_tag, "created plugin factory %s", getUuid()); } PluginFactory::~PluginFactory() @@ -101,7 +104,7 @@ PluginFactory::~PluginFactory() fs::remove(_runtimeDir, _ec); - Debug(_tag, "destroyed plugin factory %s", getUuid()); + PluginDebug(_tag, "destroyed plugin factory %s", getUuid()); delete _uuid; } @@ -109,7 +112,7 @@ PluginFactory & PluginFactory::addSearchDir(const fs::path &searchDir) { _searchDirs.push_back(searchDir); - Debug(_tag, "added plugin search dir %s", searchDir.c_str()); + PluginDebug(_tag, "added plugin search dir %s", searchDir.c_str()); return *this; } @@ -117,7 +120,7 @@ PluginFactory & PluginFactory::setRuntimeDir(const fs::path &runtimeDir) { _runtimeDir = runtimeDir / fs::path(getUuid()); - Debug(_tag, "set plugin runtime dir %s", runtimeDir.c_str()); + PluginDebug(_tag, "set plugin runtime dir %s", runtimeDir.c_str()); return *this; } @@ -153,7 +156,7 @@ PluginFactory::getRemapPlugin(const fs::path &configPath, int argc, char **argv, if (nullptr == plugin) { /* The plugin requested have not been loaded yet. */ - Debug(_tag, "plugin '%s' has not been loaded yet, loading as remap plugin", configPath.c_str()); + PluginDebug(_tag, "plugin '%s' has not been loaded yet, loading as remap plugin", configPath.c_str()); fs::path runtimePath; runtimePath /= _runtimeDir; @@ -168,7 +171,7 @@ PluginFactory::getRemapPlugin(const fs::path &configPath, int argc, char **argv, plugin = new RemapPluginInfo(configPath, effectivePath, runtimePath); if (nullptr != plugin) { if (plugin->load(error)) { - _list.append(plugin); + PluginDso::loadedPlugins()->add(plugin); if (plugin->init(error)) { inst = RemapPluginInst::init(plugin, argc, argv, error); @@ -185,7 +188,7 @@ PluginFactory::getRemapPlugin(const fs::path &configPath, int argc, char **argv, } } } else { - Debug(_tag, "plugin '%s' has already been loaded", configPath.c_str()); + PluginDebug(_tag, "plugin '%s' has already been loaded", configPath.c_str()); inst = RemapPluginInst::init(plugin, argc, argv, error); if (nullptr != inst) { _instList.append(inst); @@ -234,15 +237,7 @@ PluginFactory::getEffectivePath(const fs::path &configPath) PluginDso * PluginFactory::findByEffectivePath(const fs::path &path) { - struct stat sb; - time_t mtime = 0; - if (0 == stat(path.c_str(), &sb)) { - mtime = sb.st_mtime; - } - auto spot = std::find_if(_list.begin(), _list.end(), [&](PluginDso const &plugin) -> bool { - return (0 == path.string().compare(plugin.effectivePath().string()) && (mtime == plugin.modTime())); - }); - return spot == _list.end() ? nullptr : static_cast(spot); + return PluginDso::loadedPlugins()->findByEffectivePath(path); } /** @@ -255,7 +250,7 @@ PluginFactory::findByEffectivePath(const fs::path &path) void PluginFactory::deactivate() { - Debug(_tag, "deactivate configuration used by factory '%s'", getUuid()); + PluginDebug(_tag, "deactivate configuration used by factory '%s'", getUuid()); _instList.apply([](RemapPluginInst &pluginInst) -> void { pluginInst.done(); }); } @@ -266,10 +261,7 @@ PluginFactory::deactivate() void PluginFactory::indicatePreReload() { - Debug(_tag, "indicated config is going to be reloaded by factory '%s' to %zu plugin%s", getUuid(), _list.count(), - _list.count() != 1 ? "s" : ""); - - _list.apply([](PluginDso &plugin) -> void { plugin.indicatePreReload(); }); + PluginDso::loadedPlugins()->indicatePreReload(getUuid()); } /** @@ -278,24 +270,13 @@ PluginFactory::indicatePreReload() void PluginFactory::indicatePostReload(bool reloadSuccessful) { - Debug(_tag, "indicated config is done reloading by factory '%s' to %zu plugin%s", getUuid(), _list.count(), - _list.count() != 1 ? "s" : ""); - /* Find out which plugins (DSO) are actually instantiated by this factory */ std::unordered_map pluginUsed; for (auto &inst : _instList) { pluginUsed[&(inst._plugin)]++; } - for (auto &plugin : _list) { - TSRemapReloadStatus status = TSREMAP_CONFIG_RELOAD_FAILURE; - if (reloadSuccessful) { - /* reload succeeded but was the plugin instantiated by this factory? */ - status = (pluginUsed.end() == pluginUsed.find(&plugin) ? TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED : - TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED); - } - plugin.indicatePostReload(status); - } + PluginDso::loadedPlugins()->indicatePostReload(reloadSuccessful, pluginUsed, getUuid()); } void diff --git a/proxy/http/remap/PluginFactory.h b/proxy/http/remap/PluginFactory.h index 5982db45a30..3c2902ced84 100644 --- a/proxy/http/remap/PluginFactory.h +++ b/proxy/http/remap/PluginFactory.h @@ -85,8 +85,7 @@ class RemapPluginInst */ class PluginFactory { - using PluginInstList = ts::IntrusiveDList; - PluginDso::PluginList &_list = PluginDso::_list; + using PluginInstList = ts::IntrusiveDList; public: PluginFactory(); diff --git a/proxy/http/remap/RemapConfig.cc b/proxy/http/remap/RemapConfig.cc index 424f4bfac8c..63bca48db1b 100644 --- a/proxy/http/remap/RemapConfig.cc +++ b/proxy/http/remap/RemapConfig.cc @@ -815,6 +815,7 @@ remap_load_plugin(const char **argv, int argc, url_mapping *mp, char *errbuf, in bool result = true; if (nullptr == pi) { snprintf(errbuf, errbufsize, "%s", error.c_str()); + result = false; } else { mp->add_plugin_instance(pi); } diff --git a/proxy/http/remap/RemapPluginInfo.cc b/proxy/http/remap/RemapPluginInfo.cc index 8f8962b1747..736fd4d6727 100644 --- a/proxy/http/remap/RemapPluginInfo.cc +++ b/proxy/http/remap/RemapPluginInfo.cc @@ -34,6 +34,8 @@ #include "unit-tests/plugin_testing_common.h" #else #include "tscore/Diags.h" +#define PluginDebug Debug +#define PluginError Error #endif /** @@ -53,7 +55,7 @@ RemapPluginInfo::getFunctionSymbol(const char *symbol) std::string error; /* ignore the error, return nullptr if symbol not defined */ void *address = nullptr; if (getSymbol(symbol, address, error)) { - Debug(_tag, "plugin '%s' found symbol '%s'", _configPath.c_str(), symbol); + PluginDebug(_tag, "plugin '%s' found symbol '%s'", _configPath.c_str(), symbol); } return reinterpret_cast(address); } @@ -109,9 +111,9 @@ RemapPluginInfo::load(std::string &error) } if (valid) { - Debug(_tag, "plugin '%s' callbacks validated", _configPath.c_str()); + PluginDebug(_tag, "plugin '%s' callbacks validated", _configPath.c_str()); } else { - Error("plugin '%s' callbacks validation failed: %s", _configPath.c_str(), error.c_str()); + PluginError("plugin '%s' callbacks validation failed: %s", _configPath.c_str(), error.c_str()); } return valid; } @@ -123,7 +125,7 @@ RemapPluginInfo::init(std::string &error) TSRemapInterface ri; bool result = true; - Debug(_tag, "started initializing plugin '%s'", _configPath.c_str()); + PluginDebug(_tag, "started initializing plugin '%s'", _configPath.c_str()); /* A buffer to get the error from the plugin instance init function, be defensive here. */ char tmpbuf[2048]; @@ -145,7 +147,7 @@ RemapPluginInfo::init(std::string &error) resetPluginContext(); - Debug(_tag, "finished initializing plugin '%s'", _configPath.c_str()); + PluginDebug(_tag, "finished initializing plugin '%s'", _configPath.c_str()); return result; } @@ -165,7 +167,7 @@ RemapPluginInfo::initInstance(int argc, char **argv, void **ih, std::string &err TSReturnCode res = TS_SUCCESS; bool result = true; - Debug(_tag, "started initializing instance of plugin '%s'", _configPath.c_str()); + PluginDebug(_tag, "started initializing instance of plugin '%s'", _configPath.c_str()); /* A buffer to get the error from the plugin instance init function, be defensive here. */ char tmpbuf[2048]; @@ -198,7 +200,7 @@ RemapPluginInfo::initInstance(int argc, char **argv, void **ih, std::string &err } } - Debug(_tag, "finished initializing instance of plugin '%s'", _configPath.c_str()); + PluginDebug(_tag, "finished initializing instance of plugin '%s'", _configPath.c_str()); return result; } @@ -274,12 +276,12 @@ RemapPluginInfo::setPluginContext() { _tempContext = pluginThreadContext; pluginThreadContext = this; - Debug(_tag, "change plugin context from dso-addr:%p to dso-addr:%p", pluginThreadContext, _tempContext); + PluginDebug(_tag, "change plugin context from dso-addr:%p to dso-addr:%p", pluginThreadContext, _tempContext); } inline void RemapPluginInfo::resetPluginContext() { - Debug(_tag, "change plugin context from dso-addr:%p to dso-addr:%p (restore)", this, pluginThreadContext); + PluginDebug(_tag, "change plugin context from dso-addr:%p to dso-addr:%p (restore)", this, pluginThreadContext); pluginThreadContext = _tempContext; } diff --git a/proxy/http/remap/unit-tests/plugin_testing_common.h b/proxy/http/remap/unit-tests/plugin_testing_common.h index f96c42031cf..fd01dd05683 100644 --- a/proxy/http/remap/unit-tests/plugin_testing_common.h +++ b/proxy/http/remap/unit-tests/plugin_testing_common.h @@ -93,8 +93,9 @@ extern "C" { typedef void *GetPluginDebugObjectFunction(void); GetPluginDebugObjectFunction getPluginDebugObjectTest; -#define Debug(category, fmt, ...) PrintToStdErr("(%s) %s:%d:%s() " fmt "\n", category, __FILE__, __LINE__, __func__, ##__VA_ARGS__) -#define Error(fmt, ...) PrintToStdErr("%s:%d:%s() " fmt "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__) +#define PluginDebug(category, fmt, ...) \ + PrintToStdErr("(%s) %s:%d:%s() " fmt "\n", category, __FILE__, __LINE__, __func__, ##__VA_ARGS__) +#define PluginError(fmt, ...) PrintToStdErr("%s:%d:%s() " fmt "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__) void PrintToStdErr(const char *fmt, ...); #ifdef __cplusplus diff --git a/proxy/http/remap/unit-tests/test_PluginFactory.cc b/proxy/http/remap/unit-tests/test_PluginFactory.cc index 1456f206a79..d42f0588cc8 100644 --- a/proxy/http/remap/unit-tests/test_PluginFactory.cc +++ b/proxy/http/remap/unit-tests/test_PluginFactory.cc @@ -35,6 +35,30 @@ #include "plugin_testing_common.h" #include "../PluginFactory.h" #include "../PluginDso.h" +#include "I_EventSystem.h" +#include "tscore/I_Layout.h" +#include "diags.i" + +#define TEST_THREADS 2 +struct EventProcessorListener : Catch::TestEventListenerBase { + using TestEventListenerBase::TestEventListenerBase; + + void + testRunStarting(Catch::TestRunInfo const &testRunInfo) override + { + Layout::create(); + init_diags("", nullptr); + RecProcessInit(RECM_STAND_ALONE); + + ink_event_system_init(EVENT_SYSTEM_MODULE_PUBLIC_VERSION); + eventProcessor.start(TEST_THREADS, 1048576); + + EThread *main_thread = new EThread; + main_thread->set_specific(); + } +}; + +CATCH_REGISTER_LISTENER(EventProcessorListener); thread_local PluginThreadContext *pluginThreadContext; From 5cb5590efb4c96f91d064358eeb06c031c9a1822 Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Thu, 24 Oct 2019 20:48:10 -0600 Subject: [PATCH 083/718] Upgrade warning about cachekey behavior --- doc/release-notes/upgrading.en.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/release-notes/upgrading.en.rst b/doc/release-notes/upgrading.en.rst index 9f9204fbae0..b70c93c0ed3 100644 --- a/doc/release-notes/upgrading.en.rst +++ b/doc/release-notes/upgrading.en.rst @@ -42,6 +42,12 @@ Cache The cache in this releases of ATS is compatible with previous versions of ATS. You would not expect to lose your cache, or have to reinitialize the cache when upgrading. +However, due to changes in how remap plugins are processed, your cache key *might* change. In versions +to v9.0.0, the first plugin in a remap rule would get the pristine URL, and subsequent plugins would +get the remapped URL. As of v9.0.0, **all** plugins now receive the remapped URL. If you are using +a plugin that modifies the cache key, e.g. :ref:`admin-plugins-cachekey`, if it was evaluated first +in a remap rule, the behavior (input) changes, and therefore, cache keys can change! + Configuration changes --------------------- The following incompatible changes to the configurations have been made in this version of ATS. From e0af528971648a32fef038a4751556e9cfa3ff49 Mon Sep 17 00:00:00 2001 From: Vijay Mamidi Date: Sat, 12 Oct 2019 21:45:25 +0000 Subject: [PATCH 084/718] support for listening on all the net threads uses epollexclusive flag and soreuseport (cherry picked from commit 4dc8dc7f787fcb484e85b6dcf646c189a74fb1b3) --- doc/admin-guide/files/records.config.en.rst | 14 +++++ iocore/net/Connection.cc | 14 ++++- iocore/net/P_NetAccept.h | 1 + iocore/net/P_UnixNet.h | 5 +- iocore/net/UnixNet.cc | 2 + iocore/net/UnixNetAccept.cc | 70 +++++++++++++-------- iocore/net/UnixNetProcessor.cc | 7 ++- mgmt/RecordsConfig.cc | 2 + src/traffic_manager/traffic_manager.cc | 5 ++ 9 files changed, 92 insertions(+), 28 deletions(-) diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst index ea7dfb8642a..f875519d90e 100644 --- a/doc/admin-guide/files/records.config.en.rst +++ b/doc/admin-guide/files/records.config.en.rst @@ -317,11 +317,25 @@ Thread Variables The number of threads |TS| will create if `proxy.config.exec_thread.autoconfig` is set to ``0``, otherwise this option is ignored. +.. ts:cv:: CONFIG proxy.config.exec_thread.listen INT 0 + + If enabled (``1``) all the exex_threads listen for incoming connections. `proxy.config.accept_threads` + should be disabled to enable this variable. + .. ts:cv:: CONFIG proxy.config.accept_threads INT 1 The number of accept threads. If disabled (``0``), then accepts will be done in each of the worker threads. + ============== ================== =================== + accept_threads exec_thread.listen Effect + ============== ================== =================== + ``0`` ``0`` All worker threads accept new connections and share listen fd. + ``1`` ``0`` New conections are accepted on a dedicated accept thread and distributed to worker threads in round robin fashion. + ``0`` ``1`` All worker threads listen on the same port using SO_REUSEPORT. + Each thread has its own listen and new connections are accepted on all the threads. + + By default, `proxy.config.accept_threads` is set to 1 and `proxy.config.exec_thread.listen` is set to 0. .. ts:cv:: CONFIG proxy.config.thread.default.stacksize INT 1048576 Default thread stack size, in bytes, for all threads (default is 1 MB). diff --git a/iocore/net/Connection.cc b/iocore/net/Connection.cc index da7f530c9b4..99c10880331 100644 --- a/iocore/net/Connection.cc +++ b/iocore/net/Connection.cc @@ -136,7 +136,8 @@ add_http_filter(int fd ATS_UNUSED) int Server::setup_fd_for_listen(bool non_blocking, const NetProcessor::AcceptOptions &opt) { - int res = 0; + int res = 0; + int listen_per_thread = 0; ink_assert(fd != NO_FD); @@ -212,6 +213,17 @@ Server::setup_fd_for_listen(bool non_blocking, const NetProcessor::AcceptOptions if ((res = safe_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, SOCKOPT_ON, sizeof(int))) < 0) { goto Lerror; } + REC_ReadConfigInteger(listen_per_thread, "proxy.config.exec_thread.listen"); + if (listen_per_thread == 1) { + if ((res = safe_setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, SOCKOPT_ON, sizeof(int))) < 0) { + goto Lerror; + } +#ifdef SO_REUSEPORT_LB + if ((res = safe_setsockopt(fd, SOL_SOCKET, SO_REUSEPORT_LB, SOCKOPT_ON, sizeof(int))) < 0) { + goto Lerror; + } +#endif + } if ((opt.sockopt_flags & NetVCOptions::SOCK_OPT_NO_DELAY) && (res = safe_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, SOCKOPT_ON, sizeof(int))) < 0) { diff --git a/iocore/net/P_NetAccept.h b/iocore/net/P_NetAccept.h index aa136b0fb7a..db7ceb6ce88 100644 --- a/iocore/net/P_NetAccept.h +++ b/iocore/net/P_NetAccept.h @@ -107,6 +107,7 @@ struct NetAccept : public Continuation { virtual int acceptEvent(int event, void *e); virtual int acceptFastEvent(int event, void *e); + virtual int accept_per_thread(int event, void *e); int acceptLoopEvent(int event, Event *e); void cancel(); diff --git a/iocore/net/P_UnixNet.h b/iocore/net/P_UnixNet.h index a29cd7f4437..91ccb6fec0d 100644 --- a/iocore/net/P_UnixNet.h +++ b/iocore/net/P_UnixNet.h @@ -38,6 +38,9 @@ #define EVENTIO_ASYNC_SIGNAL 5 #if TS_USE_EPOLL +#ifndef EPOLLEXCLUSIVE +#define EPOLLEXCLUSIVE 0 +#endif #ifdef USE_EDGE_TRIGGER_EPOLL #define USE_EDGE_TRIGGER 1 #define EVENTIO_READ (EPOLLIN | EPOLLET) @@ -592,7 +595,7 @@ EventIO::start(EventLoop l, int afd, Continuation *c, int e) #if TS_USE_EPOLL struct epoll_event ev; memset(&ev, 0, sizeof(ev)); - ev.events = e; + ev.events = e | EPOLLEXCLUSIVE; ev.data.ptr = this; #ifndef USE_EDGE_TRIGGER events = e; diff --git a/iocore/net/UnixNet.cc b/iocore/net/UnixNet.cc index c2eded5e1cf..76900778a46 100644 --- a/iocore/net/UnixNet.cc +++ b/iocore/net/UnixNet.cc @@ -524,6 +524,8 @@ NetHandler::waitForActivity(ink_hrtime timeout) } } else if (epd->type == EVENTIO_ASYNC_SIGNAL) { net_signal_hook_callback(this->thread); + } else if (epd->type == EVENTIO_NETACCEPT) { + this->thread->schedule_imm(epd->data.c); } ev_next_event(pd, x); } diff --git a/iocore/net/UnixNetAccept.cc b/iocore/net/UnixNetAccept.cc index 3a452f62f14..9254d7f0e44 100644 --- a/iocore/net/UnixNetAccept.cc +++ b/iocore/net/UnixNetAccept.cc @@ -201,15 +201,17 @@ NetAccept::init_accept(EThread *t) t->schedule_every(this, period); } -void -NetAccept::init_accept_per_thread() +int +NetAccept::accept_per_thread(int event, void *ep) { - int i, n; + int listen_per_thread = 0; + REC_ReadConfigInteger(listen_per_thread, "proxy.config.exec_thread.listen"); - ink_assert(opt.etype >= 0); - - if (do_listen(NON_BLOCKING)) { - return; + if (listen_per_thread == 1) { + if (do_listen(NON_BLOCKING)) { + Fatal("[NetAccept::accept_per_thread]:error listenting on ports"); + return -1; + } } if (accept_fn == net_accept) { @@ -217,21 +219,38 @@ NetAccept::init_accept_per_thread() } else { SET_HANDLER((NetAcceptHandler)&NetAccept::acceptEvent); } + PollDescriptor *pd = get_PollDescriptor(this_ethread()); + if (this->ep.start(pd, this, EVENTIO_READ) < 0) { + Fatal("[NetAccept::accept_per_thread]:error starting EventIO"); + return -1; + } + return 0; +} - period = -HRTIME_MSECONDS(net_accept_period); - n = eventProcessor.thread_group[opt.etype]._count; +void +NetAccept::init_accept_per_thread() +{ + int i, n; + int listen_per_thread = 0; - for (i = 0; i < n; i++) { - NetAccept *a = (i < n - 1) ? clone() : this; - EThread *t = eventProcessor.thread_group[opt.etype]._thread[i]; - PollDescriptor *pd = get_PollDescriptor(t); + ink_assert(opt.etype >= 0); + REC_ReadConfigInteger(listen_per_thread, "proxy.config.exec_thread.listen"); - if (a->ep.start(pd, a, EVENTIO_READ) < 0) { - Warning("[NetAccept::init_accept_per_thread]:error starting EventIO"); + if (listen_per_thread == 0) { + if (do_listen(NON_BLOCKING)) { + Fatal("[NetAccept::accept_per_thread]:error listenting on ports"); + return; } + } + + SET_HANDLER((NetAcceptHandler)&NetAccept::accept_per_thread); + n = eventProcessor.thread_group[opt.etype]._count; - a->mutex = get_NetHandler(t)->mutex; - t->schedule_every(a, period); + for (i = 0; i < n; i++) { + NetAccept *a = (i < n - 1) ? clone() : this; + EThread *t = eventProcessor.thread_group[opt.etype]._thread[i]; + a->mutex = get_NetHandler(t)->mutex; + t->schedule_imm(a); } } @@ -401,16 +420,18 @@ NetAccept::acceptFastEvent(int event, void *ep) int loop = accept_till_done; do { - if (!opt.backdoor && check_net_throttle(ACCEPT)) { - ifd = NO_FD; - return EVENT_CONT; - } - socklen_t sz = sizeof(con.addr); int fd = socketManager.accept4(server.fd, &con.addr.sa, &sz, SOCK_NONBLOCK | SOCK_CLOEXEC); con.fd = fd; if (likely(fd >= 0)) { + // check for throttle + if (!opt.backdoor && check_net_throttle(ACCEPT)) { + // close the connection as we are in throttle state + con.close(); + NET_SUM_DYN_STAT(net_connections_throttled_in_stat, 1); + continue; + } Debug("iocore_net", "accepted a new socket: %d", fd); NET_SUM_GLOBAL_DYN_STAT(net_tcp_accept_stat, 1); if (opt.send_bufsize > 0) { @@ -440,6 +461,7 @@ NetAccept::acceptFastEvent(int event, void *ep) } // check return value from accept() if (res < 0) { + Debug("iocore_net", "received : %s", strerror(errno)); res = -errno; if (res == -EAGAIN || res == -ECONNABORTED #if defined(linux) @@ -458,9 +480,7 @@ NetAccept::acceptFastEvent(int event, void *ep) } vc = (UnixNetVConnection *)this->getNetProcessor()->allocate_vc(e->ethread); - if (!vc) { - goto Ldone; - } + ink_release_assert(vc); NET_SUM_GLOBAL_DYN_STAT(net_connections_currently_open_stat, 1); vc->id = net_next_connection_number(); diff --git a/iocore/net/UnixNetProcessor.cc b/iocore/net/UnixNetProcessor.cc index 11bf503187d..c8bc1e850f6 100644 --- a/iocore/net/UnixNetProcessor.cc +++ b/iocore/net/UnixNetProcessor.cc @@ -92,6 +92,7 @@ UnixNetProcessor::accept_internal(Continuation *cont, int fd, AcceptOptions cons ProxyMutex *mutex = this_ethread()->mutex.get(); int accept_threads = opt.accept_threads; // might be changed. IpEndpoint accept_ip; // local binding address. + int listen_per_thread = 0; NetAccept *na = createNetAccept(opt); na->id = ink_atomic_increment(&net_accept_number, 1); @@ -101,6 +102,10 @@ UnixNetProcessor::accept_internal(Continuation *cont, int fd, AcceptOptions cons if (opt.accept_threads < 0) { REC_ReadConfigInteger(accept_threads, "proxy.config.accept_threads"); } + REC_ReadConfigInteger(listen_per_thread, "proxy.config.exec_thread.listen"); + if (accept_threads > 0 && listen_per_thread > 0) { + Fatal("Please disable accept_threads or exec_threads.listen"); + } NET_INCREMENT_DYN_STAT(net_accepts_currently_open_stat); @@ -137,7 +142,7 @@ UnixNetProcessor::accept_internal(Continuation *cont, int fd, AcceptOptions cons na->action_->server = &na->server; if (opt.frequent_accept) { // true - if (accept_threads > 0) { + if (accept_threads > 0 && listen_per_thread == 0) { na->init_accept_loop(); } else { na->init_accept_per_thread(); diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc index 62547c08056..57883fbd0da 100644 --- a/mgmt/RecordsConfig.cc +++ b/mgmt/RecordsConfig.cc @@ -116,6 +116,8 @@ static const RecordElement RecordsConfig[] = , {RECT_CONFIG, "proxy.config.exec_thread.affinity", RECD_INT, "1", RECU_RESTART_TS, RR_NULL, RECC_INT, "[0-4]", RECA_READ_ONLY} , + {RECT_CONFIG, "proxy.config.exec_thread.listen", RECD_INT, "0", RECU_RESTART_TS, RR_NULL, RECC_INT, "[0-1]", RECA_READ_ONLY} + , {RECT_CONFIG, "proxy.config.accept_threads", RECD_INT, "1", RECU_RESTART_TS, RR_NULL, RECC_INT, "[0-" TS_STR(TS_MAX_NUMBER_EVENT_THREADS) "]", RECA_READ_ONLY} , {RECT_CONFIG, "proxy.config.task_threads", RECD_INT, "2", RECU_RESTART_TS, RR_NULL, RECC_INT, "[1-" TS_STR(TS_MAX_NUMBER_EVENT_THREADS) "]", RECA_READ_ONLY} diff --git a/src/traffic_manager/traffic_manager.cc b/src/traffic_manager/traffic_manager.cc index e6f7192bb46..e6f14e62e9a 100644 --- a/src/traffic_manager/traffic_manager.cc +++ b/src/traffic_manager/traffic_manager.cc @@ -557,6 +557,11 @@ main(int argc, const char **argv) } RecGetRecordInt("proxy.config.net.connections_throttle", &fds_throttle); + RecInt listen_per_thread = 0; + RecGetRecordInt("proxy.config.exec_thread.listen", &listen_per_thread); + if (listen_per_thread > 0) { // Turn off listening. Traffic server is going to listen on all the threads. + listen_off = true; + } set_process_limits(fds_throttle); // as root From 7bd0a535a58c90e7bc463987becfab9ed8db6f83 Mon Sep 17 00:00:00 2001 From: Vijay Mamidi Date: Sat, 26 Oct 2019 15:05:26 -0700 Subject: [PATCH 085/718] Fix the malformed threads table (cherry picked from commit 14b33b54dbc88d49f58fb41f9ad06bde1c36c964) --- doc/admin-guide/files/records.config.en.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst index f875519d90e..d52c0afb392 100644 --- a/doc/admin-guide/files/records.config.en.rst +++ b/doc/admin-guide/files/records.config.en.rst @@ -327,15 +327,15 @@ Thread Variables The number of accept threads. If disabled (``0``), then accepts will be done in each of the worker threads. - ============== ================== =================== - accept_threads exec_thread.listen Effect - ============== ================== =================== - ``0`` ``0`` All worker threads accept new connections and share listen fd. - ``1`` ``0`` New conections are accepted on a dedicated accept thread and distributed to worker threads in round robin fashion. - ``0`` ``1`` All worker threads listen on the same port using SO_REUSEPORT. - Each thread has its own listen and new connections are accepted on all the threads. - - By default, `proxy.config.accept_threads` is set to 1 and `proxy.config.exec_thread.listen` is set to 0. + ==================== ====================== ===================== + accept_threads exec_thread.listen Effect + ==================== ====================== ===================== + ``0`` ``0`` All worker threads accept new connections and share listen fd. + ``1`` ``0`` New conections are accepted on a dedicated accept thread and distributed to worker threads in round robin fashion. + ``0`` ``1`` All worker threads listen on the same port using SO_REUSEPORT. Each thread has its own listen fd and new connections are accepted on all the threads. + ==================== ====================== ===================== + + By default, `proxy.config.accept_threads` is set to 1 and `proxy.config.exec_thread.listen` is set to 0. .. ts:cv:: CONFIG proxy.config.thread.default.stacksize INT 1048576 Default thread stack size, in bytes, for all threads (default is 1 MB). From 58e2334ba7ab1d80868e89327c68952d66e9bcfa Mon Sep 17 00:00:00 2001 From: Masakazu Kitajo Date: Thu, 10 Oct 2019 13:23:13 -0700 Subject: [PATCH 086/718] clang-analyzer: Add a null check (cherry picked from commit cbc46ac4570ac034189d83de4e28c4b495545737) --- proxy/hdrs/MIME.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/proxy/hdrs/MIME.cc b/proxy/hdrs/MIME.cc index 9f9c57cee6e..71074012b72 100644 --- a/proxy/hdrs/MIME.cc +++ b/proxy/hdrs/MIME.cc @@ -485,6 +485,8 @@ mime_hdr_set_accelerators_and_presence_bits(MIMEHdrImpl *mh, MIMEField *field) return; } + ink_assert(mh); + mime_hdr_presence_set(mh, field->m_wks_idx); slot_id = hdrtoken_index_to_slotid(field->m_wks_idx); @@ -1570,6 +1572,7 @@ mime_hdr_field_attach(MIMEHdrImpl *mh, MIMEField *field, int check_for_dups, MIM void mime_hdr_field_detach(MIMEHdrImpl *mh, MIMEField *field, bool detach_all_dups) { + ink_assert(mh); MIMEField *next_dup = field->m_next_dup; // If this field is already detached, there's nothing to do. There must From 535badf8c4d0ca5161e5069cd652a90894c1790f Mon Sep 17 00:00:00 2001 From: bneradt Date: Wed, 23 Oct 2019 20:09:11 +0000 Subject: [PATCH 087/718] Adding connection close headers to regex_remap test. (cherry picked from commit f3942fe7828f1f26faf18c8b7ba716ebaf5a1f25) --- .../pluginTest/regex_remap/replay/yts-2819.replay.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/gold_tests/pluginTest/regex_remap/replay/yts-2819.replay.json b/tests/gold_tests/pluginTest/regex_remap/replay/yts-2819.replay.json index b9dfccfd8cb..5083a134e54 100644 --- a/tests/gold_tests/pluginTest/regex_remap/replay/yts-2819.replay.json +++ b/tests/gold_tests/pluginTest/regex_remap/replay/yts-2819.replay.json @@ -62,6 +62,10 @@ [ "Content-Length", "6128" + ], + [ + "Connection", + "close" ] ] } @@ -132,6 +136,10 @@ [ "Content-Length", "6128" + ], + [ + "Connection", + "close" ] ] } From 028085a1f9ea81e043cc38387486fcd12b651585 Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Tue, 29 Oct 2019 09:10:02 -0600 Subject: [PATCH 088/718] Warn about the %{PATH} -> %{CLIENT-URL:PATH} change --- doc/release-notes/upgrading.en.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/release-notes/upgrading.en.rst b/doc/release-notes/upgrading.en.rst index b70c93c0ed3..c1b47a4ebb0 100644 --- a/doc/release-notes/upgrading.en.rst +++ b/doc/release-notes/upgrading.en.rst @@ -55,3 +55,10 @@ The following incompatible changes to the configurations have been made in this Plugins ------- +The following plugins have changes that might require you to change configurations. + +header_rewrite +~~~~~~~~~~~~~~ + +* The `%{PATH}` directive is now removed, and instead you want to use `%{CLIENT-URL:PATH}`. This was +done to unify the behavior of these operators, rather than having this one-off directive. From a299a8f81dea1f32d665a5fbd288865a21c34210 Mon Sep 17 00:00:00 2001 From: Phil Sorber Date: Mon, 28 Oct 2019 18:08:20 -0600 Subject: [PATCH 089/718] Issue #6072: Make If-Range date compare to be exact match. (cherry picked from commit 4ca3839c32131c8f7fc36813a1e5cbf3656e9592) --- proxy/http/HttpTransactCache.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proxy/http/HttpTransactCache.cc b/proxy/http/HttpTransactCache.cc index 8ea46c37345..d732c5320dd 100644 --- a/proxy/http/HttpTransactCache.cc +++ b/proxy/http/HttpTransactCache.cc @@ -1381,13 +1381,13 @@ HttpTransactCache::match_response_to_request_conditionals(HTTPHdr *request, HTTP return HTTP_STATUS_RANGE_NOT_SATISFIABLE; } } - // this a Date, similar to If-Unmodified-Since + // this a Date, similar to If-Unmodified-Since but must be an exact match else { // lm_value is zero if Last-modified not exists ink_time_t lm_value = response->get_last_modified(); // condition fails if Last-modified not exists - if ((request->get_if_range_date() < lm_value) || (lm_value == 0)) { + if ((request->get_if_range_date() != lm_value) || (lm_value == 0)) { return HTTP_STATUS_RANGE_NOT_SATISFIABLE; } else { return response->status_get(); From 46bd7dbed1e179b246600cc98263d37fba50ee1f Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Tue, 29 Oct 2019 10:42:06 -0600 Subject: [PATCH 090/718] Solaris and cache v23 are unsupported for v9.0.0 --- doc/release-notes/upgrading.en.rst | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/doc/release-notes/upgrading.en.rst b/doc/release-notes/upgrading.en.rst index c1b47a4ebb0..d99092af691 100644 --- a/doc/release-notes/upgrading.en.rst +++ b/doc/release-notes/upgrading.en.rst @@ -48,11 +48,14 @@ get the remapped URL. As of v9.0.0, **all** plugins now receive the remapped URL a plugin that modifies the cache key, e.g. :ref:`admin-plugins-cachekey`, if it was evaluated first in a remap rule, the behavior (input) changes, and therefore, cache keys can change! +The old `v23` cache is no longer supported, which means caches created with ATS v2.x will no longer be +possible to load with ATS v9.0.0 or later. We feel that this is an unlikely scenario, but if you do +run into this, clearing the cache is required. + Configuration changes --------------------- The following incompatible changes to the configurations have been made in this version of ATS. - Plugins ------- The following plugins have changes that might require you to change configurations. @@ -62,3 +65,10 @@ header_rewrite * The `%{PATH}` directive is now removed, and instead you want to use `%{CLIENT-URL:PATH}`. This was done to unify the behavior of these operators, rather than having this one-off directive. + +Platform specific +----------------- + +Solaris is no longer a supported platform, but the code is still there. However, it's unlikely to work, +and unless someone takes on ownership of this Platform, it will be removed from the source in ATS v10.0.0. +For more details, see issue #5553. From 490273b1568c30b83ee8abaf2c49c20f20227568 Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Wed, 30 Oct 2019 15:04:37 -0600 Subject: [PATCH 091/718] Documented #3819, new connection management --- doc/release-notes/upgrading.en.rst | 42 ++++++++++++++++++++++++++---- doc/release-notes/whats-new.en.rst | 24 +++++++++++++++-- 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/doc/release-notes/upgrading.en.rst b/doc/release-notes/upgrading.en.rst index d99092af691..a35e2fffac3 100644 --- a/doc/release-notes/upgrading.en.rst +++ b/doc/release-notes/upgrading.en.rst @@ -25,6 +25,42 @@ Upgrading to ATS v9.x .. toctree:: :maxdepth: 1 +YAML +---- + +We are moving configurations over to YAML, and thus far, the following configurations are now fully +migrated over to YAML: + +* :file:`logging.yaml` (*was* `logging.config` or `logging.lua`) +* :file:`ip_allow.yaml` (*was* `ip_allow.config`) + +In addition, a new file for TLS handhsake negotiation configuration is added: + +* :file:`sni.yaml` (this was for a while named ssl_server_name.config in Github) + +New records.config settings +---------------------------- + +These are the changes that are most likely to cause problems during an upgrade. Take special care +making sure you have updated your configurations accordingly. + +Connection management +~~~~~~~~~~~~~~~~~~~~~ +The old settings for origin connection management included the following settings: + +* `proxy.config.http.origin_max_connections` +* `proxy.config.http.origin_max_connections_queue` +* `proxy.config.http.origin_min_keep_alive_connections` + +These are all gone, and replaced with the following set of configurations: + +* :ts:cv:`proxy.config.http.per_server.connection.max` (overridable) +* :ts:cv:`proxy.config.http.per_server.connection.match` (overridable) +* :ts:cv:`proxy.config.http.per_server.connection.alert_delay` +* :ts:cv:`proxy.config.http.per_server.connection.queue_size` +* :ts:cv:`proxy.config.http.per_server.connection.queue_delay` +* :ts:cv:`proxy.config.http.per_server.connection.min` + Deprecated or Removed Features ------------------------------ The following features, configurations and plugins are either removed or deprecated in this @@ -52,10 +88,6 @@ The old `v23` cache is no longer supported, which means caches created with ATS possible to load with ATS v9.0.0 or later. We feel that this is an unlikely scenario, but if you do run into this, clearing the cache is required. -Configuration changes ---------------------- -The following incompatible changes to the configurations have been made in this version of ATS. - Plugins ------- The following plugins have changes that might require you to change configurations. @@ -64,7 +96,7 @@ header_rewrite ~~~~~~~~~~~~~~ * The `%{PATH}` directive is now removed, and instead you want to use `%{CLIENT-URL:PATH}`. This was -done to unify the behavior of these operators, rather than having this one-off directive. + done to unify the behavior of these operators, rather than having this one-off directive. Platform specific ----------------- diff --git a/doc/release-notes/whats-new.en.rst b/doc/release-notes/whats-new.en.rst index f335fed5518..87027cf94ec 100644 --- a/doc/release-notes/whats-new.en.rst +++ b/doc/release-notes/whats-new.en.rst @@ -31,8 +31,28 @@ have participated in this development cycle. New Features ------------ -New or modifed Configurations ------------------------------ +Incompatible records.config settings +------------------------------------ + +These are the changes that are most likely to cause problems during an upgrade. Take special care +making sure you have updated your configurations accordingly. + +Connection management +~~~~~~~~~~~~~~~~~~~~~ +The old settings for origin connection management included the following settings: + +* `proxy.config.http.origin_max_connections` +* `proxy.config.http.origin_max_connections_queue` +* `proxy.config.http.origin_min_keep_alive_connections` + +These are all gone, and replaced with the following set of configurations: + +* :ts:cv:`proxy.config.http.per_server.connection.max` (overridable) +* :ts:cv:`proxy.config.http.per_server.connection.match` (overridable) +* :ts:cv:`proxy.config.http.per_server.connection.alert_delay` +* :ts:cv:`proxy.config.http.per_server.connection.queue_size` +* :ts:cv:`proxy.config.http.per_server.connection.queue_delay` +* :ts:cv:`proxy.config.http.per_server.connection.min` Logging and Metrics ------------------- From 6eefa698a60100f55c38d313e2b801cb71d3d173 Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Wed, 30 Oct 2019 16:23:36 -0600 Subject: [PATCH 092/718] Updated with more new features and incopmatible changes --- doc/release-notes/upgrading.en.rst | 27 ++++++++++++++++++++++++--- doc/release-notes/whats-new.en.rst | 18 ++++++++++++++++-- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/doc/release-notes/upgrading.en.rst b/doc/release-notes/upgrading.en.rst index a35e2fffac3..fb2505d5d4d 100644 --- a/doc/release-notes/upgrading.en.rst +++ b/doc/release-notes/upgrading.en.rst @@ -25,6 +25,14 @@ Upgrading to ATS v9.x .. toctree:: :maxdepth: 1 +Remapping +--------- + +One of the biggest changes in ATS v9.0.0 is that URL rewrites, as specified in a :file:`remap.config` +rule, now always happens **before** all plugins are executed. This can have significant impact on +behavior, since plugins might now see a different URL than they did in prior versions. In particular, +plugins modifying the cache key could have serious problems (see the section below for details). + YAML ---- @@ -61,6 +69,13 @@ These are all gone, and replaced with the following set of configurations: * :ts:cv:`proxy.config.http.per_server.connection.queue_delay` * :ts:cv:`proxy.config.http.per_server.connection.min` +Removed records.config settings +------------------------------- + +The following settings are simply gone, and have no purpose: + +* `proxy.config.config_dir` (see PROXY_CONFIG_CONFIG_DIR environment variable) + Deprecated or Removed Features ------------------------------ The following features, configurations and plugins are either removed or deprecated in this @@ -70,8 +85,16 @@ removed in the next major release of ATS. API Changes ----------- -The following APIs have changed, either in semanatics, interfaces, or both. +Our APIs are guaranteed to be compatible within major versions, but we do make changes +for each new major release. + +Removed APIs +~~~~~~~~~~~~ +* `TSHttpTxnRedirectRequest()` +Renamed or modified APIs +~~~~~~~~~~~~~~~~~~~~~~~~ +* `TSVConnSSLConnectionGet` is renamed to be :c:func:`TSVConnSslConnectionGet`. Cache ----- @@ -94,13 +117,11 @@ The following plugins have changes that might require you to change configuratio header_rewrite ~~~~~~~~~~~~~~ - * The `%{PATH}` directive is now removed, and instead you want to use `%{CLIENT-URL:PATH}`. This was done to unify the behavior of these operators, rather than having this one-off directive. Platform specific ----------------- - Solaris is no longer a supported platform, but the code is still there. However, it's unlikely to work, and unless someone takes on ownership of this Platform, it will be removed from the source in ATS v10.0.0. For more details, see issue #5553. diff --git a/doc/release-notes/whats-new.en.rst b/doc/release-notes/whats-new.en.rst index 87027cf94ec..c4fb1ebcbcf 100644 --- a/doc/release-notes/whats-new.en.rst +++ b/doc/release-notes/whats-new.en.rst @@ -21,7 +21,6 @@ What's New in ATS v9.x ======================= - This version of ATS includes over commits, from pull requests. A total of contributors have participated in this development cycle. @@ -31,9 +30,19 @@ have participated in this development cycle. New Features ------------ +This version of ATS has a number of new features (details below), but we're particularly excited about +the following features: + +* Experimental QUIC support (draft 23). +* TLS v1.3 0RTT support. + +PROXY protocol +~~~~~~~~~~~~~~ +ATS now supports the `PROXY https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt`_ protocol, +on the inbound side. The incoming PROXY data gets transformed into the `Forwarded` header. + Incompatible records.config settings ------------------------------------ - These are the changes that are most likely to cause problems during an upgrade. Take special care making sure you have updated your configurations accordingly. @@ -59,3 +68,8 @@ Logging and Metrics Plugins ------- + +xdebug +~~~~~~ + +* A new directive, `fwd=` to control the number of hops the header is forwarded for. From e3a1428ebef51e11825b152c05a6ea55bc2e1c57 Mon Sep 17 00:00:00 2001 From: Gancho Tenev Date: Tue, 29 Oct 2019 21:27:46 -0700 Subject: [PATCH 093/718] doc + unittest TSRemap(Init|NewInstance) failures Documented configuration reload behavior when `TSRemapIniti()` and `TSRemapNewInstance()` return `TS_ERROR` aborting the reload. Verified that `TSRemapInit()` and `TSRemapNewInstance()` actually abort the configuration reload if any of them return `TS_ERROR`. Discovered and fixed a discrepency with not unloading the DSO if the initial `TSRemapInit()` call returns `TS_ERROR`. Added unit tests to validate the DSO actuall unloading. (cherry picked from commit 63e048a7546bb87537498265fd7ccf1f5700d396) --- .../plugins/remap-plugins.en.rst | 6 ++ proxy/http/remap/Makefile.am | 13 +++- proxy/http/remap/PluginFactory.cc | 6 +- .../http/remap/unit-tests/plugin_init_fail.cc | 58 ++++++++++++++++ .../remap/unit-tests/plugin_instinit_fail.cc | 69 +++++++++++++++++++ .../remap/unit-tests/test_PluginFactory.cc | 52 +++++++++++++- 6 files changed, 198 insertions(+), 6 deletions(-) create mode 100644 proxy/http/remap/unit-tests/plugin_init_fail.cc create mode 100644 proxy/http/remap/unit-tests/plugin_instinit_fail.cc diff --git a/doc/developer-guide/plugins/remap-plugins.en.rst b/doc/developer-guide/plugins/remap-plugins.en.rst index d43616955f1..244651000b8 100644 --- a/doc/developer-guide/plugins/remap-plugins.en.rst +++ b/doc/developer-guide/plugins/remap-plugins.en.rst @@ -50,6 +50,9 @@ should be placed in :arg:`errbuff`, taking note of the maximum size of the buffe :arg:`errbuff_size`. The message is checked if the function returns a value other than :macro:`TS_SUCCESS`. +If :func:`TSRemapInit` returns :macro:`TS_ERROR` then the remap configuration loading +is aborted immediatelly. + This function should perform any plugin global initialization, such as setting up static data tables. It only be called immediately after the dynamic library is loaded from disk. @@ -88,6 +91,9 @@ If there is an error then the callback should return :macro:`TS_ERROR` and fill :arg:`errbuff` with a C-string describing the error. Otherwise the function must return :macro:`TS_SUCCESS`. +If :func:`TSRemapNewInstance` returns :macro:`TS_ERROR` then the remap configuration loading +is aborted immediatelly. + Configuration reload notifications ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/proxy/http/remap/Makefile.am b/proxy/http/remap/Makefile.am index 8275166371d..c1874c9145b 100644 --- a/proxy/http/remap/Makefile.am +++ b/proxy/http/remap/Makefile.am @@ -82,7 +82,10 @@ test_PluginDso_SOURCES = \ test_PluginFactory_CPPFLAGS = $(AM_CPPFLAGS) -I$(abs_top_srcdir)/tests/include -DPLUGIN_DSO_TESTS test_PluginFactory_LIBTOOLFLAGS = --preserve-dup-deps -EXTRA_test_PluginFactory_DEPENDENCIES = unit-tests/plugin_v1.la +EXTRA_test_PluginFactory_DEPENDENCIES = \ + unit-tests/plugin_v1.la \ + unit-tests/plugin_init_fail.la + unit-tests/plugin_instinit_fail.la test_PluginFactory_LDADD = $(COMMON_PLUGINDSO_LDADDS) test_PluginFactory_LDFLAGS = $(AM_LDFLAGS) test_PluginFactory_SOURCES = \ @@ -121,6 +124,8 @@ DSO_LDFLAGS = \ pkglib_LTLIBRARIES = \ unit-tests/plugin_v1.la \ unit-tests/plugin_v2.la \ + unit-tests/plugin_init_fail.la \ + unit-tests/plugin_instinit_fail.la \ unit-tests/plugin_required_cb.la \ unit-tests/plugin_missing_deleteinstance.la \ unit-tests/plugin_missing_doremap.la \ @@ -133,6 +138,12 @@ unit_tests_plugin_v1_la_CPPFLAGS = -DPLUGINDSOVER=1 $(AM_CPPFLAGS) unit_tests_plugin_v2_la_SOURCES = unit-tests/plugin_misc_cb.cc unit_tests_plugin_v2_la_LDFLAGS = $(DSO_LDFLAGS) unit_tests_plugin_v2_la_CPPFLAGS = -DPLUGINDSOVER=2 $(AM_CPPFLAGS) +unit_tests_plugin_init_fail_la_SOURCES = unit-tests/plugin_init_fail.cc +unit_tests_plugin_init_fail_la_LDFLAGS = $(DSO_LDFLAGS) +unit_tests_plugin_init_fail_la_CPPFLAGS = $(AM_CPPFLAGS) +unit_tests_plugin_instinit_fail_la_SOURCES = unit-tests/plugin_instinit_fail.cc +unit_tests_plugin_instinit_fail_la_LDFLAGS = $(DSO_LDFLAGS) +unit_tests_plugin_instinit_fail_la_CPPFLAGS = $(AM_CPPFLAGS) unit_tests_plugin_required_cb_la_SOURCES = unit-tests/plugin_required_cb.cc unit_tests_plugin_required_cb_la_LDFLAGS = $(DSO_LDFLAGS) unit_tests_plugin_required_cb_la_CPPFLAGS = -DPLUGINDSOVER=1 $(AM_CPPFLAGS) diff --git a/proxy/http/remap/PluginFactory.cc b/proxy/http/remap/PluginFactory.cc index 8fc55afda63..b55875b92d1 100644 --- a/proxy/http/remap/PluginFactory.cc +++ b/proxy/http/remap/PluginFactory.cc @@ -171,13 +171,15 @@ PluginFactory::getRemapPlugin(const fs::path &configPath, int argc, char **argv, plugin = new RemapPluginInfo(configPath, effectivePath, runtimePath); if (nullptr != plugin) { if (plugin->load(error)) { - PluginDso::loadedPlugins()->add(plugin); - if (plugin->init(error)) { + PluginDso::loadedPlugins()->add(plugin); inst = RemapPluginInst::init(plugin, argc, argv, error); if (nullptr != inst) { _instList.append(inst); } + } else { + plugin->unload(error); + delete plugin; } if (_preventiveCleaning) { diff --git a/proxy/http/remap/unit-tests/plugin_init_fail.cc b/proxy/http/remap/unit-tests/plugin_init_fail.cc new file mode 100644 index 00000000000..151382f7009 --- /dev/null +++ b/proxy/http/remap/unit-tests/plugin_init_fail.cc @@ -0,0 +1,58 @@ +/** @file + + A test plugin for testing Plugin's Dynamic Shared Objects (DSO) + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + @section details Details + + Implements code necessary for Reverse Proxy which mostly consists of + general purpose hostname substitution in URLs. + + */ + +#include "plugin_testing_common.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "ts/ts.h" +#include "ts/remap.h" + +TSReturnCode +TSRemapInit(TSRemapInterface *api_info, char *errbuf, int errbuf_size) +{ + return TS_ERROR; +} + +void +TSRemapDone(void) +{ +} + +TSRemapStatus +TSRemapDoRemap(void *ih, TSHttpTxn rh, TSRemapRequestInfo *rri) +{ + return TSREMAP_NO_REMAP; +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ diff --git a/proxy/http/remap/unit-tests/plugin_instinit_fail.cc b/proxy/http/remap/unit-tests/plugin_instinit_fail.cc new file mode 100644 index 00000000000..41bf6b1bbc9 --- /dev/null +++ b/proxy/http/remap/unit-tests/plugin_instinit_fail.cc @@ -0,0 +1,69 @@ +/** @file + + A test plugin for testing Plugin's Dynamic Shared Objects (DSO) + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + @section details Details + + Implements code necessary for Reverse Proxy which mostly consists of + general purpose hostname substitution in URLs. + + */ + +#include "plugin_testing_common.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "ts/ts.h" +#include "ts/remap.h" + +TSReturnCode +TSRemapInit(TSRemapInterface *api_info, char *errbuf, int errbuf_size) +{ + return TS_SUCCESS; +} + +void +TSRemapDone(void) +{ +} + +TSReturnCode +TSRemapNewInstance(int argc, char *argv[], void **ih, char *errbuf, int errbuf_size) +{ + return TS_ERROR; +} + +void +TSRemapDeleteInstance(void *) +{ +} + +TSRemapStatus +TSRemapDoRemap(void *ih, TSHttpTxn rh, TSRemapRequestInfo *rri) +{ + return TSREMAP_NO_REMAP; +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ diff --git a/proxy/http/remap/unit-tests/test_PluginFactory.cc b/proxy/http/remap/unit-tests/test_PluginFactory.cc index d42f0588cc8..de80397c504 100644 --- a/proxy/http/remap/unit-tests/test_PluginFactory.cc +++ b/proxy/http/remap/unit-tests/test_PluginFactory.cc @@ -190,7 +190,11 @@ SCENARIO("loading plugins", "[plugin][core]") PluginFactoryUnitTest *factory = getFactory(tempComponent); RemapPluginInst *plugin = factory->getRemapPlugin(configPath, 0, nullptr, error); - THEN("expect it to successfully load") { validateSuccessfulConfigPathTest(plugin, error, effectivePath, runtimePath); } + THEN("expect it to successfully load") + { + validateSuccessfulConfigPathTest(plugin, error, effectivePath, runtimePath); + CHECK(nullptr != PluginDso::loadedPlugins()->findByEffectivePath(effectivePath)); + } teardownConfigPathTest(factory); } @@ -204,7 +208,11 @@ SCENARIO("loading plugins", "[plugin][core]") PluginFactoryUnitTest *factory = getFactory(tempComponent); RemapPluginInst *plugin = factory->getRemapPlugin(configPath, 0, nullptr, error); - THEN("expect it to successfully load") { validateSuccessfulConfigPathTest(plugin, error, effectivePath, runtimePath); } + THEN("expect it to successfully load") + { + validateSuccessfulConfigPathTest(plugin, error, effectivePath, runtimePath); + CHECK(nullptr != PluginDso::loadedPlugins()->findByEffectivePath(effectivePath)); + } teardownConfigPathTest(factory); } @@ -218,7 +226,11 @@ SCENARIO("loading plugins", "[plugin][core]") PluginFactoryUnitTest *factory = getFactory(tempComponent); RemapPluginInst *plugin = factory->getRemapPlugin(configPath, 0, nullptr, error); - THEN("expect it to successfully load") { validateSuccessfulConfigPathTest(plugin, error, effectivePath, runtimePath); } + THEN("expect it to successfully load") + { + validateSuccessfulConfigPathTest(plugin, error, effectivePath, runtimePath); + CHECK(nullptr != PluginDso::loadedPlugins()->findByEffectivePath(effectivePath)); + } teardownConfigPathTest(factory); } @@ -267,6 +279,40 @@ SCENARIO("loading plugins", "[plugin][core]") teardownConfigPathTest(factory); } + + WHEN("plugin initialization fails") + { + fs::path configPath = fs::path("plugin_init_fail.so"); + fs::path buildPath = pluginBuildDir / configPath; + setupConfigPathTest(configPath, buildPath, tempComponent, effectivePath, runtimePath); + PluginFactoryUnitTest *factory = getFactory(tempComponent); + RemapPluginInst *plugin = factory->getRemapPlugin(configPath, 0, nullptr, error); + + THEN("expect it to unload the plugin dso") + { + CHECK(nullptr == plugin); + CHECK(nullptr == PluginDso::loadedPlugins()->findByEffectivePath(effectivePath)); + } + + teardownConfigPathTest(factory); + } + + WHEN("instance initialization fails") + { + fs::path configPath = fs::path("plugin_instinit_fail.so"); + fs::path buildPath = pluginBuildDir / configPath; + setupConfigPathTest(configPath, buildPath, tempComponent, effectivePath, runtimePath); + PluginFactoryUnitTest *factory = getFactory(tempComponent); + RemapPluginInst *plugin = factory->getRemapPlugin(configPath, 0, nullptr, error); + + THEN("expect it to unload the plugin dso") + { + CHECK(nullptr == plugin); + CHECK(nullptr == PluginDso::loadedPlugins()->findByEffectivePath(effectivePath)); + } + + teardownConfigPathTest(factory); + } } } From 14b1c6805583b5ad6039c3f046f3d19996b2eff3 Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Wed, 30 Oct 2019 17:15:55 -0600 Subject: [PATCH 094/718] Fix the external link --- doc/release-notes/whats-new.en.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes/whats-new.en.rst b/doc/release-notes/whats-new.en.rst index c4fb1ebcbcf..53e4841fea9 100644 --- a/doc/release-notes/whats-new.en.rst +++ b/doc/release-notes/whats-new.en.rst @@ -38,7 +38,7 @@ the following features: PROXY protocol ~~~~~~~~~~~~~~ -ATS now supports the `PROXY https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt`_ protocol, +ATS now supports the `PROXY `_ protocol, on the inbound side. The incoming PROXY data gets transformed into the `Forwarded` header. Incompatible records.config settings From 5a3f00876f993410a6308e8900582bd0fcbd886e Mon Sep 17 00:00:00 2001 From: bneradt Date: Thu, 31 Oct 2019 22:51:19 +0000 Subject: [PATCH 095/718] Minor fixes. (cherry picked from commit 35f31c62b1cdc0530a53943db9435db2f8d4ba18) --- doc/admin-guide/plugins/traffic_dump.en.rst | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/doc/admin-guide/plugins/traffic_dump.en.rst b/doc/admin-guide/plugins/traffic_dump.en.rst index 2d012f11855..45c7d51e669 100644 --- a/doc/admin-guide/plugins/traffic_dump.en.rst +++ b/doc/admin-guide/plugins/traffic_dump.en.rst @@ -33,10 +33,10 @@ Plugin Configuration ==================== .. program:: traffic_dump.so -* ``Traffic Dump`` is a global plugin and is configured via :file:`plugin.config`. +``Traffic Dump`` is a global plugin and is configured via :file:`plugin.config`. .. option:: --logdir - (`required`) - specifies the directory for writing all dump files. If path is relative, it is relative to the Traffic Server directory. The plugin will use first three characters of client ip to create subdirs in an attempt to spread dumps evenly and avoid too many files in a single directory. + (`required`) - specifies the directory for writing all dump files. If path is relative, it is relative to the Traffic Server directory. The plugin will use first three characters of the client's IP to create subdirs in an attempt to spread dumps evenly and avoid too many files in a single directory. .. option:: --sample @@ -44,20 +44,21 @@ Plugin Configuration .. option:: --limit - (`required`) - specifies the max disk usage N bytes(approximate). Traffic Dump will stop capturing new sessions once disk usage exceeds this limit. + (`required`) - specifies the max disk usage N bytes (approximate). Traffic Dump will stop capturing new sessions once disk usage exceeds this limit. -* ``traffic_ctl`` command. - ``traffic_ctl plugin msg traffic_dump.sample N`` - changes the sampling ratio N as mentioned above. - ``traffic_ctl plugin msg traffic_dump.reset`` - resets the disk usage counter. - ``traffic_ctl plugin msg traffic_dump.limit N`` - changes the max disk usage. +``traffic_ctl`` + * ``traffic_ctl plugin msg traffic_dump.sample N`` - changes the sampling ratio N as mentioned above. + * ``traffic_ctl plugin msg traffic_dump.reset`` - resets the disk usage counter. + * ``traffic_ctl plugin msg traffic_dump.limit N`` - changes the max disk usage to N bytes as mentioned above. Replay Format ============= This format contains traffic data including: + * Each session and transactions in the session. * Timestamps. * The four headers (ua request, proxy request, origin server response, proxy response). * The protocol stack for the user agent. * The transaction count for the outbound session. * The content block sizes. -* See schema here: :ts:git:`tests/tools/traffic-replay/replay_schema.json` +* See schema here: :ts:git:`tests/tools/lib/replay_schema.json` From 1b62835bb55dd95b414c6d7d3a41ca21b043b191 Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Thu, 31 Oct 2019 11:43:11 -0600 Subject: [PATCH 096/718] Removes proxy.config.cache.storage_filename (cherry picked from commit 12d0b56bdc6dfe4c561baa85cf8f4ecf3028d141) --- include/tscore/Filenames.h | 26 +++++++++++++++++++++++ iocore/cache/Cache.cc | 3 ++- iocore/cache/Store.cc | 14 ++++++------ lib/perl/lib/Apache/TS/AdminClient.pm | 1 - mgmt/RecordsConfig.cc | 2 -- src/traffic_layout/info.cc | 3 ++- src/traffic_manager/AddConfigFilesHere.cc | 3 ++- src/tscore/Filenames.cc | 24 +++++++++++++++++++++ src/tscore/Makefile.am | 1 + 9 files changed, 64 insertions(+), 13 deletions(-) create mode 100644 include/tscore/Filenames.h create mode 100644 src/tscore/Filenames.cc diff --git a/include/tscore/Filenames.h b/include/tscore/Filenames.h new file mode 100644 index 00000000000..67065fb968e --- /dev/null +++ b/include/tscore/Filenames.h @@ -0,0 +1,26 @@ +/** @file + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#pragma once + +/////////////////////////////////////////////////////////////////// +// Configuration file names +extern const char *STORAGE_CONF_FILENAME; diff --git a/iocore/cache/Cache.cc b/iocore/cache/Cache.cc index ee7effe417b..83b33b54de7 100644 --- a/iocore/cache/Cache.cc +++ b/iocore/cache/Cache.cc @@ -28,6 +28,7 @@ #include "StatPages.h" #include "tscore/I_Layout.h" +#include "tscore/Filenames.h" #include "HttpTransactCache.h" #include "HttpSM.h" @@ -3252,7 +3253,7 @@ ink_cache_init(ts::ModuleVersion v) Result result = theCacheStore.read_config(); if (result.failed()) { - Fatal("Failed to read cache storage configuration: %s", result.message()); + Fatal("Failed to read cache configuration %s: %s", STORAGE_CONF_FILENAME, result.message()); } } diff --git a/iocore/cache/Store.cc b/iocore/cache/Store.cc index c5f009faea7..119206f91ad 100644 --- a/iocore/cache/Store.cc +++ b/iocore/cache/Store.cc @@ -24,6 +24,7 @@ #include "tscore/ink_platform.h" #include "P_Cache.h" #include "tscore/I_Layout.h" +#include "tscore/Filenames.h" #include "tscore/ink_file.h" #include "tscore/Tokenizer.h" #include "tscore/SimpleTokenizer.h" @@ -36,7 +37,6 @@ // // Store // - const char Store::VOLUME_KEY[] = "volume"; const char Store::HASH_BASE_STRING_KEY[] = "id"; @@ -325,13 +325,13 @@ Store::read_config() Span *sd = nullptr, *cur = nullptr; Span *ns; ats_scoped_fd fd; - ats_scoped_str storage_path(RecConfigReadConfigPath("proxy.config.cache.storage_filename", "storage.config")); + ats_scoped_str storage_path(RecConfigReadConfigPath(nullptr, STORAGE_CONF_FILENAME)); - Note("storage.config loading ..."); + Note("%s loading ...", STORAGE_CONF_FILENAME); Debug("cache_init", "Store::read_config, fd = -1, \"%s\"", (const char *)storage_path); fd = ::open(storage_path, O_RDONLY); if (fd < 0) { - Error("storage.config failed to load"); + Error("%s failed to load", STORAGE_CONF_FILENAME); return Result::failure("open %s: %s", (const char *)storage_path, strerror(errno)); } @@ -372,7 +372,7 @@ Store::read_config() const char *end; if ((size = ink_atoi64(e, &end)) <= 0 || *end != '\0') { delete sd; - Error("storage.config failed to load"); + Error("%s failed to load", STORAGE_CONF_FILENAME); return Result::failure("failed to parse size '%s'", e); } } else if (0 == strncasecmp(HASH_BASE_STRING_KEY, e, sizeof(HASH_BASE_STRING_KEY) - 1)) { @@ -390,7 +390,7 @@ Store::read_config() } if (!*e || !ParseRules::is_digit(*e) || 0 >= (volume_num = ink_atoi(e))) { delete sd; - Error("storage.config failed to load"); + Error("%s failed to load", STORAGE_CONF_FILENAME); return Result::failure("failed to parse volume number '%s'", e); } } @@ -442,7 +442,7 @@ Store::read_config() sd = nullptr; // these are all used. sort(); - Note("storage.config finished loading"); + Note("%s finished loading", STORAGE_CONF_FILENAME); return Result::ok(); } diff --git a/lib/perl/lib/Apache/TS/AdminClient.pm b/lib/perl/lib/Apache/TS/AdminClient.pm index a8023f9f883..dbccd3eeaec 100644 --- a/lib/perl/lib/Apache/TS/AdminClient.pm +++ b/lib/perl/lib/Apache/TS/AdminClient.pm @@ -349,7 +349,6 @@ The Apache Traffic Server Administration Manual will explain what these strings proxy.config.cache.ram_cache_cutoff proxy.config.cache.ram_cache.size proxy.config.cache.select_alternate - proxy.config.cache.storage_filename proxy.config.cache.threads_per_disk proxy.config.cache.mutex_retry_delay proxy.config.cop.core_signal diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc index 57883fbd0da..8e7ec9ddfbf 100644 --- a/mgmt/RecordsConfig.cc +++ b/mgmt/RecordsConfig.cc @@ -796,8 +796,6 @@ static const RecordElement RecordsConfig[] = //# Cache //# //############################################################################## - {RECT_CONFIG, "proxy.config.cache.storage_filename", RECD_STRING, "storage.config", RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} - , {RECT_CONFIG, "proxy.config.cache.control.filename", RECD_STRING, "cache.config", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , {RECT_CONFIG, "proxy.config.cache.ip_allow.filename", RECD_STRING, "ip_allow.yaml", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} diff --git a/src/traffic_layout/info.cc b/src/traffic_layout/info.cc index 6b521eaf94d..51aba61a9ac 100644 --- a/src/traffic_layout/info.cc +++ b/src/traffic_layout/info.cc @@ -23,6 +23,7 @@ #include #include "tscore/I_Layout.h" +#include "tscore/Filenames.h" #include "tscore/BufferWriter.h" #include "records/I_RecProcess.h" #include "RecordsConfig.h" @@ -158,7 +159,7 @@ produce_layout(bool json) print_var("remap.config", RecConfigReadConfigPath("proxy.config.url_remap.filename"), json); print_var("plugin.config", RecConfigReadConfigPath(nullptr, "plugin.config"), json); print_var("ssl_multicert.config", RecConfigReadConfigPath("proxy.config.ssl.server.multicert.filename"), json); - print_var("storage.config", RecConfigReadConfigPath("proxy.config.cache.storage_filename"), json); + print_var(STORAGE_CONF_FILENAME, RecConfigReadConfigPath(nullptr, STORAGE_CONF_FILENAME), json); print_var("hosting.config", RecConfigReadConfigPath("proxy.config.cache.hosting_filename"), json); print_var("volume.config", RecConfigReadConfigPath("proxy.config.cache.volume_filename"), json); print_var("ip_allow.yaml", RecConfigReadConfigPath("proxy.config.cache.ip_allow.filename"), json, true); diff --git a/src/traffic_manager/AddConfigFilesHere.cc b/src/traffic_manager/AddConfigFilesHere.cc index 5f894ccadb2..de33eb6aad6 100644 --- a/src/traffic_manager/AddConfigFilesHere.cc +++ b/src/traffic_manager/AddConfigFilesHere.cc @@ -22,6 +22,7 @@ */ #include "tscore/ink_platform.h" +#include "tscore/Filenames.h" #include "MgmtUtils.h" #include "tscore/Diags.h" #include "FileManager.h" @@ -73,7 +74,7 @@ initializeRegistry() } registerFile("proxy.config.log.config.filename", "logging.yaml"); - registerFile("", "storage.config"); + registerFile("", STORAGE_CONF_FILENAME); registerFile("proxy.config.socks.socks_config_file", "socks.config"); registerFile("records.config", "records.config"); registerFile("proxy.config.cache.control.filename", "cache.config"); diff --git a/src/tscore/Filenames.cc b/src/tscore/Filenames.cc new file mode 100644 index 00000000000..cd296c8e108 --- /dev/null +++ b/src/tscore/Filenames.cc @@ -0,0 +1,24 @@ +/** @file + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +/////////////////////////////////////////////////////////////////// +// Configuration file names +const char *STORAGE_CONF_FILENAME = "storage.config"; diff --git a/src/tscore/Makefile.am b/src/tscore/Makefile.am index 755df4ad664..11b7285ce6a 100644 --- a/src/tscore/Makefile.am +++ b/src/tscore/Makefile.am @@ -60,6 +60,7 @@ libtscore_la_SOURCES = \ EventNotify.cc \ Extendible.cc \ fastlz.c \ + Filenames.cc \ Hash.cc \ HashFNV.cc \ HashMD5.cc \ From e993a1897d951a36335d7264073a5159b6478b36 Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Tue, 29 Oct 2019 08:58:39 -0600 Subject: [PATCH 097/718] Add an appropriate warning where behavior has changed (cherry picked from commit 63ddd24508aba6c501233f1ce7559a15fb73ee46) --- doc/admin-guide/plugins/header_rewrite.en.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/admin-guide/plugins/header_rewrite.en.rst b/doc/admin-guide/plugins/header_rewrite.en.rst index e5951e7f56a..217940acd04 100644 --- a/doc/admin-guide/plugins/header_rewrite.en.rst +++ b/doc/admin-guide/plugins/header_rewrite.en.rst @@ -822,7 +822,9 @@ Part Description HOST Full hostname. PATH URL substring beginning with (but not including) the first ``/`` after - the hostname up to, but not including, the query string. + the hostname up to, but not including, the query string. **Note**: previous + versions of ATS had a `%{PATH}` directive, this will no longer work. Instead, + you want to use `%{CLIENT-URL:PATH}`. PORT Port number. From 6b44697625296da6cb98889b949fc307a99dd3ed Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Fri, 1 Nov 2019 14:45:52 +0900 Subject: [PATCH 098/718] Fix null pointer dereference reported by clang-analyzer (cherry picked from commit 33a5ebe303361076ef636d1590faf31c7f44cc57) --- proxy/http/HttpTunnel.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/proxy/http/HttpTunnel.cc b/proxy/http/HttpTunnel.cc index 882e1e5ca1c..97e3cc9641c 100644 --- a/proxy/http/HttpTunnel.cc +++ b/proxy/http/HttpTunnel.cc @@ -1182,8 +1182,12 @@ HttpTunnel::producer_handler(int event, HttpTunnelProducer *p) case VC_EVENT_INACTIVITY_TIMEOUT: case HTTP_TUNNEL_EVENT_CONSUMER_DETACH: if (p->alive) { - p->alive = false; - p->bytes_read = p->read_vio->ndone; + p->alive = false; + if (p->read_vio) { + p->bytes_read = p->read_vio->ndone; + } else { + p->bytes_read = 0; + } // Clear any outstanding reads so they don't // collide with future tunnel IO's p->vc->do_io_read(nullptr, 0, nullptr); From 57b9c3c1d4ba70e73a89f4b92de4c6d34d6c6283 Mon Sep 17 00:00:00 2001 From: Randall Meyer Date: Tue, 29 Oct 2019 10:50:10 -0700 Subject: [PATCH 099/718] For remap_stats, removes configure time dependency on search.h The plugin no longer depends on this header since moving to C++ (cherry picked from commit 4f569586f9889c91eab3f2f3fcd81bf0cab2549e) Conflicts: plugins/Makefile.am --- configure.ac | 2 -- plugins/Makefile.am | 5 +---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 112afa40459..68c348796ec 100644 --- a/configure.ac +++ b/configure.ac @@ -2080,8 +2080,6 @@ AS_IF([test "x$enable_experimental_plugins" = "xyes"], AC_CHECK_FUNCS([hcreate_r hsearch_r]) ]) ]) -AM_CONDITIONAL([BUILD_REMAP_STATS_PLUGIN], - [ test "x$enable_experimental_plugins" = "xyes" -a "x$ac_cv_header_search_h" = "xyes" -a "x$ac_cv_type_struct_hsearch_data" = "xyes" -a "x$ac_cv_func_hcreate_r" = "xyes" -a "x$ac_cv_func_hsearch_r" = "xyes" ]) AC_ARG_WITH([default-stack-size], [AS_HELP_STRING([--with-default-stack-size],[specify the default stack size in bytes [default=1048576]])], diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 9818f9c00b3..5af6494495f 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -71,6 +71,7 @@ include experimental/memcache/Makefile.inc include experimental/metalink/Makefile.inc include experimental/money_trace/Makefile.inc include experimental/mp4/Makefile.inc +include experimental/remap_stats/Makefile.inc include experimental/server_push_preload/Makefile.inc include experimental/slice/Makefile.inc include experimental/sslheaders/Makefile.inc @@ -92,10 +93,6 @@ if BUILD_SSL_SESSION_REUSE_PLUGIN include experimental/ssl_session_reuse/Makefile.inc endif -if BUILD_REMAP_STATS_PLUGIN -include experimental/remap_stats/Makefile.inc -endif - if HAS_KYOTOCABINET include experimental/cache_key_genid/Makefile.inc endif From 540bb1d175b6a11c8a9201f7fc729c4d2faaa8cc Mon Sep 17 00:00:00 2001 From: Gancho Tenev Date: Thu, 31 Oct 2019 14:06:22 -0700 Subject: [PATCH 100/718] Docs: cachekey: fixed non-ascii table characters (cherry picked from commit 1e6760e33290a908cbcbfee60398ba8335f87792) --- doc/admin-guide/plugins/cachekey.en.rst | 34 ++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/doc/admin-guide/plugins/cachekey.en.rst b/doc/admin-guide/plugins/cachekey.en.rst index 5b6ba4cdd18..ff8e4352750 100644 --- a/doc/admin-guide/plugins/cachekey.en.rst +++ b/doc/admin-guide/plugins/cachekey.en.rst @@ -83,21 +83,21 @@ Cache key structure and related plugin parameters :: - Optional components | ┌─────────────────┬────────────── ───┬──────────────────────┐ - (included in this order) | │ --static-prefix | --capture-prefix │ --capture-prefix-uri │ + Optional components | ┌─────────────────┬──────────────────┬──────────────────────┐ + (included in this order) | │ --static-prefix │ --capture-prefix │ --capture-prefix-uri │ | ├─────────────────┴──────────────────┴──────────────────────┤ - Default values if no | │ /host/port or scheme://host:port (see the table below) | + Default values if no | │ /host/port or scheme://host:port (see the table below) │ optional components | └───────────────────────────────────────────────────────────┘ configured | ┌────────────────────┬─────────────────────────┬──────────────────────┐ - │ --canonical-prefix | default value if no │ input used for │ - │ | prefix parameters used │ --capture-prefix │ - ├────────────────────┴─────────────────────────┴──────────────────────┤ - │ false | /host/port | host:port | - ├────────────────────┴─────────────────────────┴──────────────────────┤ - │ true | scheme://host:port | scheme://host:port | - └──────────────────────────────────────────────┴──────────────────────┘ + │ --canonical-prefix │ default value if no │ input used for │ + │ │ prefix parameters used │ --capture-prefix │ + ├────────────────────┼─────────────────────────┼──────────────────────┤ + │ false │ /host/port │ host:port │ + ├────────────────────┼─────────────────────────┼──────────────────────┤ + │ true │ scheme://host:port │ scheme://host:port │ + └────────────────────┴─────────────────────────┴──────────────────────┘ * ``--static-prefix=`` (default: empty string) - if specified and not an empty string the ```` will be added to the `cache key`. @@ -114,9 +114,9 @@ Cache key structure and related plugin parameters :: Optional components | ┌────────────┬──────────────┐ - (included in this order) | │ --ua-class | --ua-capture │ + (included in this order) | │ --ua-class │ --ua-capture │ | ├────────────┴──────────────┤ - Default values if no | │ (empty) | + Default values if no | │ (empty) │ optional components | └───────────────────────────┘ configured | @@ -135,8 +135,8 @@ Cache key structure and related plugin parameters Optional components | ┌───────────────────┬───────────────────┐ | │ --include-headers │ --capture-header │ - | ├───────────────────────────────────────┤ - Default values if no | │ (empty) | (empty) | + | ├───────────────────┼───────────────────┤ + Default values if no | │ (empty) │ (empty) │ optional components | └───────────────────┴───────────────────┘ configured | @@ -152,7 +152,7 @@ Cache key structure and related plugin parameters Optional components | ┌───────────────────┐ | │ --include-cookies │ | ├───────────────────┤ - Default values if no | │ (empty) | + Default values if no | │ (empty) │ optional components | └───────────────────┘ configured | @@ -164,9 +164,9 @@ Cache key structure and related plugin parameters :: Optional components | ┌────────────────────┬────────────────┐ - (included in this order) | │ --capture-path-uri | --capture-path │ + (included in this order) | │ --capture-path-uri │ --capture-path │ | ├────────────────────┴────────────────┤ - Default values if no | │ URI path | + Default values if no | │ URI path │ optional components | └─────────────────────────────────────┘ configured | From 17acf3121614142a01d69d45b035bf1c0313be36 Mon Sep 17 00:00:00 2001 From: Gancho Tenev Date: Thu, 31 Oct 2019 13:35:37 -0700 Subject: [PATCH 101/718] Docs: clarify remap plugin inst init params (cherry picked from commit 0d88806b31293552cccf70b8aefbc55d844a7da9) --- doc/developer-guide/plugins/remap-plugins.en.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/developer-guide/plugins/remap-plugins.en.rst b/doc/developer-guide/plugins/remap-plugins.en.rst index 244651000b8..9884834c575 100644 --- a/doc/developer-guide/plugins/remap-plugins.en.rst +++ b/doc/developer-guide/plugins/remap-plugins.en.rst @@ -27,7 +27,9 @@ invoked when the rule is matched. For example, a rule such as map http://example.one/ http://example.two/ @plugin=example.so @pparam=first_arg @pparm=second_arg -will, if matched, cause the plugin "example.so" to be called with parameters "first_arg" and "second_arg". +will, if matched, cause the plugin "example.so" to be called with parameters `http://example.one/`, +`http://example.two/`, "first_arg" and "second_arg". Please keep in mind that "from" URL and "to" URL +will be converted to their canonical view. A key difference between global and remap plugins is reconfiguration and reloading. If :file:`remap.config` is reloaded, then all remap plugins are reconfigured based on the new version From 3085e02fbff634df186b5adb871804841be1d5aa Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Mon, 28 Oct 2019 11:59:27 +0900 Subject: [PATCH 102/718] Cleanup: Ignore checkprograms of remap (cherry picked from commit f5c9a57423f4087ca846e53120321e4bc39ce209) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 9d79cbd69ea..bccd632350e 100644 --- a/.gitignore +++ b/.gitignore @@ -107,6 +107,7 @@ proxy/hdrs/test_hdr_heap proxy/hdrs/test_Huffmancode proxy/hdrs/test_XPACK proxy/http/test_proxy_http +proxy/http/remap/test_* proxy/http2/test_Http2DependencyTree proxy/http2/test_Http2FrequencyCounter proxy/http2/test_HPACK From da04f6da8205ee37e9c10a62787c713fff645ca7 Mon Sep 17 00:00:00 2001 From: bneradt Date: Tue, 29 Oct 2019 21:34:59 +0000 Subject: [PATCH 103/718] Fixing log cleanup candidate selection and adding a test for it. (cherry picked from commit c9c885505d54197b4fdd4e323b906a795e37390e) --- proxy/logging/LogConfig.cc | 9 +- .../gold_tests/logging/log_retention.test.py | 105 ++++++++++++++++++ 2 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 tests/gold_tests/logging/log_retention.test.py diff --git a/proxy/logging/LogConfig.cc b/proxy/logging/LogConfig.cc index 41b0fcc4c05..84236b7ab96 100644 --- a/proxy/logging/LogConfig.cc +++ b/proxy/logging/LogConfig.cc @@ -617,12 +617,17 @@ LogConfig::update_space_used() // then check if the candidate belongs to any given log type // ts::TextView type_name(entry->d_name, strlen(entry->d_name)); + // A rolled log will look something like: + // squid.log_some.hostname.com.20191029.18h15m02s-20191029.18h30m02s.old + // + // The following logic cuts things back to original unrolled file which + // is the key into the deleting_info map (squid.log in the above example). auto suffix = type_name; - type_name.remove_suffix(suffix.remove_prefix(suffix.find('.') + 1).remove_prefix(suffix.find('.')).size()); + type_name.remove_suffix(suffix.remove_prefix(suffix.find('.') + 1).remove_prefix(suffix.find('_')).size()); auto iter = deleting_info.find(type_name); if (iter == deleting_info.end()) { // We won't delete the log if its name doesn't match any give type. - break; + continue; } auto &candidates = iter->candidates; diff --git a/tests/gold_tests/logging/log_retention.test.py b/tests/gold_tests/logging/log_retention.test.py new file mode 100644 index 00000000000..7ed68c21acc --- /dev/null +++ b/tests/gold_tests/logging/log_retention.test.py @@ -0,0 +1,105 @@ +''' +Verify correct log retention behavior. +''' +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +Test.Summary = ''' +Test the enforcment of proxy.config.log.max_space_mb_for_logs. +''' + +# Create and configure the ATS process. +ts = Test.MakeATSProcess("ts") + +ts.Disk.records_config.update({ + # Do not accept connections from clients until cache subsystem is operational. + 'proxy.config.http.wait_for_cache': 1, + + 'proxy.config.diags.debug.enabled': 1, + 'proxy.config.diags.debug.tags': 'logspace', + + 'proxy.config.log.rolling_enabled': 3, + 'proxy.config.log.auto_delete_rolled_files': 1, + + # 10 MB is the minimum rolling size. + 'proxy.config.log.rolling_size_mb': 10, + 'proxy.config.log.periodic_tasks_interval': 1, + # The following configures a 12 MB log cap with a required 2 MB head room. + # Thus the rotated log of just over 10 MB should be deleted because it + # will not leave enough head room. + 'proxy.config.log.max_space_mb_headroom': 2, + 'proxy.config.log.max_space_mb_for_logs': 12, +}) + + +# Configure approximately 5 KB entries. +ts.Disk.logging_yaml.AddLines( + ''' +logging: + formats: + - name: long + format: "{prefix}: %" + logs: + - filename: test_rotation + format: long +'''.format(prefix="0123456789"*500).split("\n") +) + +# Verify from traffic.out that the rotated log file was auto-deleted. +ts.Streams.stderr = Testers.ContainsExpression( + "logical space used.*space is not available", + "It was detected that space was not available") +ts.Streams.stderr += Testers.ContainsExpression( + "auto-deleting.*test_rotation.log", + "Verify the test log file got deleted") +ts.Streams.stderr += Testers.ContainsExpression( + "The rolled logfile.*was auto-deleted.*bytes were reclaimed", + "Verify that space was reclaimed") + +# Create and configure microserver. +server = Test.MakeOriginServer("server") +request_header = {"headers": "GET / HTTP/1.1\r\nHost: does.not.matter\r\n\r\n", + "timestamp": "1469733493.993", "body": ""} +response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\nCache-control: max-age=85000\r\n\r\n", + "timestamp": "1469733493.993", "body": "xxx"} +server.addResponse("sessionlog.json", request_header, response_header) +ts.Disk.remap_config.AddLine( + 'map http://127.0.0.1:{0} http://127.0.0.1:{1}'.format(ts.Variables.port, server.Variables.Port) +) + +# The first test run starts the required processes. +tr = Test.AddTestRun() +tr.Processes.Default.Command = 'curl "http://127.1.1.1:{0}" --verbose ; '.format( + ts.Variables.port) +tr.Processes.Default.ReturnCode = 0 +server.StartBefore(Test.Processes.ts) +tr.Processes.Default.StartBefore(Test.Processes.server) + +tr.StillRunningAfter = ts +tr.StillRunningAfter = server + +# With the following test run, we instigate a log rotation via entries from a +# few thousand curl requests. +tr = Test.AddTestRun() +# At 5K a log entry, we need a lot of curl'd requests to get to the 10 MB roll +# minimum. +curl_commands = 'for i in {{1..2500}}; do curl "http://127.1.1.1:{0}" --verbose; done'.format( + ts.Variables.port) +tr.Processes.Default.Command = curl_commands +tr.Processes.Default.ReturnCode = 0 + +tr.StillRunningAfter = ts +tr.StillRunningAfter = server From 1305e7000a50bb16dfa4d047636c2a0a460de09f Mon Sep 17 00:00:00 2001 From: bneradt Date: Fri, 25 Oct 2019 22:49:31 +0000 Subject: [PATCH 104/718] Issue 4635: Address pipe reuse after configuration reload issues (cherry picked from commit 69a318f2cbb332edcdcfb6a58aec32b91e05f867) --- proxy/logging/LogFile.cc | 6 ++++++ proxy/logging/LogObject.cc | 19 +++++++------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/proxy/logging/LogFile.cc b/proxy/logging/LogFile.cc index 1d7d0a1c8cd..d0b95dae324 100644 --- a/proxy/logging/LogFile.cc +++ b/proxy/logging/LogFile.cc @@ -118,6 +118,12 @@ LogFile::LogFile(const LogFile ©) LogFile::~LogFile() { Debug("log-file", "entering LogFile destructor, this=%p", this); + + // close_file() checks whether a file is open before attempting to close, so + // this is safe to call even if a file had not been opened. Further, calling + // close_file() here ensures that we do not leak file descriptors. + close_file(); + delete m_log; ats_free(m_header); ats_free(m_name); diff --git a/proxy/logging/LogObject.cc b/proxy/logging/LogObject.cc index f1c2337b01d..040c73dda6f 100644 --- a/proxy/logging/LogObject.cc +++ b/proxy/logging/LogObject.cc @@ -961,24 +961,20 @@ LogObjectManager::_solve_filename_conflicts(LogObject *log_object, int maxConfli LogUtils::manager_alarm(LogUtils::LOG_ALARM_ERROR, msg, filename); retVal = CANNOT_SOLVE_FILENAME_CONFLICTS; } else { - // either the meta file could not be read, or the new object's - // signature and the metafile signature do not match ==> - // roll old filename so the new object can use the filename + // Either the meta file could not be read, or the new object's + // signature and the metafile signature do not match. + // Roll the old filename so the new object can use the filename // it requested (previously we used to rename the NEW file - // but now we roll the OLD file), or if the log object writes - // to a pipe, just remove the file if it was open as a pipe + // but now we roll the OLD file). However, if the log object writes to + // a pipe don't roll because rolling is not applicable to pipes. bool roll_file = true; if (log_object->writes_to_pipe()) { - // determine if existing file is a pipe, and remove it if - // that is the case so the right metadata for the new pipe - // is created later - // + // Verify whether the existing file is a pipe. If it is, + // disable the roll_file flag so we don't attempt rolling. struct stat s; if (stat(filename, &s) < 0) { - // an error happened while trying to get file info - // const char *msg = "Cannot stat log file %s: %s"; char *se = strerror(errno); @@ -988,7 +984,6 @@ LogObjectManager::_solve_filename_conflicts(LogObject *log_object, int maxConfli roll_file = false; } else { if (S_ISFIFO(s.st_mode)) { - unlink(filename); roll_file = false; } } From 479baecb710acd927356a15eb55b0701b7b07144 Mon Sep 17 00:00:00 2001 From: bneradt Date: Fri, 18 Oct 2019 15:26:43 +0000 Subject: [PATCH 105/718] Fixing session sharing with IP matching. (cherry picked from commit 1d5089243f0dcdf0d9b39379dea47f3c14f383ab) --- proxy/http/HttpSessionManager.cc | 3 + tests/Pipfile | 1 + .../gold_tests/session_sharing/gold/200.gold | 19 +++ .../session_sharing/session_match.test.py | 113 ++++++++++++++++++ 4 files changed, 136 insertions(+) create mode 100644 tests/gold_tests/session_sharing/gold/200.gold create mode 100644 tests/gold_tests/session_sharing/session_match.test.py diff --git a/proxy/http/HttpSessionManager.cc b/proxy/http/HttpSessionManager.cc index b50e854d101..3667e6f717b 100644 --- a/proxy/http/HttpSessionManager.cc +++ b/proxy/http/HttpSessionManager.cc @@ -133,6 +133,9 @@ ServerSessionPool::acquireSession(sockaddr const *addr, CryptoHash const &hostna break; } } + } else if (last != first) { + --last; + zret = HSM_DONE; } if (zret == HSM_DONE) { to_return = last; diff --git a/tests/Pipfile b/tests/Pipfile index 83578aca495..f8a6bcc5009 100644 --- a/tests/Pipfile +++ b/tests/Pipfile @@ -30,6 +30,7 @@ dnslib = "*" requests = "*" gunicorn = "*" httpbin = "*" +microserver = ">=1.0.4" [requires] python_version = "3" diff --git a/tests/gold_tests/session_sharing/gold/200.gold b/tests/gold_tests/session_sharing/gold/200.gold new file mode 100644 index 00000000000..c1ac419ea9e --- /dev/null +++ b/tests/gold_tests/session_sharing/gold/200.gold @@ -0,0 +1,19 @@ +`` +< HTTP/1.1 200 OK +`` +< Content-Length: 0 +`` +< Connection: close +`` +< HTTP/1.1 200 OK +`` +< Content-Length: 0 +`` +< Connection: close +`` +< HTTP/1.1 200 OK +`` +< Content-Length: 0 +`` +< Connection: close +`` diff --git a/tests/gold_tests/session_sharing/session_match.test.py b/tests/gold_tests/session_sharing/session_match.test.py new file mode 100644 index 00000000000..2e619e5eff9 --- /dev/null +++ b/tests/gold_tests/session_sharing/session_match.test.py @@ -0,0 +1,113 @@ +''' +Test that a plugin can modify server session sharing. +''' +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +class SessionMatchTest: + TestCounter = 0 + def __init__(self, TestSummary, sharingMatchValue): + SessionMatchTest.TestCounter += 1 + self._MyTestCount = SessionMatchTest.TestCounter + Test.Summary = TestSummary + self._tr = Test.AddTestRun() + self._sharingMatchValue = sharingMatchValue + self.setupOriginServer() + self.setupTS() + + def setupOriginServer(self): + self._server = Test.MakeOriginServer("server{counter}".format(counter=self._MyTestCount)) + request_header = {"headers": + "GET /one HTTP/1.1\r\nHost: www.example.com\r\nContent-Length: 0\r\n\r\n", + "timestamp": "1469733493.993", "body": ""} + response_header = {"headers": "HTTP/1.1 200 OK\r\nServer: microserver\r\n" + "Content-Length: 0\r\n\r\n", + "timestamp": "1469733493.993", "body": ""} + self._server.addResponse("sessionlog.json", request_header, response_header) + + request_header2 = {"headers": "GET /two HTTP/1.1\r\nContent-Length: 0\r\n" + "Host: www.example.com\r\n\r\n", + "timestamp": "1469733493.993", "body": "a\r\na\r\na\r\n\r\n"} + response_header2 = {"headers": "HTTP/1.1 200 OK\r\nServer: microserver\r\n" + "Content-Length: 0\r\n\r\n", + "timestamp": "1469733493.993", "body": ""} + self._server.addResponse("sessionlog.json", request_header2, response_header2) + + request_header3 = {"headers": "GET /three HTTP/1.1\r\nContent-Length: 0\r\n" + "Host: www.example.com\r\nConnection: close\r\n\r\n", + "timestamp": "1469733493.993", "body": "a\r\na\r\na\r\n\r\n"} + response_header3 = {"headers": "HTTP/1.1 200 OK\r\nServer: microserver\r\n" + "Connection: close\r\nContent-Length: 0\r\n\r\n", + "timestamp": "1469733493.993", "body": ""} + self._server.addResponse("sessionlog.json", request_header3, response_header3) + + def setupTS(self): + self._ts = Test.MakeATSProcess("ts{counter}".format(counter=self._MyTestCount)) + self._ts.Disk.remap_config.AddLine( + 'map / http://127.0.0.1:{0}'.format(self._server.Variables.Port) + ) + self._ts.Disk.records_config.update({ + 'proxy.config.diags.debug.enabled': 1, + 'proxy.config.diags.debug.tags': 'http', + 'proxy.config.http.auth_server_session_private': 1, + 'proxy.config.http.server_session_sharing.pool': 'global', + 'proxy.config.http.server_session_sharing.match': self._sharingMatchValue, + }) + + def _runTraffic(self): + self._tr.Processes.Default.Command = ( + 'curl -v -H\'Host: www.example.com\' -H\'Connection: close\' http://127.0.1:{port}/one &&' + 'curl -v -H\'Host: www.example.com\' -H\'Connection: close\' http://127.0.1:{port}/two &&' + 'curl -v -H\'Host: www.example.com\' -H\'Connection: close\' http://127.0.1:{port}/three'.format( + port = self._ts.Variables.port)) + self._tr.Processes.Default.ReturnCode = 0 + self._tr.Processes.Default.StartBefore(self._server) + self._tr.Processes.Default.StartBefore(self._ts) + self._tr.Processes.Default.Streams.stderr = "gold/200.gold" + + def runAndExpectSharing(self): + self._runTraffic() + self._ts.Streams.stderr = Testers.ContainsExpression( + "global pool search successful", + "Verify that sessions got shared") + + def runAndExpectNoSharing(self): + self._runTraffic() + self._ts.Streams.stderr = Testers.ExcludesExpression( + "global pool search successful", + "Verify that sessions did not get shared") + + +sessionMatchTest = SessionMatchTest( + TestSummary='Test that session sharing works with host matching', + sharingMatchValue='host') +sessionMatchTest.runAndExpectSharing() + +sessionMatchTest = SessionMatchTest( + TestSummary='Test that session sharing works with ip matching', + sharingMatchValue='ip') +sessionMatchTest.runAndExpectSharing() + +sessionMatchTest = SessionMatchTest( + TestSummary='Test that session sharing works with matching both ip and host', + sharingMatchValue='both') +sessionMatchTest.runAndExpectSharing() + +sessionMatchTest = SessionMatchTest( + TestSummary='Test that session sharing is disabled when matching is set to none', + sharingMatchValue='none') +sessionMatchTest.runAndExpectNoSharing() From 782d9e4d923300006a55c4b2d7dd4e9d9bae2277 Mon Sep 17 00:00:00 2001 From: Bryan Call Date: Thu, 24 Oct 2019 15:16:06 -0700 Subject: [PATCH 106/718] Updated API header and ssl_session_reuse for new TSSslSessionInsert changes (cherry picked from commit ed2a8befdf4333cd5473baae99807850f1be2392) --- include/ts/ts.h | 2 +- iocore/net/SSLSessionCache.cc | 2 +- iocore/net/SSLSessionCache.h | 2 +- plugins/experimental/ssl_session_reuse/src/session_process.cc | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/ts/ts.h b/include/ts/ts.h index a0887dec5da..60828f9bc57 100644 --- a/include/ts/ts.h +++ b/include/ts/ts.h @@ -1262,7 +1262,7 @@ TSReturnCode TSVConnProtocolEnable(TSVConn connp, const char *protocol_name); tsapi int TSVConnIsSsl(TSVConn sslp); tsapi TSSslSession TSSslSessionGet(const TSSslSessionID *session_id); tsapi int TSSslSessionGetBuffer(const TSSslSessionID *session_id, char *buffer, int *len_ptr); -tsapi TSReturnCode TSSslSessionInsert(const TSSslSessionID *session_id, TSSslSession add_session); +tsapi TSReturnCode TSSslSessionInsert(const TSSslSessionID *session_id, TSSslSession add_session, TSSslConnection ssl_conn); tsapi TSReturnCode TSSslSessionRemove(const TSSslSessionID *session_id); /* -------------------------------------------------------------------------- diff --git a/iocore/net/SSLSessionCache.cc b/iocore/net/SSLSessionCache.cc index 611b4c8b70f..17fb174bfd6 100644 --- a/iocore/net/SSLSessionCache.cc +++ b/iocore/net/SSLSessionCache.cc @@ -168,7 +168,7 @@ SSLSessionBucket::insertSession(const SSLSessionID &id, SSL_SESSION *sess, SSL * ink_release_assert(static_cast(buf_exdata->block_size()) >= len_exdata); ssl_session_cache_exdata *exdata = reinterpret_cast(buf_exdata->data()); // This could be moved to a function in charge of populating exdata - exdata->curve = SSLGetCurveNID(ssl); + exdata->curve = (ssl == nullptr) ? 0 : SSLGetCurveNID(ssl); ats_scoped_obj ssl_session(new SSLSession(id, buf, len, buf_exdata)); diff --git a/iocore/net/SSLSessionCache.h b/iocore/net/SSLSessionCache.h index 7968b46bd34..44ba12d764c 100644 --- a/iocore/net/SSLSessionCache.h +++ b/iocore/net/SSLSessionCache.h @@ -33,7 +33,7 @@ #define SSL_MAX_SESSION_SIZE 256 struct ssl_session_cache_exdata { - ssl_curve_id curve; + ssl_curve_id curve = 0; }; struct SSLSessionID : public TSSslSessionID { diff --git a/plugins/experimental/ssl_session_reuse/src/session_process.cc b/plugins/experimental/ssl_session_reuse/src/session_process.cc index 3f69e18f3ea..be6e029d222 100644 --- a/plugins/experimental/ssl_session_reuse/src/session_process.cc +++ b/plugins/experimental/ssl_session_reuse/src/session_process.cc @@ -249,7 +249,7 @@ add_session(char *session_id, int session_id_len, const std::string &encrypted_s if (sid.len > sizeof(sid.bytes)) { sid.len = sizeof(sid.bytes); } - TSSslSessionInsert(&sid, reinterpret_cast(sess)); + TSSslSessionInsert(&sid, reinterpret_cast(sess), nullptr); // Free the sesison object created by d2i_SSL_SESSION // We should make an API that just takes the ASN buffer SSL_SESSION_free(sess); From 8573b234eaac86034f5e29532b44b31c4b555f1f Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Wed, 23 Oct 2019 13:48:17 +0900 Subject: [PATCH 107/718] Ignore MgmtMessageHdr if ProcessManager is not running (cherry picked from commit 5936dcdda6d8f6695ce613e6022bf735732ca566) --- mgmt/ProcessManager.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mgmt/ProcessManager.cc b/mgmt/ProcessManager.cc index ef18e237c6a..897cef1cc70 100644 --- a/mgmt/ProcessManager.cc +++ b/mgmt/ProcessManager.cc @@ -266,6 +266,10 @@ ProcessManager::signalManager(int msg_id, std::string_view text) void ProcessManager::signalManager(MgmtMessageHdr *mh) { + if (!this->running) { + Warning("MgmtMessageHdr is ignored. Because ProcessManager is not running"); + return; + } ink_release_assert(::enqueue(mgmt_signal_queue, mh)); #if HAVE_EVENTFD From 807e6cbdeb9c9d79be768fe73a19a5b6167d4e32 Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Mon, 4 Nov 2019 10:18:25 -0700 Subject: [PATCH 108/718] Updated ChangeLog --- CHANGELOG-9.0.0 | 86 ++++++++++--------------------------------------- 1 file changed, 17 insertions(+), 69 deletions(-) diff --git a/CHANGELOG-9.0.0 b/CHANGELOG-9.0.0 index d211d56fbfd..2d520825fd1 100644 --- a/CHANGELOG-9.0.0 +++ b/CHANGELOG-9.0.0 @@ -9,14 +9,11 @@ Changes with Apache Traffic Server 9.0.0 #3900 - ts/Extendible and AcidPtr classes #3901 - MemArena: Add make method to construct objects in the arena. #3907 - IntrusiveDList: Refreshed for C++ eleventy, added const_iterator. - #3913 - Doc: fix build error in traffic_layout documentation. #3921 - Bug fix in microServer's threading and reorganized some code #3925 - Enforce sphinx>=1.7.5 when building docs #3930 - Remove proxy.config.config_dir from records.config #3941 - Fix RecConfigReadPluginDir and clean up RecCore - #3942 - Doc: Fix build error in Lua plugin documentation. #3943 - Handle response parsing case where EOF happens before any data arrives. - #3945 - Doc: Tweak to fix doc issues in IntrusiveDList documentation. #3951 - Fixed broken sphinx version check on MacOS #3955 - IntrusiveHashMap: Refresh TSHashTable for C++ eleventy. #3957 - Add generic "guard" class (PostScript) for exception and early function return safety. @@ -27,12 +24,12 @@ Changes with Apache Traffic Server 9.0.0 #3966 - Add BWF support for SourceLocation. #3967 - BufferWriter: Add print overloads to FixedBufferWriter #3968 - Test: Convert test_Regex.cc to Catch. - #3982 - Minor update on README's directory structure #3992 - TextView: More unit tests. #3993 - Test: Convert test_Ptr.cc to Catch. #4003 - Fix another crash on shutdown #4008 - Add support for 'fwd' value to X-Debug header, and move to later hook any deletion of X-Debug header from client request. #4020 - Add logic to clean up vios on HttpSM shutdown + #4028 - proxy.config.http.connect_attempts_timeout tracks TTBF instead of connect #4029 - Replace TSHashTable in server session management with IntrusiveHashMap #4033 - Removes remnants of dprintf support #4039 - Enable ECDH explicitly only if OpenSSL version is v1.0.2 or lower @@ -42,7 +39,6 @@ Changes with Apache Traffic Server 9.0.0 #4047 - Improve log entry for http connect result errors #4049 - Removes carriage returns from MT_hashtable.h #4050 - Optimize: make NetAccept::init_accept_loop has the logic similar to NetAccept::init_accept_per_thread - #4051 - Doc: Document TSContCall #4063 - BWF: Add "FirstOf" for better handling of printing alternates for null strings. #4064 - Runroot: Update test to support different layout #4067 - Bug fix for timeout test @@ -51,21 +47,17 @@ Changes with Apache Traffic Server 9.0.0 #4089 - reenable timeout and change microServer timeout logic #4095 - Optimize: Assign nh->mutex to new NetVC first and switch to new mutex within UnixNetVC::acceptEvent #4098 - adding a Mutex to the continuation - #4100 - Doc: Update comments in InkAPI.cc in the header and for member converters. #4107 - Fixes MacOS linker issue with release build #4113 - Disables openclose_h2 test. #4115 - TextView: Add overload for strcasecmp for string_view & TextView. #4125 - ssl_session_reuse plugin - #4127 - Allows to run Spinx builds on portions of the docs #4129 - Update IPAllow infrastructure. - #4132 - Completes documentation regarding redirects #4133 - Disables the double test for inconsistent execution #4140 - Meta: Add conditional compilation case meta structures. #4145 - Adds configurable behavior on redirect to loopback #4146 - Cleanup: remove unused and unimplemented functions from ink_string.h #4148 - Cleanup: Remove #define INT_TO_BOOL, use local lambda instead. #4149 - Clang-format: Redo clang-format error that slipped through. - #4163 - Doc: Remove deprecated configs from examples of traffic_ctl #4168 - YAML: Convert ip_allow.config #4175 - TextView: Better support for std::string assignment. #4176 - TextView: Add support for use as "Source" in STL containers. @@ -82,11 +74,9 @@ Changes with Apache Traffic Server 9.0.0 #4220 - IntrusiveHashMap: Inserts preserve order for equal keys, as with std::multimap #4221 - IntrusiveHashMap: Fix for find false positive in some cases. #4226 - HttpSessionManager: Fix potential infinite loop problem. - #4234 - Corrects path to test file in docs #4240 - Inherited Extendible #4249 - Test: Convert test_PriorityQueue.cc to Catch #4257 - Update base version of AuTest to 1.6.0 - #4259 - Corrects typo in argument name #4260 - Removes logging of secrets #4261 - Adds a few missing packages needed by autest #4265 - CMakeLists.txt: Change to be generic and not need updates so often. @@ -97,12 +87,10 @@ Changes with Apache Traffic Server 9.0.0 #4289 - Do not follow redirects after cache hit #4290 - Remove unnecessary line in src/Makefile.am #4300 - Expand the post chunked tests. - #4301 - Fix doc building warnings for recent plugin docs #4305 - Generally random code cleanup #4306 - Convert traffic_cache_tool to use ArgParser #4309 - Orders k-v pairs to avoid making too many files #4310 - Add warning of body_factory templates are not loaded due to missing dot file - #4324 - Adds Robots exclusion file #4331 - Make build failures also mark the CA builds as failed #4332 - Fixes build issues related to Clang Analyzer only #4334 - Converts ink_autoconf.h to #pragma once @@ -116,7 +104,6 @@ Changes with Apache Traffic Server 9.0.0 #4357 - TCL: Remove TCL dependency from iocore #4360 - Fix mysql_remap plugin build with MySQL 8 #4363 - CMake: Add lib/records, unit_tests. - #4366 - Docs: Remove the EXTERNAL_TYPES logic #4368 - s3_auth_v4: update default region map #4374 - TCL: remove TCL dependency from RecHttp #4384 - Fix gzip(compress) plugin not linked correctly with zlib @@ -126,7 +113,6 @@ Changes with Apache Traffic Server 9.0.0 #4402 - Convert traffic_cache_tool to use ts_file #4406 - ts_file: Add 'view' method to get a view of the path. #4411 - Split current client transactions metrics into HTTP/1.1 and HTTP/2 - #4412 - Cachekey plugin doc minor typos fixed. #4414 - Cleaning up TLS server verify options #4422 - TCL: Rmove TCL dependency from HostStatus #4424 - YAML: LibSWOC IntrusiveDList update. @@ -159,7 +145,6 @@ Changes with Apache Traffic Server 9.0.0 #4522 - Rewrite TunnelHashMap in modern standard #4524 - Convert ctx_store in SSLCertLookUp to use STL vector #4526 - Atomic: Convert ProxyConfig to use std::atomic. - #4527 - Remove FAQ entry claiming that Traffic Server does not support expect-100 #4531 - Rewrite url after running all remap plugins #4532 - Remove explicit free of ref-counted object. #4536 - Minor C++ cleanup for background_fetch @@ -168,7 +153,6 @@ Changes with Apache Traffic Server 9.0.0 #4544 - Updated Dockerfile with some additional dependencies #4545 - Fix tunnel_route action in ssl_server_name and various test fixes for Fedora 28 and 29 #4546 - Test: fix failed clang link for test_proxy_http. - #4551 - Fix TLS hooks diagram and other docs cleanup #4553 - hostdb: Replace the last TSHashTable with IntrusiveHashMap. #4555 - Test: fix test_Ptr.cc to deal with clang not liking "p1 = p1". #4564 - Fix duplicate keys in python dict @@ -196,11 +180,9 @@ Changes with Apache Traffic Server 9.0.0 #4630 - Generalize the wild-card fqdn's for user_agent attributes in ssl_server_name #4641 - Issue #4637: Clean up / unify hex conversions. #4642 - Issue #4637 - Clean up / unify hex conversions - #4643 - Docs: Fix proxy.config.net.connections_throttle text. #4645 - Cleanup: Remove Map.h including HashMap, Vec and TSHashTable #4646 - TCL: Remove TCL from our code base #4657 - TLS Bridge: Fix error where connect failure lead to a silent timeout. - #4660 - Runroot: Add a new doc on runroot for programs #4662 - Adds a reasonable rip-grep config file #4663 - Add back in the option to conf_remap the verify_server settings. #4666 - Allow empty fqdn in ssl_server_name for unset SNI case. @@ -219,7 +201,6 @@ Changes with Apache Traffic Server 9.0.0 #4703 - Correct the statements within ink_assert and ink_release_assert #4704 - task threads ready lifecycle hook #4705 - Eliminate remaining hack around copy CTORs - #4706 - Correction to documentation for TSHttpHookAdd(). #4707 - Remove the APIHooks::invoke() function. #4712 - Make client cert overridable #4715 - Optimize: Avoid meaningless lock operations @@ -228,17 +209,14 @@ Changes with Apache Traffic Server 9.0.0 #4720 - Fix disable freelist options #4721 - Optimize: Do not signal EThreads which are not blocked on cond_timedwait #4722 - Add control for how outbound SNI is selected. - #4723 - Fix documentation on client certificates in ssl_server_name #4724 - Add shutdown lifecycle hook #4727 - Remove unused Http2Stream destructor #4730 - Moved AtomicBit into its own file. #4734 - Event num ordering #4738 - Fix typo in HdrHeap #4746 - Optimize: tighten the logic of the PluginVC::process_read/write_side() - #4747 - Slight clarification to documentation of TLS User Agent Hooks. #4748 - Tries to enforce .git installation of pre-commit #4749 - Add more information about event data to 'hook add' API function documentation. - #4750 - Fix spelling errors reported by lintian #4760 - Updated STATUS with all known releases #4764 - Adds logging around various config file loads #4765 - Cleanup: Make _next_round_robin uint64_t @@ -256,11 +234,9 @@ Changes with Apache Traffic Server 9.0.0 #4804 - Regex: update to use string_view. #4805 - JA3 fingerprint and documentation #4806 - Add Log fields that dump all MIME headers in a message. - #4809 - Set "Language" of po files under doc/locale/ja/ #4814 - Add normalization the URI before cdniuc validation in URI Signing #4815 - Add valid_tls_protocols_in to allow for per-domain protocols. #4816 - Fix potential unterminated string in logging in state machine. - #4817 - Fix a content issue and a couple format issues. #4818 - Add log method overload for string_view to LogObject #4819 - Add clang-format build target to CMake editor file. #4827 - MIME: Update MIMEField::name_get and MIMEField::value_get to return string_view @@ -273,9 +249,7 @@ Changes with Apache Traffic Server 9.0.0 #4835 - TLS Bridge: Fix possible race condition. #4836 - Correctly deal with the ssl.client.sni_policy if not set via conf_remap #4837 - Fix potential instability in cacheIMSRange - #4840 - resolve stack-use-after-scope in YamlLogConfig.cc #4841 - Do not call dns_result repeatedly for a valid dns result. - #4844 - doc for option -F #4846 - Fix initialization style. #4847 - Increase the per test case timeout from 5 to 10 seconds #4849 - Allow client_cert and client_key to be specified by relative path @@ -300,7 +274,6 @@ Changes with Apache Traffic Server 9.0.0 #4901 - Update overridable config conversion logic. #4903 - Adjust connection timeout for TLS #4909 - Update plugin API type conversions to support enums automatically. - #4910 - Doc: Update HdrHeap documentation for serialization, string inheritance. #4914 - DFA: Update DFA to use string_view. #4916 - Optimize: Keep cont->mutex locked, during probe the bucket by hash object within HostDBProcessor::getby #4917 - Update HdrUtils to be C++17. @@ -324,7 +297,6 @@ Changes with Apache Traffic Server 9.0.0 #4955 - Marks the YAML exceptions, which gives line number / pos info #4956 - Fix a ssl handshake crash during shutdown #4957 - Remove error-prone mirror enum in code handling TS API SSL hooks. - #4960 - Add doc for using relative path to configuration directory for lua sc… #4961 - Optimize: rewrite getbyname_imm and getSRVbyname_imm as wrappers for getby #4962 - Remove unnecessary storing of redirect_url in redirect_info #4964 - Rewrite URL before all remap plugins run @@ -336,7 +308,6 @@ Changes with Apache Traffic Server 9.0.0 #4975 - URL: remove undefined function declaration. #4976 - Fix tls_forward_nonhttp test requirement #4979 - Ignore config.cache file - #4982 - Documentation fix to lua plugin #4986 - Added TS_SSL_CLIENT_HELLO_HOOK and docs #4988 - Implement nbf claim in Uri Signing Plugin #5000 - Add Perltidy configuration and build target @@ -371,7 +342,6 @@ Changes with Apache Traffic Server 9.0.0 #5074 - Move minimum OpenSSL version to 1.0.2 #5075 - Fixed the compatibility with previous cache verison #5077 - Unify plugins hook dispatch - #5078 - Fix directives for checking TS_USE_TLS_OCSP #5079 - Fix directives for checking TS_HAS_TESTS #5082 - Add support for the lua and numeric log roll values #5086 - Remove extra args to bwprint in SSLConfigParams::getCTX() @@ -402,6 +372,7 @@ Changes with Apache Traffic Server 9.0.0 #5152 - Test acid ptr persistence #5153 - Separate P_SSLUtil and P_SSLClientUtils includes #5157 - Set the block's m_water_level in Arena:free even if the block is not the last block + #5163 - Fix memleak in ProcessManager::stop() #5167 - Fix Makefile.am to run clang-tidy #5172 - Run clang-tidy one by one #5174 - Adds Cache test suits @@ -420,7 +391,6 @@ Changes with Apache Traffic Server 9.0.0 #5199 - autest for slice plugin #5201 - Replace EThread::has_event_loop with EThread::tt == REGULAR #5204 - Moved unit test suppression file and updated it - #5205 - Adding a note into storage.config admin doc about cache invalidation … #5208 - Adds a little wrapper script to build inside vscode #5211 - Check return value of open #5212 - Cache:ttl-in-cache should always override never-cache @@ -452,12 +422,9 @@ Changes with Apache Traffic Server 9.0.0 #5278 - Fixes the Brotli build issues #5281 - Change Au test condition for minimal OpenSSL version to use traffic_layout info --versions #5282 - Plugin reload - #5286 - Update README.md - #5289 - Don't read frames after sending GOAWAY with an error code #5290 - MIMEScanner: Only clear scanner line buffer if at MIME_PARSE_BEFORE state #5292 - Fix a build error in xdebug on macos #5293 - Destroy MIMEFieldBlockImpl that doesn't have fields in use - #5297 - Doc: fix proxy.config.cache.ram_cache.algorithm description #5301 - Slice Plugin: add options for disabling or pacing detailed block stitch error logging. #5302 - Correct config name for proxy.config.dns.connection_mode #5306 - Removes priorities for AIOs, thanks oknet @@ -470,7 +437,6 @@ Changes with Apache Traffic Server 9.0.0 #5313 - cppcheck: Reduce the scope of the variable 'out_buf' #5314 - cppcheck fixes for iocore/hostdb #5315 - cppcheck: Fixed various issues with SSL files - #5316 - cppcheck: Removed problematic move operators for FixedBufferWriter. #5317 - cppcheck: Fix various issues of Http2DependencyTree #5318 - cppcheck: Fixes various issues under proxy/http/remap #5320 - Added user defined conversion operator in ConstBuffer for string_view. @@ -484,7 +450,6 @@ Changes with Apache Traffic Server 9.0.0 #5328 - cppcheck: fixes issues found for plugins/authproxy #5329 - Fixes clang-analyzer error dereferencing nullptr in parent #5330 - cppcheck: Fix various issues of Http2ConnectionState - #5331 - Off by 1 error in memcpy of redirect url #5333 - cppcheck: Reduces variable scope for files in mgmt/... #5334 - cppcheck: fixes issues in ink_uuid.h #5335 - cppcheck: Change to C++ style pointer casting in Thread.cc @@ -538,14 +503,8 @@ Changes with Apache Traffic Server 9.0.0 #5420 - Adds update header only test case #5421 - Check nullptr before call netvc->do_io_close in SSLNextProtocolAccept::mainEvent #5423 - This fixes parsing where the [ ] section gets merged into values - #5424 - Fix ContFlags for gcc 9. #5425 - Updates the VSCode include dirs - #5427 - gcc9 - fix class Connection. - #5428 - gcc9 - fix CryptoHash.h #5431 - New APIs: Server/ClientCertUpdate - #5433 - gcc9 - Fix Errata.h, NumericType.h. - #5434 - gcc9 - Fix I_Store.h - #5435 - gcc9 - fix HTTPVersion. #5436 - Additional places to propagate the per-client-ip debug tags. #5438 - Add wait_for_cache to make all_headers test more resilient #5439 - Removes unused TSConfig usage in ssl_sni example @@ -560,7 +519,6 @@ Changes with Apache Traffic Server 9.0.0 #5451 - Fix FREELIST macros for AArch64 #5452 - Clang Analyzer: Fix IpMap.cc false positives. #2 #5455 - Convert ssl_preaccept plugin to use command-line arguments - #5456 - Fixes spelling in doc #5458 - Updates the Docker image with latest dependencies #5460 - Fixed clang-analyzer issue calling schedule_imm with the continuation possibly being a nullptr #5462 - gcc9: fixed issue with always printing a null char* @@ -575,19 +533,16 @@ Changes with Apache Traffic Server 9.0.0 #5477 - Removes proxy.config.http.server_tcp_init_cwnd #5478 - Fixes some cache-tests build issues #5480 - Add HKDF wrapper - #5482 - Document proxy.config.ssl.server.honor_cipher_order #5489 - gcc9: set default value for printing debug message #5490 - clang-analyzer: Fix uninitialized variable in make_to_lower_case. #5492 - clang-analyzer: fix bogus use after free with Ptr in LogFieldInt constructor. #5495 - Correct the clear range when cache restart #5497 - gcc9: sprintf and strncat fixes in plugins #5500 - Added Docker support for Fedora 29 and Fedora 30 - #5502 - This is already documented in the proper traffic_ctl page #5507 - AcidPtr: Tweaks tests to be a bit more robust. #5508 - Grab lock before invoke #5509 - clang analzyer - fix false positive in Vol::handle_recover_from_data. #5510 - TextView: clean up on strcasecmp, strcmp, and memcmp. - #5516 - Make code compilable with BoringSSL #5518 - Adds a missing dependency, bump autest version #5520 - Cleanup of autest prog checks, and indentation #5521 - Check for OpenSSSL v1.1.1, for now, for this test @@ -607,7 +562,6 @@ Changes with Apache Traffic Server 9.0.0 #5552 - Add options to sort to reduce os differences in all_headers test #5554 - Updates Dockerfile, and adds a comment to autest bootstrap #5555 - Ran clang-tidy with google-readability-casting - #5556 - Minor wording changes in ssl_server_name.yaml docs #5557 - Removes empty config load warning for YAML-based configuration files #5558 - Removed headers that don't exist in the dir to fix clang-tidy #5559 - Move sni config (formerly ssl_server_name) under toplevel YAML tag 'sni' @@ -639,8 +593,6 @@ Changes with Apache Traffic Server 9.0.0 #5608 - Removes the remaining code and configurations for SSL3 #5609 - Added cert_reporting_tool plugin based off example/client_context_dump #5610 - Removes the explicit Vary configurations and code - #5613 - Doc: Add documentation for HTTP/2 statistics - #5614 - Add Pipfile for building docs #5615 - Separate stubs for libinknet from test_I_UDPNet.cc #5616 - Updates README to reflect current source tree layout #5617 - Moves Errata to tscore, removes everything else from tsconfig @@ -655,7 +607,6 @@ Changes with Apache Traffic Server 9.0.0 #5636 - HTTP/2: ignore unknown settings #5637 - TextView: Fix bug in rtrim_if when entire view is cleared. #5639 - update example directory structure and add examples for lua plugin - #5640 - Add reference to ts.client_request.get_pristine_url() in lua plugin #5643 - Cleanup debug log in mime_hdr_describe #5645 - Fix default logging.yaml with new format. #5647 - Replaces Emergency() with Error() when parsing these records.config values @@ -680,7 +631,6 @@ Changes with Apache Traffic Server 9.0.0 #5678 - More Autest ports cleanup #5680 - HTTP/2 - tweak for better field name handling. #5683 - Cleanup example directory - #5685 - Fix typo in lua plugin documentation #5686 - Reverse internal order of HPACK Dynamic Table Entries #5690 - Fix race condition in test #5697 - Coalesce empty objects in HdrHeap @@ -701,11 +651,9 @@ Changes with Apache Traffic Server 9.0.0 #5717 - Change default proxy name to be "traffic_server", not the build machine. #5721 - Fixes autodetect of brotli #5722 - In test_hooks Au test case, add work-around for flakeyness of VCONN start/close events. - #5723 - Update docs to document wipe_field_action that we use in production #5724 - Enable logging of the Elliptic Curve used to communicate with the client #5726 - Expose client request SSL stats via API & Lua plugin #5728 - Remove header_rewrite conditions deprecated in previous versions - #5730 - Cleanup and link references to sni.yaml #5731 - Use un-deprecated records for SSL server verification #5732 - Remove proxy.config.http.cache.allow_empty_doc #5733 - Fix typos in log.gold file for tsapi Au test case in merged PR 5706. @@ -723,7 +671,6 @@ Changes with Apache Traffic Server 9.0.0 #5752 - fixed datatype in example plugin #5753 - Add QUIC draft-20 support #5755 - Initialize EventIO - #5756 - Minor typo in CONTRIBUTING.md #5762 - Limit resources used by regex_remap to prevent crashes on stack overflow #5765 - Avoid a clang warning when all the defines are set #5766 - Record HttpSM Id on new transaction @@ -732,41 +679,32 @@ Changes with Apache Traffic Server 9.0.0 #5770 - IPAllow: change top level key to "ip_allow". #5771 - Fixes linker changes for luajit on macOS #5772 - Remove ssl_error stats that aren't really errors. - #5773 - Documentation for Autest in Sphinx #5774 - Updating the default cipher-suite lists for the 9.x release. #5778 - Issue 5604 - fix memory leaks for http parser. - #5779 - doc: TSL used instead of TLS in Japanese docs #5780 - Fixed std::array initialization for older compilers #5785 - Allocate DependencyTree only if HTTP/2 stream priority is enabled #5786 - Mark debug logs of polling as verbose #5789 - Add protection against null pointer access #5792 - Rename remaining references to ip_allow.config to ip_allow.yaml #5797 - Remove double call of the SNI action on TLS accept. - #5800 - Doc: fix manpage error which causes Makefile problem. #5803 - Make TS_NULL_MLOC a valid C compile-time constant. - #5806 - More doc spelling fixes #5808 - Remove unused assignment to satisfy clang-analyzer #5809 - Address possible use after free issue in HttpVCTable::remove_entry #5811 - Fix no_activity timeout for server session reuse. #5813 - Fixes broken links to documentation #5815 - Updates links to trafficserver.apache.org to https - #5817 - Fixes various issues found in docs #5819 - make check race condition fix #5821 - HTTP/2 rate limiting - #5823 - Avoid AWS auth v4 path/query param double encoding #5824 - Reactivate active timeout enforcement #5825 - Cleanup: Remove unused function & old comments #5826 - Cleanup: Signal READ_READY event only if the buffer is readable - #5827 - compress plugin: document undocumented options #5828 - Make client_context_dump test resilient to dump order changes #5829 - fix bugs from log filter feature #5830 - Make proxy.config.http.per_server.min_keep_alive_connections overridable #5831 - Fix QUIC build - #5833 - Fix H2 internal counters #5834 - Ran clang-tidy before 9.0.x branching #5839 - Fix inactivity timeout on QUIC #5841 - Cleanup: unifdef WRITE_AND_TRANSFER - #5844 - Explain how SRV origin selection works #5847 - Cleanup: Remove unused empty files #5848 - Convert check programs in iocore/eventsystem/ into Catch based unit tests #5852 - Replaced ProxyTxn::outbound vars with accept::options @@ -785,7 +723,6 @@ Changes with Apache Traffic Server 9.0.0 #5880 - ProxyTxn Refactor move code to cc #5883 - Add unit tests for MIOBuffer:write() #5885 - Add the ability to static link ASAN, TSAN and LSAN - #5887 - Fixed const issue with magick plugin #5888 - Allow disabling HTTP/2 priority frames limit #5889 - Provide stats for the recently introduced HTTP/2 rate limits #5892 - ProxySsn renaming member vars @@ -796,15 +733,12 @@ Changes with Apache Traffic Server 9.0.0 #5906 - Cleanup: unifdef TRACK_BUFFER_USER #5907 - Fix macOS build #5908 - ProxySession cleanup: moving inline functions to .h - #5915 - Update documentation for connect_attempts_timeout. #5919 - Rearrange config reload notifications #5920 - Cleanup: VIO #5921 - Cleanup AuTest for HTTP/2 #5922 - Make code buildable with BoringSSL #5926 - Fix AuTest for HTTP/2 using httpbin - #5930 - Track SSL session cache evictions performed due to full bucket #5934 - Track scheduled events to (read|write)_vio.cont from Http2Stream - #5935 - Perform a SSL quiet shutdown when close-notify is not sent #5937 - Update TSVConnSslConnectionGet name to match other TSVConnSsl* APIs #5939 - Remove hard coded filename in error message #5945 - cachekey: allow multiple values for `--key-type` @@ -813,7 +747,6 @@ Changes with Apache Traffic Server 9.0.0 #5955 - Fix debug output for global_user_agent_header. #5956 - Turn on certificate verification, in permissive mode for now #5959 - Clear api set bit to avoid crash in following redirect. - #5961 - Clarify docs on the change from redirect_enabled. #5962 - Removed hardcoded sni.yaml configuration filename in logs #5964 - Fix a build issue on enabling FIPS #5969 - Change the ready checks for ats to use the actual ats port @@ -828,5 +761,20 @@ Changes with Apache Traffic Server 9.0.0 #6000 - Add QUIC draft-23 support #6003 - Cleanup: do not re-define _proxy_ssn variable in local #6008 - Do not schedule stuff during shutdown + #6011 - clang-analyzer: Add a null check #6016 - Fix host type in host matcher. #6024 - Make proxy.config.http.request_buffer_enabled configurable and bug fix + #6031 - listen on all the net threads + #6054 - Ignore MgmtMessageHdr if ProcessManager is not running + #6062 - Adding connection close headers to regex_remap test. + #6066 - Fixing session sharing with IP matching. + #6070 - Updated API header and ssl_session_reuse for new TSSslSessionInsert changes + #6071 - Premature DSO unload with "suicidal" continuations + #6076 - Issue 4635: Address pipe reuse after configuration reload issues + #6078 - Cleanup: Ignore checkprograms of remap + #6089 - Make If-Range date compare to be exact match + #6095 - For remap_stats, removes configure time dependency on search.h + #6096 - Fixing log cleanup candidate selection and adding a test for it. + #6099 - doc + unittest TSRemap(Init|NewInstance) failures + #6106 - Removes proxy.config.cache.storage_filename + #6120 - Fix null pointer dereference reported by clang-analyzer From 4f6b220f001227d0ff23a4594cba3e0a04922514 Mon Sep 17 00:00:00 2001 From: Randall Meyer Date: Thu, 31 Oct 2019 15:58:38 -0700 Subject: [PATCH 109/718] Fixes misc. spelling and whitespace (cherry picked from commit 20ec81edccff4629ca60287700e1d0f9a1f293c8) Conflicts: doc/admin-guide/files/records.config.en.rst --- doc/admin-guide/files/records.config.en.rst | 7 +++++-- doc/admin-guide/plugins/cachekey.en.rst | 2 +- src/tscore/HostLookup.cc | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst index d52c0afb392..5e605988cb8 100644 --- a/doc/admin-guide/files/records.config.en.rst +++ b/doc/admin-guide/files/records.config.en.rst @@ -331,7 +331,7 @@ Thread Variables accept_threads exec_thread.listen Effect ==================== ====================== ===================== ``0`` ``0`` All worker threads accept new connections and share listen fd. - ``1`` ``0`` New conections are accepted on a dedicated accept thread and distributed to worker threads in round robin fashion. + ``1`` ``0`` New connections are accepted on a dedicated accept thread and distributed to worker threads in round robin fashion. ``0`` ``1`` All worker threads listen on the same port using SO_REUSEPORT. Each thread has its own listen fd and new connections are accepted on all the threads. ==================== ====================== ===================== @@ -2462,7 +2462,10 @@ DNS .. ts:cv:: CONFIG proxy.config.dns.nameservers STRING NULL :reloadable: - The DNS servers. + The DNS servers. Note that this does not override :ts:cv:`proxy.config.dns.resolv_conf`. + That is, the contents of the file listed in :ts:cv:`proxy.config.dns.resolv_conf` will + be appended to the list of nameservers specified here. To prevent this, a bogus file + can be listed there. .. ts:cv:: CONFIG proxy.config.srv_enabled INT 0 :reloadable: diff --git a/doc/admin-guide/plugins/cachekey.en.rst b/doc/admin-guide/plugins/cachekey.en.rst index ff8e4352750..3945a4398e4 100644 --- a/doc/admin-guide/plugins/cachekey.en.rst +++ b/doc/admin-guide/plugins/cachekey.en.rst @@ -56,7 +56,7 @@ The plugin manipulates the `cache key` by default. If `parent selection URL` man * ``--key-type=`` (default: ``cache_key``) - list of ``cache_key`` or ``parent_selection_url``, if multiple ``--key-type`` options are specified then all values are combined together. An instance of this plugin can be used for applying manipulations to `cache key`, `parent selection URL` or both depending on the need. See `simultaneous cache key and parent selection URL manipulation`_ -for examples of how to apply the **same** set of manupulations to both targets with a single plugin instance or applying **diferent** sets of manipulations to each target using separate plugin instances. +for examples of how to apply the **same** set of manipulations to both targets with a single plugin instance or applying **different** sets of manipulations to each target using separate plugin instances. Cache key structure and related plugin parameters diff --git a/src/tscore/HostLookup.cc b/src/tscore/HostLookup.cc index 22ee6648424..79c509583ef 100644 --- a/src/tscore/HostLookup.cc +++ b/src/tscore/HostLookup.cc @@ -211,7 +211,7 @@ struct CharIndexBlock { // ----------- ------------ // 0 | | | | | | // . | | | | | | -// CharIndexBlock . | | | | | | +// CharIndexBlock . | | | | | | // ---------- . | | | | | | // 0 | | | . | | | |-->23| ptr| 0 | (ptr is to the // . | | | |-------->25| 0 | -----| | | | hostBranch for From 0932b0ae864924a644baa66ab6b51aef92a78b67 Mon Sep 17 00:00:00 2001 From: Silvano Cerza Date: Thu, 10 Oct 2019 16:57:40 +0200 Subject: [PATCH 110/718] Rewrote remap_stats plugin to use C++ (cherry picked from commit a42e61f725d52c6c976c0ab1a03bfe2e77b95c69) --- plugins/experimental/remap_stats/Makefile.inc | 2 +- .../{remap_stats.c => remap_stats.cc} | 136 +++++++----------- 2 files changed, 56 insertions(+), 82 deletions(-) rename plugins/experimental/remap_stats/{remap_stats.c => remap_stats.cc} (65%) diff --git a/plugins/experimental/remap_stats/Makefile.inc b/plugins/experimental/remap_stats/Makefile.inc index 9cf318ea159..ce922580071 100644 --- a/plugins/experimental/remap_stats/Makefile.inc +++ b/plugins/experimental/remap_stats/Makefile.inc @@ -17,4 +17,4 @@ pkglib_LTLIBRARIES += experimental/remap_stats/remap_stats.la experimental_remap_stats_remap_stats_la_SOURCES = \ - experimental/remap_stats/remap_stats.c + experimental/remap_stats/remap_stats.cc diff --git a/plugins/experimental/remap_stats/remap_stats.c b/plugins/experimental/remap_stats/remap_stats.cc similarity index 65% rename from plugins/experimental/remap_stats/remap_stats.c rename to plugins/experimental/remap_stats/remap_stats.cc index 79c931598b8..43df970dd5d 100644 --- a/plugins/experimental/remap_stats/remap_stats.c +++ b/plugins/experimental/remap_stats/remap_stats.cc @@ -21,57 +21,42 @@ #include "tscore/ink_config.h" #include "tscore/ink_defs.h" +#include "tscore/BufferWriter.h" #include "ts/ts.h" -#include -#include -#include -#include -#include -#include + +#include +#include +#include #define PLUGIN_NAME "remap_stats" #define DEBUG_TAG PLUGIN_NAME #define MAX_STAT_LENGTH (1 << 8) -typedef struct { +struct config_t { bool post_remap_host; int txn_slot; TSStatPersistence persist_type; TSMutex stat_creation_mutex; -} config_t; +}; // From "core".... sigh, but we need it for now at least. extern int max_records_entries; static void -stat_add(char *name, TSMgmtInt amount, TSStatPersistence persist_type, TSMutex create_mutex) +stat_add(const char *name, TSMgmtInt amount, TSStatPersistence persist_type, TSMutex create_mutex) { int stat_id = -1; - ENTRY search, *result = NULL; - static __thread struct hsearch_data stat_cache; - static __thread bool hash_init = false; - - if (unlikely(!hash_init)) { - // NOLINTNEXTLINE - hcreate_r(max_records_entries << 1, &stat_cache); // This is weird, but oh well. - hash_init = true; - TSDebug(DEBUG_TAG, "stat cache hash init"); - } - - search.key = name; - search.data = 0; - // NOLINTNEXTLINE - hsearch_r(search, FIND, &result, &stat_cache); + static thread_local std::unordered_map hash; - if (unlikely(result == NULL)) { + if (unlikely(hash.find(name) == hash.cend())) { // This is an unlikely path because we most likely have the stat cached // so this mutex won't be much overhead and it fixes a race condition // in the RecCore. Hopefully this can be removed in the future. TSMutexLock(create_mutex); - if (TS_ERROR == TSStatFindName((const char *)name, &stat_id)) { - stat_id = TSStatCreate((const char *)name, TS_RECORDDATATYPE_INT, persist_type, TS_STAT_SYNC_SUM); + if (TS_ERROR == TSStatFindName(name, &stat_id)) { + stat_id = TSStatCreate(name, TS_RECORDDATATYPE_INT, persist_type, TS_STAT_SYNC_SUM); if (stat_id == TS_ERROR) { TSDebug(DEBUG_TAG, "Error creating stat_name: %s", name); } else { @@ -81,14 +66,11 @@ stat_add(char *name, TSMgmtInt amount, TSStatPersistence persist_type, TSMutex c TSMutexUnlock(create_mutex); if (stat_id >= 0) { - search.key = TSstrdup(name); - search.data = (void *)((intptr_t)stat_id); - // NOLINTNEXTLINE - hsearch_r(search, ENTER, &result, &stat_cache); + hash.emplace(name, stat_id); TSDebug(DEBUG_TAG, "Cached stat_name: %s stat_id: %d", name, stat_id); } } else { - stat_id = (int)((intptr_t)result->data); + stat_id = hash.at(name); } if (likely(stat_id >= 0)) { @@ -130,7 +112,7 @@ handle_read_req_hdr(TSCont cont, TSEvent event ATS_UNUSED, void *edata) config_t *config; void *txnd; - config = (config_t *)TSContDataGet(cont); + config = static_cast(TSContDataGet(cont)); txnd = (void *)get_effective_host(txn); // low bit left 0 because we do not know that remap succeeded yet TSHttpTxnArgSet(txn, config->txn_slot, txnd); @@ -142,11 +124,11 @@ handle_read_req_hdr(TSCont cont, TSEvent event ATS_UNUSED, void *edata) static int handle_post_remap(TSCont cont, TSEvent event ATS_UNUSED, void *edata) { - TSHttpTxn txn = (TSHttpTxn)edata; + TSHttpTxn txn = static_cast(edata); config_t *config; void *txnd = (void *)0x01; // low bit 1 because we are post remap and thus success - config = (config_t *)TSContDataGet(cont); + config = static_cast(TSContDataGet(cont)); if (config->post_remap_host) { TSHttpTxnArgSet(txn, config->txn_slot, txnd); @@ -160,29 +142,35 @@ handle_post_remap(TSCont cont, TSEvent event ATS_UNUSED, void *edata) return 0; } -#define CREATE_STAT_NAME(s, h, b) snprintf(s, MAX_STAT_LENGTH, "plugin.%s.%s.%s", PLUGIN_NAME, h, b) +static void +create_stat_name(ts::LocalBufferWriter &stat_name, std::string_view h, std::string_view b) +{ + stat_name.reset().reduce(1); + stat_name.print("plugin.{}.{}.{}", PLUGIN_NAME, h, b); + stat_name.extend(1).write('\0'); +} static int handle_txn_close(TSCont cont, TSEvent event ATS_UNUSED, void *edata) { - TSHttpTxn txn = (TSHttpTxn)edata; + TSHttpTxn txn = static_cast(edata); config_t *config; void *txnd; int status_code = 0; TSMBuffer buf; TSMLoc hdr_loc; uint64_t out_bytes, in_bytes; - char *remap, *hostname; - char *unknown = "unknown"; - char stat_name[MAX_STAT_LENGTH]; + std::string_view remap, hostname; + std::string_view unknown("unknown"); + ts::LocalBufferWriter stat_name; - config = (config_t *)TSContDataGet(cont); + config = static_cast(TSContDataGet(cont)); txnd = TSHttpTxnArgGet(txn, config->txn_slot); - hostname = (char *)((uintptr_t)txnd & (~((uintptr_t)0x01))); // Get hostname + hostname = std::string_view(reinterpret_cast(reinterpret_cast(txnd) & ~0x01)); // Get hostname if (txnd) { - if ((uintptr_t)txnd & 0x01) // remap succeeded? + if (reinterpret_cast(txnd) & 0x01) // remap succeeded? { if (!config->post_remap_host) { remap = hostname; @@ -190,51 +178,45 @@ handle_txn_close(TSCont cont, TSEvent event ATS_UNUSED, void *edata) remap = get_effective_host(txn); } - if (!remap) { + if (remap.empty()) { remap = unknown; } in_bytes = TSHttpTxnClientReqHdrBytesGet(txn); in_bytes += TSHttpTxnClientReqBodyBytesGet(txn); - CREATE_STAT_NAME(stat_name, remap, "in_bytes"); - stat_add(stat_name, (TSMgmtInt)in_bytes, config->persist_type, config->stat_creation_mutex); + create_stat_name(stat_name, remap, "in_bytes"); + stat_add(stat_name.data(), static_cast(in_bytes), config->persist_type, config->stat_creation_mutex); out_bytes = TSHttpTxnClientRespHdrBytesGet(txn); out_bytes += TSHttpTxnClientRespBodyBytesGet(txn); - CREATE_STAT_NAME(stat_name, remap, "out_bytes"); - stat_add(stat_name, (TSMgmtInt)out_bytes, config->persist_type, config->stat_creation_mutex); + create_stat_name(stat_name, remap, "out_bytes"); + stat_add(stat_name.data(), static_cast(out_bytes), config->persist_type, config->stat_creation_mutex); if (TSHttpTxnClientRespGet(txn, &buf, &hdr_loc) == TS_SUCCESS) { - status_code = (int)TSHttpHdrStatusGet(buf, hdr_loc); + status_code = static_cast(TSHttpHdrStatusGet(buf, hdr_loc)); TSHandleMLocRelease(buf, TS_NULL_MLOC, hdr_loc); if (status_code < 200) { - CREATE_STAT_NAME(stat_name, remap, "status_other"); + create_stat_name(stat_name, remap, "status_other"); } else if (status_code <= 299) { - CREATE_STAT_NAME(stat_name, remap, "status_2xx"); + create_stat_name(stat_name, remap, "status_2xx"); } else if (status_code <= 399) { - CREATE_STAT_NAME(stat_name, remap, "status_3xx"); + create_stat_name(stat_name, remap, "status_3xx"); } else if (status_code <= 499) { - CREATE_STAT_NAME(stat_name, remap, "status_4xx"); + create_stat_name(stat_name, remap, "status_4xx"); } else if (status_code <= 599) { - CREATE_STAT_NAME(stat_name, remap, "status_5xx"); + create_stat_name(stat_name, remap, "status_5xx"); } else { - CREATE_STAT_NAME(stat_name, remap, "status_other"); + create_stat_name(stat_name, remap, "status_other"); } - stat_add(stat_name, 1, config->persist_type, config->stat_creation_mutex); + stat_add(stat_name.data(), 1, config->persist_type, config->stat_creation_mutex); } else { - CREATE_STAT_NAME(stat_name, remap, "status_unknown"); - stat_add(stat_name, 1, config->persist_type, config->stat_creation_mutex); - } - - if (remap != unknown) { - TSfree(remap); + create_stat_name(stat_name, remap, "status_unknown"); + stat_add(stat_name.data(), 1, config->persist_type, config->stat_creation_mutex); } - } else if (hostname) { - TSfree(hostname); } } @@ -248,7 +230,6 @@ TSPluginInit(int argc, const char *argv[]) { TSPluginRegistrationInfo info; TSCont pre_remap_cont, post_remap_cont, global_cont; - config_t *config; info.plugin_name = PLUGIN_NAME; info.vendor_name = "Apache Software Foundation"; @@ -262,28 +243,21 @@ TSPluginInit(int argc, const char *argv[]) TSDebug(DEBUG_TAG, "Plugin registration succeeded"); } - config = TSmalloc(sizeof(config_t)); + auto config = new config_t; config->post_remap_host = false; config->persist_type = TS_STAT_NON_PERSISTENT; config->stat_creation_mutex = TSMutexCreate(); if (argc > 1) { - int c; - static const struct option longopts[] = { - {"post-remap-host", no_argument, NULL, 'P'}, {"persistent", no_argument, NULL, 'p'}, {NULL, 0, NULL, 0}}; - - while ((c = getopt_long(argc, (char *const *)argv, "Pp", longopts, NULL)) != -1) { - switch (c) { - case 'P': + // Argument parser + for (auto i = 0; i < argc; i++) { + const std::string arg(argv[i]); + if (arg == "-P" || arg == "--post-remap-host") { config->post_remap_host = true; TSDebug(DEBUG_TAG, "Using post remap hostname"); - break; - case 'p': + } else if (arg == "-p" || arg == "--persistent") { config->persist_type = TS_STAT_PERSISTENT; TSDebug(DEBUG_TAG, "Using persistent stats"); - break; - default: - break; } } } @@ -292,16 +266,16 @@ TSPluginInit(int argc, const char *argv[]) if (!config->post_remap_host) { pre_remap_cont = TSContCreate(handle_read_req_hdr, NULL); - TSContDataSet(pre_remap_cont, (void *)config); + TSContDataSet(pre_remap_cont, static_cast(config)); TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, pre_remap_cont); } post_remap_cont = TSContCreate(handle_post_remap, NULL); - TSContDataSet(post_remap_cont, (void *)config); + TSContDataSet(post_remap_cont, static_cast(config)); TSHttpHookAdd(TS_HTTP_POST_REMAP_HOOK, post_remap_cont); global_cont = TSContCreate(handle_txn_close, NULL); - TSContDataSet(global_cont, (void *)config); + TSContDataSet(global_cont, static_cast(config)); TSHttpHookAdd(TS_HTTP_TXN_CLOSE_HOOK, global_cont); TSDebug(DEBUG_TAG, "Init complete"); From f6a32a12eb8a709af08559d6cc1a543b86854fbd Mon Sep 17 00:00:00 2001 From: Phil Sorber Date: Tue, 29 Oct 2019 11:24:10 -0600 Subject: [PATCH 111/718] Issue #4294: Handle return value of SSL_write() properly. (cherry picked from commit 5083cf97b9ab6a910c288e745e0569d4c3d02f19) --- tests/gold_tests/tls/ssl-post.c | 6 +++--- tools/http_load/http_load.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/gold_tests/tls/ssl-post.c b/tests/gold_tests/tls/ssl-post.c index 35ec0092874..dcb7ace554e 100644 --- a/tests/gold_tests/tls/ssl-post.c +++ b/tests/gold_tests/tls/ssl-post.c @@ -134,15 +134,15 @@ spawn_same_session_send(void *arg) ret = select(sfd + 1, &reads, &writes, NULL, NULL); if (FD_ISSET(sfd, &reads) || FD_ISSET(sfd, &writes)) { ret = write_ret = SSL_write(ssl, req_buf, strlen(req_buf)); - if (write_ret >= 0) + if (write_ret > 0) post_write_ret = SSL_write(ssl, post_buf, sizeof(post_buf)); } } - while (write_ret < 0) { + while (write_ret <= 0) { write_ret = SSL_write(ssl, req_buf, strlen(req_buf)); } - while (post_write_ret < 0) { + while (post_write_ret <= 0) { post_write_ret = SSL_write(ssl, post_buf, sizeof(post_buf)); } diff --git a/tools/http_load/http_load.c b/tools/http_load/http_load.c index da8c74c6bff..59bd5dd6bae 100644 --- a/tools/http_load/http_load.c +++ b/tools/http_load/http_load.c @@ -1098,7 +1098,7 @@ start_socket(int url_num, int cnum, struct timeval *nowP) r = SSL_write(connections[cnum].ssl, urls[url_num].buf, urls[url_num].buf_bytes); else r = write(connections[cnum].conn_fd, urls[url_num].buf, urls[url_num].buf_bytes); - if (r < 0) { + if (r <= 0) { perror(urls[url_num].url_str); connections[cnum].reusable = 0; close_connection(cnum); @@ -1216,7 +1216,7 @@ handle_connect(int cnum, struct timeval *nowP, int double_check) r = SSL_write(connections[cnum].ssl, urls[url_num].buf, urls[url_num].buf_bytes); else r = write(connections[cnum].conn_fd, urls[url_num].buf, urls[url_num].buf_bytes); - if (r < 0) { + if (r <= 0) { perror(urls[url_num].url_str); connections[cnum].reusable = 0; close_connection(cnum); From 0bb82b0aef43e49ca50b83247677a4ffcdc0c65e Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Mon, 4 Nov 2019 09:25:37 -0700 Subject: [PATCH 112/718] Removes the records.config.shadow alternative config file In addition, cleans up the usage and definitions of "records.config". (cherry picked from commit bbcffa075ede77058dbb713d8c9bc42e2f0f9e81) --- include/tscore/Filenames.h | 5 +++++ lib/records/P_RecDefs.h | 4 ---- lib/records/RecCore.cc | 13 +++++-------- mgmt/LocalManager.cc | 3 ++- src/traffic_layout/info.cc | 2 +- src/traffic_manager/AddConfigFilesHere.cc | 2 +- src/traffic_manager/traffic_manager.cc | 3 ++- src/tscore/Filenames.cc | 5 +++++ src/tscore/unit_tests/test_layout.cc | 5 +++-- 9 files changed, 24 insertions(+), 18 deletions(-) diff --git a/include/tscore/Filenames.h b/include/tscore/Filenames.h index 67065fb968e..6c880e02d52 100644 --- a/include/tscore/Filenames.h +++ b/include/tscore/Filenames.h @@ -24,3 +24,8 @@ /////////////////////////////////////////////////////////////////// // Configuration file names extern const char *STORAGE_CONF_FILENAME; +extern const char *RECORDS_CONF_FILENAME; + +/////////////////////////////////////////////////////////////////// +// Various other file names +extern const char *RECORDS_STATS_FILE; diff --git a/lib/records/P_RecDefs.h b/lib/records/P_RecDefs.h index 0aa4c09d62e..e987e636b7a 100644 --- a/lib/records/P_RecDefs.h +++ b/lib/records/P_RecDefs.h @@ -25,10 +25,6 @@ #include "I_RecDefs.h" -#define REC_CONFIG_FILE "records.config" -#define REC_SHADOW_EXT ".shadow" -#define REC_RAW_STATS_FILE "records.snap" - #define REC_MESSAGE_ELE_MAGIC 0xF00DF00D // We need at least this many internal record entries for our configurations and metrics. Any diff --git a/lib/records/RecCore.cc b/lib/records/RecCore.cc index f8b832c4db3..1310082d2f9 100644 --- a/lib/records/RecCore.cc +++ b/lib/records/RecCore.cc @@ -24,6 +24,7 @@ #include "tscore/ink_platform.h" #include "tscore/ink_memory.h" #include "tscore/ink_string.h" +#include "tscore/Filenames.h" #include "RecordsConfig.h" #include "P_RecFile.h" @@ -218,14 +219,10 @@ RecCoreInit(RecModeT mode_type, Diags *_diags) ink_mutex_init(&g_rec_config_lock); - g_rec_config_fpath = ats_stringdup(RecConfigReadConfigPath(nullptr, REC_CONFIG_FILE REC_SHADOW_EXT)); + g_rec_config_fpath = ats_stringdup(RecConfigReadConfigPath(nullptr, RECORDS_CONF_FILENAME)); if (RecFileExists(g_rec_config_fpath) == REC_ERR_FAIL) { - ats_free(const_cast(g_rec_config_fpath)); - g_rec_config_fpath = ats_stringdup(RecConfigReadConfigPath(nullptr, REC_CONFIG_FILE)); - if (RecFileExists(g_rec_config_fpath) == REC_ERR_FAIL) { - RecLog(DL_Warning, "Could not find '%s', system will run with defaults\n", REC_CONFIG_FILE); - file_exists = false; - } + RecLog(DL_Warning, "Could not find '%s', system will run with defaults\n", RECORDS_CONF_FILENAME); + file_exists = false; } if (file_exists) { @@ -1260,7 +1257,7 @@ std::string RecConfigReadPersistentStatsPath() { std::string rundir(RecConfigReadRuntimeDir()); - return Layout::relative_to(rundir, REC_RAW_STATS_FILE); + return Layout::relative_to(rundir, RECORDS_STATS_FILE); } void diff --git a/mgmt/LocalManager.cc b/mgmt/LocalManager.cc index 946cf772969..369cfd66e3e 100644 --- a/mgmt/LocalManager.cc +++ b/mgmt/LocalManager.cc @@ -38,6 +38,7 @@ #include "tscpp/util/TextView.h" #include "tscore/BufferWriter.h" #include "tscore/bwf_std_format.h" +#include "tscore/Filenames.h" #if TS_USE_POSIX_CAP #include @@ -749,7 +750,7 @@ LocalManager::processEventQueue() // check if we have a local file update if (mh->msg_id == MGMT_EVENT_CONFIG_FILE_UPDATE) { // records.config - if (!(strcmp(payload.begin(), REC_CONFIG_FILE))) { + if (!(strcmp(payload.begin(), RECORDS_CONF_FILENAME))) { if (RecReadConfigFile() != REC_ERR_OKAY) { mgmt_elog(errno, "[fileUpdated] Config update failed for records.config\n"); } else { diff --git a/src/traffic_layout/info.cc b/src/traffic_layout/info.cc index 51aba61a9ac..64afb6110db 100644 --- a/src/traffic_layout/info.cc +++ b/src/traffic_layout/info.cc @@ -155,7 +155,7 @@ produce_layout(bool json) print_var("PLUGINDIR", RecConfigReadPluginDir(), json); print_var("INCLUDEDIR", Layout::get()->includedir, json); - print_var("records.config", RecConfigReadConfigPath(nullptr, REC_CONFIG_FILE), json); + print_var(RECORDS_CONF_FILENAME, RecConfigReadConfigPath(nullptr, RECORDS_CONF_FILENAME), json); print_var("remap.config", RecConfigReadConfigPath("proxy.config.url_remap.filename"), json); print_var("plugin.config", RecConfigReadConfigPath(nullptr, "plugin.config"), json); print_var("ssl_multicert.config", RecConfigReadConfigPath("proxy.config.ssl.server.multicert.filename"), json); diff --git a/src/traffic_manager/AddConfigFilesHere.cc b/src/traffic_manager/AddConfigFilesHere.cc index de33eb6aad6..553c050d00c 100644 --- a/src/traffic_manager/AddConfigFilesHere.cc +++ b/src/traffic_manager/AddConfigFilesHere.cc @@ -76,7 +76,7 @@ initializeRegistry() registerFile("proxy.config.log.config.filename", "logging.yaml"); registerFile("", STORAGE_CONF_FILENAME); registerFile("proxy.config.socks.socks_config_file", "socks.config"); - registerFile("records.config", "records.config"); + registerFile(RECORDS_CONF_FILENAME, RECORDS_CONF_FILENAME); registerFile("proxy.config.cache.control.filename", "cache.config"); registerFile("proxy.config.cache.ip_allow.filename", "ip_allow.yaml"); registerFile("proxy.config.http.parent_proxy.file", "parent.config"); diff --git a/src/traffic_manager/traffic_manager.cc b/src/traffic_manager/traffic_manager.cc index e6f14e62e9a..ccbf1626267 100644 --- a/src/traffic_manager/traffic_manager.cc +++ b/src/traffic_manager/traffic_manager.cc @@ -28,6 +28,7 @@ #include "tscore/ink_args.h" #include "tscore/ink_syslog.h" #include "tscore/runroot.h" +#include "tscore/Filenames.h" #include "WebMgmtUtils.h" #include "MgmtUtils.h" @@ -90,7 +91,7 @@ static char bind_stderr[512] = ""; static const char *mgmt_path = nullptr; // By default, set the current directory as base -static const char *recs_conf = "records.config"; +static const char *recs_conf = RECORDS_CONF_FILENAME; static int fds_limit; diff --git a/src/tscore/Filenames.cc b/src/tscore/Filenames.cc index cd296c8e108..018804c7ffe 100644 --- a/src/tscore/Filenames.cc +++ b/src/tscore/Filenames.cc @@ -22,3 +22,8 @@ /////////////////////////////////////////////////////////////////// // Configuration file names const char *STORAGE_CONF_FILENAME = "storage.config"; +const char *RECORDS_CONF_FILENAME = "records.config"; + +/////////////////////////////////////////////////////////////////// +// Various other file names +const char *RECORDS_STATS_FILE = "records.snap"; diff --git a/src/tscore/unit_tests/test_layout.cc b/src/tscore/unit_tests/test_layout.cc index e478f137c3d..bd25517b798 100644 --- a/src/tscore/unit_tests/test_layout.cc +++ b/src/tscore/unit_tests/test_layout.cc @@ -23,6 +23,7 @@ #include "tscore/I_Layout.h" #include "tscore/ink_platform.h" +#include "tscore/Filenames.h" std::string append_slash(const char *path) @@ -79,8 +80,8 @@ TEST_CASE("relative to test", "[relative_to]") // relative to (4 parameters) char config_file[PATH_NAME_MAX]; - Layout::relative_to(config_file, sizeof(config_file), Layout::get()->sysconfdir, "records.config"); - std::string a = Layout::relative_to(Layout::get()->sysconfdir, "records.config"); + Layout::relative_to(config_file, sizeof(config_file), Layout::get()->sysconfdir, RECORDS_CONF_FILENAME); + std::string a = Layout::relative_to(Layout::get()->sysconfdir, RECORDS_CONF_FILENAME); std::string b = config_file; REQUIRE(a == b); } From 460d1f25a771024e056b85e2d96cab0a7d5893e7 Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Tue, 5 Nov 2019 14:21:15 -0700 Subject: [PATCH 113/718] Updated to clang-format v9.0.0 --- .clang-format | 40 +++++++++++------ .../plugins/c-api/cache_scan/cache_scan.cc | 2 +- example/plugins/c-api/intercept/intercept.cc | 2 +- example/plugins/c-api/passthru/passthru.cc | 2 +- example/plugins/c-api/statistic/statistic.cc | 2 +- .../AsyncHttpFetchStreaming.cc | 2 +- .../plugins/cpp-api/intercept/intercept.cc | 2 +- include/tscore/BufferWriter.h | 4 +- include/tscore/Errata.h | 4 +- include/tscore/IpMap.h | 8 ++-- include/tscore/RbTree.h | 4 +- include/tscore/ink_inet.h | 2 +- include/wccp/Wccp.h | 2 +- iocore/cache/CacheDir.cc | 3 +- iocore/cache/CacheTest.cc | 45 ++++++++++--------- iocore/net/quic/Mock.h | 5 +-- lib/records/RecCore.cc | 15 ++++--- mgmt/WebMgmtUtils.cc | 5 +-- mgmt/api/INKMgmtAPI.cc | 2 +- plugins/experimental/metalink/metalink.cc | 2 +- plugins/experimental/slice/HttpHeader.h | 2 +- plugins/experimental/slice/Range.cc | 2 +- plugins/experimental/slice/transfer.cc | 3 +- plugins/generator/generator.cc | 5 +-- proxy/ControlBase.h | 4 +- proxy/http/Http1Transaction.cc | 3 +- proxy/logging/LogConfig.cc | 3 +- src/traffic_server/traffic_server.cc | 3 +- src/tscore/BufferWriterFormat.cc | 45 ++++++++++--------- src/tscore/EventNotify.cc | 3 +- src/tscore/IpMap.cc | 2 +- src/tscore/ink_res_mkquery.cc | 17 +++---- src/tscore/test_atomic.cc | 2 +- src/tscore/test_freelist.cc | 2 +- src/wccp/WccpLocal.h | 34 +++++++------- tools/clang-format.sh | 6 +-- 36 files changed, 152 insertions(+), 137 deletions(-) diff --git a/.clang-format b/.clang-format index a70897438e1..292f1cc83dc 100644 --- a/.clang-format +++ b/.clang-format @@ -2,42 +2,48 @@ Language: Cpp AccessModifierOffset: -2 AlignAfterOpenBracket: Align +AlignConsecutiveMacros: false AlignConsecutiveAssignments: true AlignConsecutiveDeclarations: false AlignEscapedNewlines: Left AlignOperands: true AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: false AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: Inline -AllowShortIfStatementsOnASingleLine: false +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: All AlwaysBreakAfterReturnType: AllDefinitions AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: false +AlwaysBreakTemplateDeclarations: MultiLine BinPackArguments: true BinPackParameters: true BraceWrapping: + AfterCaseLabel: false AfterClass: true - AfterControlStatement: true - AfterEnum: true + AfterControlStatement: false + AfterEnum: false AfterFunction: true AfterNamespace: true AfterObjCDeclaration: false - AfterStruct: true - AfterUnion: true - AfterExternBlock: true + AfterStruct: false + AfterUnion: false + AfterExternBlock: false BeforeCatch: false BeforeElse: false IndentBraces: false - SplitEmptyFunction: false - SplitEmptyRecord: false - SplitEmptyNamespace: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true BreakBeforeBinaryOperators: None BreakBeforeBraces: Linux BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon BreakBeforeTernaryOperators: false BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: BeforeColon @@ -81,6 +87,7 @@ MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 NamespaceIndentation: Inner +ObjCBinPackProtocolList: Auto ObjCBlockIndentWidth: 2 ObjCSpaceAfterProperty: true ObjCSpaceBeforeProtocolList: false @@ -89,20 +96,22 @@ PenaltyBreakBeforeFirstCallParameter: 19 PenaltyBreakComment: 30000 PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 200 PointerAlignment: Right -RawStringFormats: - - Delimiter: pb - Language: TextProto - BasedOnStyle: Mozilla ReflowComments: true SortIncludes: false SortUsingDeclarations: false SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 SpacesInAngles: false @@ -111,6 +120,9 @@ SpacesInCStyleCastParentheses: false SpacesInParentheses: false SpacesInSquareBrackets: false Standard: Cpp11 +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION TabWidth: 8 UseTab: Never ... diff --git a/example/plugins/c-api/cache_scan/cache_scan.cc b/example/plugins/c-api/cache_scan/cache_scan.cc index dfdf4436100..0155bdd7594 100644 --- a/example/plugins/c-api/cache_scan/cache_scan.cc +++ b/example/plugins/c-api/cache_scan/cache_scan.cc @@ -491,7 +491,7 @@ cache_print_plugin(TSCont contp, TSEvent event, void *edata) //---------------------------------------------------------------------------- void -TSPluginInit(int /* argc ATS_UNUSED */, const char * /* argv ATS_UNUSED */ []) +TSPluginInit(int /* argc ATS_UNUSED */, const char * /* argv ATS_UNUSED */[]) { TSPluginRegistrationInfo info; diff --git a/example/plugins/c-api/intercept/intercept.cc b/example/plugins/c-api/intercept/intercept.cc index c793e19b96f..602857ed0b6 100644 --- a/example/plugins/c-api/intercept/intercept.cc +++ b/example/plugins/c-api/intercept/intercept.cc @@ -534,7 +534,7 @@ InterceptTxnHook(TSCont contp, TSEvent event, void *edata) } void -TSPluginInit(int /* argc */, const char * /* argv */ []) +TSPluginInit(int /* argc */, const char * /* argv */[]) { TSPluginRegistrationInfo info; diff --git a/example/plugins/c-api/passthru/passthru.cc b/example/plugins/c-api/passthru/passthru.cc index 8912e2961be..887dac000ca 100644 --- a/example/plugins/c-api/passthru/passthru.cc +++ b/example/plugins/c-api/passthru/passthru.cc @@ -315,7 +315,7 @@ PassthruListen() } void -TSPluginInit(int /* argc */, const char * /* argv */ []) +TSPluginInit(int /* argc */, const char * /* argv */[]) { TSPluginRegistrationInfo info = {PLUGIN_NAME, "Apache Software Foundation", "dev@trafficserver.apache.org"}; diff --git a/example/plugins/c-api/statistic/statistic.cc b/example/plugins/c-api/statistic/statistic.cc index 09ee0477bda..f76f736a922 100644 --- a/example/plugins/c-api/statistic/statistic.cc +++ b/example/plugins/c-api/statistic/statistic.cc @@ -36,7 +36,7 @@ #define PLUGIN_NAME "statistics" void -TSPluginInit(int /* argc */, const char * /* argv */ []) +TSPluginInit(int /* argc */, const char * /* argv */[]) { TSPluginRegistrationInfo info; diff --git a/example/plugins/cpp-api/async_http_fetch_streaming/AsyncHttpFetchStreaming.cc b/example/plugins/cpp-api/async_http_fetch_streaming/AsyncHttpFetchStreaming.cc index f953ab08259..d7f4f27062e 100644 --- a/example/plugins/cpp-api/async_http_fetch_streaming/AsyncHttpFetchStreaming.cc +++ b/example/plugins/cpp-api/async_http_fetch_streaming/AsyncHttpFetchStreaming.cc @@ -80,7 +80,7 @@ class InterceptInstaller : public GlobalPlugin }; void -TSPluginInit(int /* argc ATS_UNUSED */, const char * /* argv ATS_UNUSED */ []) +TSPluginInit(int /* argc ATS_UNUSED */, const char * /* argv ATS_UNUSED */[]) { if (!RegisterGlobalPlugin("CPP_Example_AsyncHttpFetchStreaming", "apache", "dev@trafficserver.apache.org")) { return; diff --git a/example/plugins/cpp-api/intercept/intercept.cc b/example/plugins/cpp-api/intercept/intercept.cc index da615cb077b..332f1047fd5 100644 --- a/example/plugins/cpp-api/intercept/intercept.cc +++ b/example/plugins/cpp-api/intercept/intercept.cc @@ -58,7 +58,7 @@ class InterceptInstaller : public GlobalPlugin }; void -TSPluginInit(int /* argc ATS_UNUSED */, const char * /* argv ATS_UNUSED */ []) +TSPluginInit(int /* argc ATS_UNUSED */, const char * /* argv ATS_UNUSED */[]) { if (!RegisterGlobalPlugin("CPP_Example_Intercept", "apache", "dev@trafficserver.apache.org")) { return; diff --git a/include/tscore/BufferWriter.h b/include/tscore/BufferWriter.h index 3e693a30b2e..103af0b62b8 100644 --- a/include/tscore/BufferWriter.h +++ b/include/tscore/BufferWriter.h @@ -529,9 +529,7 @@ namespace bw_fmt /// @a TUPLE. Due to language limitations it cannot be done directly. The formatters can be /// accessed via standard array access in contrast to templated tuple access. The actual array is /// static and therefore at run time the only operation is loading the address of the array. - template - ArgFormatterSignature * - Get_Arg_Formatter_Array(std::index_sequence) + template ArgFormatterSignature *Get_Arg_Formatter_Array(std::index_sequence) { static ArgFormatterSignature fa[sizeof...(N)] = {&bw_fmt::Arg_Formatter...}; return fa; diff --git a/include/tscore/Errata.h b/include/tscore/Errata.h index 6bc5e3a3441..b28a291c837 100644 --- a/include/tscore/Errata.h +++ b/include/tscore/Errata.h @@ -336,7 +336,7 @@ class Errata int indent, ///< Additional indention per line for messages. int shift, ///< Additional @a indent for nested @c Errata. char const *lead ///< Leading text for nested @c Errata. - ) const; + ) const; /// Simple formatted output to fixed sized buffer. /// @return Number of characters written to @a buffer. size_t write(char *buffer, ///< Output buffer. @@ -345,7 +345,7 @@ class Errata int indent, ///< Additional indention per line for messages. int shift, ///< Additional @a indent for nested @c Errata. char const *lead ///< Leading text for nested @c Errata. - ) const; + ) const; protected: /// Construct from implementation pointer. diff --git a/include/tscore/IpMap.h b/include/tscore/IpMap.h index 50a9fbe2434..d84dbc435d0 100644 --- a/include/tscore/IpMap.h +++ b/include/tscore/IpMap.h @@ -306,7 +306,7 @@ class IpMap */ bool contains(sockaddr const *target, ///< Search target (network order). void **ptr = nullptr ///< Client data return. - ) const; + ) const; /** Test for membership. @@ -318,7 +318,7 @@ class IpMap */ bool contains(in_addr_t target, ///< Search target (network order). void **ptr = nullptr ///< Client data return. - ) const; + ) const; /** Test for membership. @@ -330,7 +330,7 @@ class IpMap */ bool contains(IpEndpoint const *target, ///< Search target (network order). void **ptr = nullptr ///< Client data return. - ) const; + ) const; /** Test for membership. @@ -342,7 +342,7 @@ class IpMap */ bool contains(IpAddr const &target, ///< Search target (network order). void **ptr = nullptr ///< Client data return. - ) const; + ) const; /** Remove all addresses from the map. diff --git a/include/tscore/RbTree.h b/include/tscore/RbTree.h index dcb52f58ec6..446e1ed8a6e 100644 --- a/include/tscore/RbTree.h +++ b/include/tscore/RbTree.h @@ -52,7 +52,7 @@ namespace detail /// @return The child in the direction @a d if it exists, /// @c NULL if not. self *getChild(Direction d //!< The direction of the desired child - ) const; + ) const; /** Determine which child a node is @return @c LEFT if @a n is the left child, @@ -61,7 +61,7 @@ namespace detail */ Direction getChildDirection(self *const &n //!< The presumed child node - ) const + ) const { return (n == _left) ? LEFT : (n == _right) ? RIGHT : NONE; } diff --git a/include/tscore/ink_inet.h b/include/tscore/ink_inet.h index 70cd47ca78e..efd67c04b93 100644 --- a/include/tscore/ink_inet.h +++ b/include/tscore/ink_inet.h @@ -1214,7 +1214,7 @@ struct IpAddr { */ char *toString(char *dest, ///< [out] Destination string buffer. size_t len ///< [in] Size of buffer. - ) const; + ) const; /// Equality. bool diff --git a/include/wccp/Wccp.h b/include/wccp/Wccp.h index 0e1d26571fa..468ebbeade4 100644 --- a/include/wccp/Wccp.h +++ b/include/wccp/Wccp.h @@ -187,7 +187,7 @@ class ServiceGroup : public ServiceConstants /// Get a port value. uint16_t getPort(int idx ///< Index of target port. - ) const; + ) const; /// Set a port value. self &setPort(int idx, ///< Index of port. uint16_t port ///< Value for port. diff --git a/iocore/cache/CacheDir.cc b/iocore/cache/CacheDir.cc index a0cedc45f5e..04b6288e05d 100644 --- a/iocore/cache/CacheDir.cc +++ b/iocore/cache/CacheDir.cc @@ -1191,7 +1191,8 @@ compare_ushort(void const *a, void const *b) // Check // -int Vol::dir_check(bool /* fix ATS_UNUSED */) // TODO: we should eliminate this parameter ? +int +Vol::dir_check(bool /* fix ATS_UNUSED */) // TODO: we should eliminate this parameter ? { static int const SEGMENT_HISTOGRAM_WIDTH = 16; int hist[SEGMENT_HISTOGRAM_WIDTH + 1] = {0}; diff --git a/iocore/cache/CacheTest.cc b/iocore/cache/CacheTest.cc index fac78b90011..d7d42e24cda 100644 --- a/iocore/cache/CacheTest.cc +++ b/iocore/cache/CacheTest.cc @@ -333,13 +333,14 @@ EXCLUSIVE_REGRESSION_TEST(cache)(RegressionTest *t, int /* atype ATS_UNUSED */, remove_fail_test.expect_event = CACHE_EVENT_REMOVE_FAILED; rand_CacheKey(&remove_fail_test.key, thread->mutex); - CACHE_SM(t, replace_write_test, - { cacheProcessor.open_write(this, &key, CACHE_FRAG_TYPE_NONE, 100, CACHE_WRITE_OPT_SYNC); } int open_write_callout() { - header.serial = 10; - cache_vc->set_header(&header, sizeof(header)); - cvio = cache_vc->do_io_write(this, nbytes, buffer_reader); - return 1; - }); + CACHE_SM( + t, replace_write_test, + { cacheProcessor.open_write(this, &key, CACHE_FRAG_TYPE_NONE, 100, CACHE_WRITE_OPT_SYNC); } int open_write_callout() { + header.serial = 10; + cache_vc->set_header(&header, sizeof(header)); + cvio = cache_vc->do_io_write(this, nbytes, buffer_reader); + return 1; + }); replace_write_test.expect_initial_event = CACHE_EVENT_OPEN_WRITE; replace_write_test.expect_event = VC_EVENT_WRITE_COMPLETE; replace_write_test.nbytes = 100; @@ -365,16 +366,17 @@ EXCLUSIVE_REGRESSION_TEST(cache)(RegressionTest *t, int /* atype ATS_UNUSED */, replace_test.key = replace_write_test.key; replace_test.content_salt = 1; - CACHE_SM(t, replace_read_test, { cacheProcessor.open_read(this, &key); } int open_read_callout() { - CacheTestHeader *h = nullptr; - int hlen = 0; - if (cache_vc->get_header((void **)&h, &hlen) < 0) - return -1; - if (h->serial != 11) - return -1; - cvio = cache_vc->do_io_read(this, nbytes, buffer); - return 1; - }); + CACHE_SM( + t, replace_read_test, { cacheProcessor.open_read(this, &key); } int open_read_callout() { + CacheTestHeader *h = nullptr; + int hlen = 0; + if (cache_vc->get_header((void **)&h, &hlen) < 0) + return -1; + if (h->serial != 11) + return -1; + cvio = cache_vc->do_io_read(this, nbytes, buffer); + return 1; + }); replace_read_test.expect_initial_event = CACHE_EVENT_OPEN_READ; replace_read_test.expect_event = VC_EVENT_READ_COMPLETE; replace_read_test.nbytes = 100; @@ -387,10 +389,11 @@ EXCLUSIVE_REGRESSION_TEST(cache)(RegressionTest *t, int /* atype ATS_UNUSED */, large_write_test.nbytes = 10000000; rand_CacheKey(&large_write_test.key, thread->mutex); - CACHE_SM(t, pread_test, { cacheProcessor.open_read(this, &key); } int open_read_callout() { - cvio = cache_vc->do_io_pread(this, nbytes, buffer, 7000000); - return 1; - }); + CACHE_SM( + t, pread_test, { cacheProcessor.open_read(this, &key); } int open_read_callout() { + cvio = cache_vc->do_io_pread(this, nbytes, buffer, 7000000); + return 1; + }); pread_test.expect_initial_event = CACHE_EVENT_OPEN_READ; pread_test.expect_event = VC_EVENT_READ_COMPLETE; pread_test.nbytes = 100; diff --git a/iocore/net/quic/Mock.h b/iocore/net/quic/Mock.h index 535dff56b46..0c78e30aa0c 100644 --- a/iocore/net/quic/Mock.h +++ b/iocore/net/quic/Mock.h @@ -560,10 +560,7 @@ class MockQUICLossDetector : public QUICLossDetector _padder(NetVConnectionContext_t::NET_VCONNECTION_UNSET) { } - void - rcv_frame(std::shared_ptr) - { - } + void rcv_frame(std::shared_ptr) {} void on_packet_sent(QUICPacketUPtr packet) diff --git a/lib/records/RecCore.cc b/lib/records/RecCore.cc index 1310082d2f9..01430b7253e 100644 --- a/lib/records/RecCore.cc +++ b/lib/records/RecCore.cc @@ -1283,11 +1283,12 @@ RecSignalWarning(int sig, const char *fmt, ...) void RecConfigWarnIfUnregistered() { - RecDumpRecords(RECT_CONFIG, - [](RecT, void *, int registered_p, const char *name, int, RecData *) -> void { - if (!registered_p) { - Warning("Unrecognized configuration value '%s'", name); - } - }, - nullptr); + RecDumpRecords( + RECT_CONFIG, + [](RecT, void *, int registered_p, const char *name, int, RecData *) -> void { + if (!registered_p) { + Warning("Unrecognized configuration value '%s'", name); + } + }, + nullptr); } diff --git a/mgmt/WebMgmtUtils.cc b/mgmt/WebMgmtUtils.cc index 383d7df7967..eb004e28c34 100644 --- a/mgmt/WebMgmtUtils.cc +++ b/mgmt/WebMgmtUtils.cc @@ -1065,9 +1065,8 @@ recordIPCheck(const char *pattern, const char *value) // regex_t regex; // int result; bool check; - const char *range_pattern = - R"(\[[0-9]+\-[0-9]+\]\\\.\[[0-9]+\-[0-9]+\]\\\.\[[0-9]+\-[0-9]+\]\\\.\[[0-9]+\-[0-9]+\])"; - const char *ip_pattern = "[0-9]*[0-9]*[0-9].[0-9]*[0-9]*[0-9].[0-9]*[0-9]*[0-9].[0-9]*[0-9]*[0-9]"; + const char *range_pattern = R"(\[[0-9]+\-[0-9]+\]\\\.\[[0-9]+\-[0-9]+\]\\\.\[[0-9]+\-[0-9]+\]\\\.\[[0-9]+\-[0-9]+\])"; + const char *ip_pattern = "[0-9]*[0-9]*[0-9].[0-9]*[0-9]*[0-9].[0-9]*[0-9]*[0-9].[0-9]*[0-9]*[0-9]"; Tokenizer dotTok1("."); Tokenizer dotTok2("."); diff --git a/mgmt/api/INKMgmtAPI.cc b/mgmt/api/INKMgmtAPI.cc index 245c198280b..0c4c376f53b 100644 --- a/mgmt/api/INKMgmtAPI.cc +++ b/mgmt/api/INKMgmtAPI.cc @@ -688,7 +688,7 @@ TSTerminate() /*--- plugin initialization -----------------------------------------------*/ inkexp extern void -TSPluginInit(int /* argc ATS_UNUSED */, const char * /* argv ATS_UNUSED */ []) +TSPluginInit(int /* argc ATS_UNUSED */, const char * /* argv ATS_UNUSED */[]) { } diff --git a/plugins/experimental/metalink/metalink.cc b/plugins/experimental/metalink/metalink.cc index e1819fc4845..fc97e1489f7 100644 --- a/plugins/experimental/metalink/metalink.cc +++ b/plugins/experimental/metalink/metalink.cc @@ -888,7 +888,7 @@ handler(TSCont contp, TSEvent event, void *edata) } void -TSPluginInit(int /* argc ATS_UNUSED */, const char * /* argv ATS_UNUSED */ []) +TSPluginInit(int /* argc ATS_UNUSED */, const char * /* argv ATS_UNUSED */[]) { TSPluginRegistrationInfo info; diff --git a/plugins/experimental/slice/HttpHeader.h b/plugins/experimental/slice/HttpHeader.h index bfd9c4d6f4e..c72f776adad 100644 --- a/plugins/experimental/slice/HttpHeader.h +++ b/plugins/experimental/slice/HttpHeader.h @@ -106,7 +106,7 @@ struct HttpHeader { char *const valstr, // <-- return string value int *const vallen, // <-- pass in capacity, returns len of string int const index = -1 // retrieves all values - ) const; + ) const; /** Sets or adds a key/value diff --git a/plugins/experimental/slice/Range.cc b/plugins/experimental/slice/Range.cc index bb06099722b..ad62c34ae65 100644 --- a/plugins/experimental/slice/Range.cc +++ b/plugins/experimental/slice/Range.cc @@ -121,7 +121,7 @@ Range::fromStringClosed(char const *const rangestr) bool Range::toStringClosed(char *const bufstr, int *const buflen // returns actual bytes used - ) const +) const { if (!isValid()) { if (0 < *buflen) { diff --git a/plugins/experimental/slice/transfer.cc b/plugins/experimental/slice/transfer.cc index 4ab7a8bb7c1..c94842e4fae 100644 --- a/plugins/experimental/slice/transfer.cc +++ b/plugins/experimental/slice/transfer.cc @@ -18,7 +18,8 @@ #include "transfer.h" -int64_t transfer_content_bytes(Data *const data) // , char const * const fstr) +int64_t +transfer_content_bytes(Data *const data) // , char const * const fstr) { int64_t consumed(0); diff --git a/plugins/generator/generator.cc b/plugins/generator/generator.cc index 551c6ec5a6f..743ad516404 100644 --- a/plugins/generator/generator.cc +++ b/plugins/generator/generator.cc @@ -642,7 +642,7 @@ GeneratorInitialize() } void -TSPluginInit(int /* argc */, const char * /* argv */ []) +TSPluginInit(int /* argc */, const char * /* argv */[]) { TSPluginRegistrationInfo info; @@ -676,8 +676,7 @@ TSRemapDoRemap(void * /* ih */, TSHttpTxn txn, TSRemapRequestInfo * /* rri ATS_U } TSReturnCode -TSRemapNewInstance(int /* argc */, char * /* argv */ [], void **ih, char * /* errbuf ATS_UNUSED */, - int /* errbuf_size ATS_UNUSED */) +TSRemapNewInstance(int /* argc */, char * /* argv */[], void **ih, char * /* errbuf ATS_UNUSED */, int /* errbuf_size ATS_UNUSED */) { *ih = nullptr; return TS_SUCCESS; diff --git a/proxy/ControlBase.h b/proxy/ControlBase.h index 76ffb25861d..4c79d544865 100644 --- a/proxy/ControlBase.h +++ b/proxy/ControlBase.h @@ -65,10 +65,10 @@ class ControlBase @return @c true if the request is matched, @c false if not. */ virtual bool check(HttpRequestData *req ///< Request to check. - ) const = 0; + ) const = 0; /// Print the mod information. virtual void print(FILE *f ///< Output stream. - ) const = 0; + ) const = 0; }; ControlBase(); diff --git a/proxy/http/Http1Transaction.cc b/proxy/http/Http1Transaction.cc index 8a2790c29b7..5d07691e182 100644 --- a/proxy/http/Http1Transaction.cc +++ b/proxy/http/Http1Transaction.cc @@ -46,7 +46,8 @@ Http1Transaction::release(IOBufferReader *r) } } -void Http1Transaction::destroy() // todo make ~Http1Transaction() +void +Http1Transaction::destroy() // todo make ~Http1Transaction() { _sm = nullptr; } diff --git a/proxy/logging/LogConfig.cc b/proxy/logging/LogConfig.cc index 84236b7ab96..77d517147da 100644 --- a/proxy/logging/LogConfig.cc +++ b/proxy/logging/LogConfig.cc @@ -98,8 +98,7 @@ LogConfig::setup_default_values() max_line_size = 9216; // size of pipe buffer for SunOS 5.6 } -void -LogConfig::reconfigure_mgmt_variables(ts::MemSpan) +void LogConfig::reconfigure_mgmt_variables(ts::MemSpan) { Note("received log reconfiguration event, rolling now"); Log::config->roll_log_files_now = true; diff --git a/src/traffic_server/traffic_server.cc b/src/traffic_server/traffic_server.cc index d6095ab4d42..07d46ad740a 100644 --- a/src/traffic_server/traffic_server.cc +++ b/src/traffic_server/traffic_server.cc @@ -2029,8 +2029,7 @@ REGRESSION_TEST(Hdrs)(RegressionTest *t, int atype, int *pstatus) } #endif -static void -mgmt_restart_shutdown_callback(ts::MemSpan) +static void mgmt_restart_shutdown_callback(ts::MemSpan) { sync_cache_dir_on_shutdown(); } diff --git a/src/tscore/BufferWriterFormat.cc b/src/tscore/BufferWriterFormat.cc index 0060a2c673b..b1070227974 100644 --- a/src/tscore/BufferWriterFormat.cc +++ b/src/tscore/BufferWriterFormat.cc @@ -467,17 +467,18 @@ namespace bw_fmt } w.write(digits); } else { // use generic Write_Aligned - Write_Aligned(w, - [&]() { - if (prefix1) { - w.write(prefix1); - if (prefix2) { - w.write(prefix2); - } - } - w.write(digits); - }, - spec._align, width, spec._fill, neg); + Write_Aligned( + w, + [&]() { + if (prefix1) { + w.write(prefix1); + if (prefix2) { + w.write(prefix2); + } + } + w.write(digits); + }, + spec._align, width, spec._fill, neg); } return w; } @@ -574,13 +575,14 @@ namespace bw_fmt std::string_view whole_digits{whole + sizeof(whole) - l, l}; std::string_view frac_digits{fraction + sizeof(fraction) - r, r}; - Write_Aligned(w, - [&]() { - w.write(whole_digits); - w.write(dec); - w.write(frac_digits); - }, - spec._align, width, spec._fill, neg); + Write_Aligned( + w, + [&]() { + w.write(whole_digits); + w.write(dec); + w.write(frac_digits); + }, + spec._align, width, spec._fill, neg); return w; } @@ -611,7 +613,8 @@ bwformat(BufferWriter &w, BWFSpec const &spec, std::string_view sv) return bwformat(w, spec, bwf::detail::MemDump(sv.data(), sv.size())); } else { width -= sv.size(); - bw_fmt::Write_Aligned(w, [&w, &sv]() { w.write(sv); }, spec._align, width, spec._fill, 0); + bw_fmt::Write_Aligned( + w, [&w, &sv]() { w.write(sv); }, spec._align, width, spec._fill, 0); } return w; } @@ -963,8 +966,8 @@ bwformat(BufferWriter &w, BWFSpec const &spec, bwf::detail::MemDump const &hex) w.write(fmt_type); width -= 2; } - bw_fmt::Write_Aligned(w, [&w, &hex, digits]() { bw_fmt::Format_As_Hex(w, hex._view, digits); }, spec._align, width, spec._fill, - 0); + bw_fmt::Write_Aligned( + w, [&w, &hex, digits]() { bw_fmt::Format_As_Hex(w, hex._view, digits); }, spec._align, width, spec._fill, 0); return w; } diff --git a/src/tscore/EventNotify.cc b/src/tscore/EventNotify.cc index a18decc3021..d0aeec04228 100644 --- a/src/tscore/EventNotify.cc +++ b/src/tscore/EventNotify.cc @@ -104,7 +104,8 @@ EventNotify::wait() #endif } -int EventNotify::timedwait(int timeout) // milliseconds +int +EventNotify::timedwait(int timeout) // milliseconds { #ifdef HAVE_EVENTFD ssize_t nr, nr_fd = 0; diff --git a/src/tscore/IpMap.cc b/src/tscore/IpMap.cc index c24445fc832..3001fc14d78 100644 --- a/src/tscore/IpMap.cc +++ b/src/tscore/IpMap.cc @@ -180,7 +180,7 @@ namespace detail */ bool contains(ArgType target, ///< Search target value. void **ptr = nullptr ///< Client data return. - ) const; + ) const; /** Remove all addresses in the map. diff --git a/src/tscore/ink_res_mkquery.cc b/src/tscore/ink_res_mkquery.cc index 5e9db633142..7bfe95bd4cf 100644 --- a/src/tscore/ink_res_mkquery.cc +++ b/src/tscore/ink_res_mkquery.cc @@ -88,14 +88,15 @@ * Form all types of queries. * Returns the size of the result or -1. */ -int ink_res_mkquery(ink_res_state statp, int op, /*!< opcode of query */ - const char *dname, /*!< domain name */ - int _class, int type, /*!< _class and type of query */ - const u_char *data, /*!< resource record data */ - int datalen, /*!< length of data */ - const u_char * /* newrr_in ATS_UNUSED */, /*!< new rr for modify or append */ - u_char *buf, /*!< buffer to put query */ - int buflen) /*!< size of buffer */ +int +ink_res_mkquery(ink_res_state statp, int op, /*!< opcode of query */ + const char *dname, /*!< domain name */ + int _class, int type, /*!< _class and type of query */ + const u_char *data, /*!< resource record data */ + int datalen, /*!< length of data */ + const u_char * /* newrr_in ATS_UNUSED */, /*!< new rr for modify or append */ + u_char *buf, /*!< buffer to put query */ + int buflen) /*!< size of buffer */ { HEADER *hp; u_char *cp, *ep; diff --git a/src/tscore/test_atomic.cc b/src/tscore/test_atomic.cc index f498645a620..bb2ff0f1be7 100644 --- a/src/tscore/test_atomic.cc +++ b/src/tscore/test_atomic.cc @@ -139,7 +139,7 @@ cycle_data(void *d) #endif // LONG_ATOMICLIST_TEST int -main(int /* argc ATS_UNUSED */, const char * /* argv ATS_UNUSED */ []) +main(int /* argc ATS_UNUSED */, const char * /* argv ATS_UNUSED */[]) { #ifndef LONG_ATOMICLIST_TEST int32_t m = 1, n = 100; diff --git a/src/tscore/test_freelist.cc b/src/tscore/test_freelist.cc index 8c5776babf9..5106f5122a7 100644 --- a/src/tscore/test_freelist.cc +++ b/src/tscore/test_freelist.cc @@ -66,7 +66,7 @@ test(void *d) } int -main(int /* argc ATS_UNUSED */, char * /*argv ATS_UNUSED */ []) +main(int /* argc ATS_UNUSED */, char * /*argv ATS_UNUSED */[]) { int i; diff --git a/src/wccp/WccpLocal.h b/src/wccp/WccpLocal.h index 773ce911cc9..c3329d2b377 100644 --- a/src/wccp/WccpLocal.h +++ b/src/wccp/WccpLocal.h @@ -296,7 +296,7 @@ class RouterAssignListElt ); /// Access const element. RouterAssignElt const &elt(int idx ///< Index of target element. - ) const; + ) const; /// Get the number of elements. uint32_t getCount() const; //@} @@ -537,7 +537,7 @@ class HashAssignElt uint32_t getCount() const; /// Get a cache address. uint32_t getAddr(int idx ///< Index of target address. - ) const; + ) const; /// Set a cache address. self &setAddr(int idx, ///< Index of target address. uint32_t addr ///< Address value to set. @@ -547,7 +547,7 @@ class HashAssignElt ); /// Access a const bucket. Bucket const &operator[](size_t idx ///< Bucket index (0..N_BUCKETS-1) - ) const; + ) const; //@} /** Do a round robin assignment. @@ -1046,7 +1046,7 @@ class SecurityComp : public CompWithHeader ); bool validate(MsgBuffer const &msg ///< Message data. - ) const; + ) const; protected: /// Local to this message shared key / password. @@ -1105,7 +1105,7 @@ class ServiceComp : public CompWithHeader /// Get a port value. uint16_t getPort(int idx ///< Index of target port. - ) const; + ) const; /// Set a port value. self &setPort(int idx, ///< Index of port. uint16_t port ///< Value for port. @@ -1195,7 +1195,7 @@ class RouterIdComp : public CompWithHeader uint32_t getFromCount() const; /// Get received from address. uint32_t getFromAddr(int idx ///< Index of address. - ) const; + ) const; /// Set received from address. self &setFromAddr(int idx, ///< Index of address. uint32_t addr ///< Address value. @@ -1335,14 +1335,14 @@ class RouterViewComp : public CompWithHeader ); /// Access cache element. CacheIdBox const &cacheId(int idx ///< Index of target element. - ) const; + ) const; /// Get router count field. /// @note No @c setf method because this cannot be changed independently. /// @see fill uint32_t getRouterCount() const; /// Get router address. uint32_t getRouterAddr(int idx ///< Index of router. - ) const; + ) const; /// Set router address. self &setRouterAddr(int idx, ///< Index of router. uint32_t addr ///< Address value. @@ -1418,7 +1418,7 @@ class CacheViewComp : public CompWithHeader uint32_t getCacheCount() const; /// Get a cache address. uint32_t getCacheAddr(int idx ///< Index of target address. - ) const; + ) const; /// Set a cache address. self &setCacheAddr(int idx, ///< Index of target address. uint32_t addr ///< Address value to set. @@ -1499,7 +1499,7 @@ class AssignInfoComp : public CompWithHeader uint32_t getCacheCount() const; /// Get a cache address. uint32_t getCacheAddr(int idx ///< Index of target address. - ) const; + ) const; /// Set a cache address. self &setCacheAddr(int idx, ///< Index of target address. uint32_t addr ///< Address value to set. @@ -1509,7 +1509,7 @@ class AssignInfoComp : public CompWithHeader ); /// Access a bucket. Bucket const &bucket(int idx ///< Index of target bucket. - ) const; + ) const; //@} /// Fill out the component from an @c Assignment. @@ -1560,7 +1560,7 @@ class CapComp : public CompWithHeader CapabilityElt &elt(int idx ///< Index of target element. ); CapabilityElt const &elt(int idx ///< Index of target element. - ) const; + ) const; /// Get the element count. /// @note No corresponding @c setf_ because that cannot be changed once set. /// @see fill @@ -2268,7 +2268,7 @@ class Impl : public ts::IntrusivePtrCounter /// @return Security option to use during message fill. SecurityOption setSecurity(BaseMsg &msg, ///< Message. GroupData const &group ///< Group data used to control fill. - ) const; + ) const; /// Validate a security component. bool validateSecurity(BaseMsg &msg, ///< Message data (including security component). GroupData const &group ///< Group data for message. @@ -2301,11 +2301,11 @@ namespace detail /// Time until next packet. /// @return Seconds until a packet should be sent. time_t waitTime(time_t now ///< Current time. - ) const; + ) const; /// Time till next ping. /// @return Seconds until a HERE_I_AM should be sent. time_t pingTime(time_t now ///< Current time. - ) const; + ) const; uint32_t m_addr; ///< Router identifying IP address. uint32_t m_generation; ///< Router's view change number. @@ -2406,7 +2406,7 @@ namespace detail /// Time until next event. /// @return The number of seconds until the next event of interest. time_t waitTime(time_t now ///< Current time. - ) const; + ) const; /** Cull routers. Routers that have not replied recently are moved from the @@ -2503,7 +2503,7 @@ class CacheImpl : public Impl */ virtual ts::Errata checkRouterAssignment(GroupData const &group, ///< Group with assignment. RouterViewComp const &comp ///< Assignment reported by router. - ) const; + ) const; protected: /// Generate contents in HERE_I_AM @a msg for seed router. diff --git a/tools/clang-format.sh b/tools/clang-format.sh index 6c37d5df5eb..7d85ebb7021 100755 --- a/tools/clang-format.sh +++ b/tools/clang-format.sh @@ -19,7 +19,7 @@ # limitations under the License. # Update the PKGDATE with the new version date when making a new clang-format binary package. -PKGDATE="20180413" +PKGDATE="20191031" function main() { set -e # exit on error @@ -27,7 +27,7 @@ function main() { DIR=${1:-.} PACKAGE="clang-format-${PKGDATE}.tar.bz2" - VERSION="clang-format version 6.0.1 (http://llvm.org/git/clang.git d5f48a217f404c3462537527f4169bb45eed3904) (http://llvm.org/git/llvm.git aa0c91ae818e0b9e7981a42236dededc85997568)" + VERSION="clang-format version 9.0.0 (https://github.com/llvm/llvm-project.git 0399d5a9682b3cef71c653373e38890c63c4c365)" URL=${URL:-https://ci.trafficserver.apache.org/bintray/${PACKAGE}} @@ -62,7 +62,7 @@ function main() { ${CURL} -L --progress-bar -o ${ARCHIVE} ${URL} ${TAR} -x -C ${ROOT} -f ${ARCHIVE} cat > ${ROOT}/sha1 << EOF -26aff1bc6dc315c695c62cadde38c934acd22d06 ${ARCHIVE} +c1b7ae57bfc80507ee155779a1ab8cf919b3e062 ${ARCHIVE} EOF ${SHASUM} -c ${ROOT}/sha1 chmod +x ${FORMAT} From bf4aeeb772bf347feadc14e5789caebb4b77aecf Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Tue, 5 Nov 2019 17:38:26 -0700 Subject: [PATCH 114/718] Deprecated a bunch of configs for filenames --- doc/release-notes/upgrading.en.rst | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/doc/release-notes/upgrading.en.rst b/doc/release-notes/upgrading.en.rst index fb2505d5d4d..f7a46b8b62d 100644 --- a/doc/release-notes/upgrading.en.rst +++ b/doc/release-notes/upgrading.en.rst @@ -75,6 +75,25 @@ Removed records.config settings The following settings are simply gone, and have no purpose: * `proxy.config.config_dir` (see PROXY_CONFIG_CONFIG_DIR environment variable) +* `proxy.config.cache.storage_filename` (see next section as well) + +Deprecated records.config settings +---------------------------------- +The following configurations still exist, and functions, but are considered +deprecated and will be removed in a future release. We **strongly** encourage +you to avoid using any of these: + + * :ts:cv:`proxy.config.http.parent_proxy.file` + * :ts:cv:`proxy.config.socks.socks_config_file` + * :ts:cv:`proxy.config.cache.control.filename` + * :ts:cv:`proxy.config.cache.ip_allow.filename` + * :ts:cv:`proxy.config.cache.hosting_filename` + * :ts:cv:`proxy.config.cache.volume_filename` + * :ts:cv:`proxy.config.dns.splitdns.filename` + * :ts:cv:`proxy.config.log.config.filename` + * :ts:cv:`proxy.config.url_remap.filename` + * :ts:cv:`proxy.config.ssl.server.multicert.filename` + * :ts:cv:`proxy.config.ssl.servername.filename` Deprecated or Removed Features ------------------------------ From 003e7123c424b3d64a2f01d70a5c4e6b0b43340f Mon Sep 17 00:00:00 2001 From: Randall Meyer Date: Fri, 1 Nov 2019 16:24:21 -0700 Subject: [PATCH 115/718] Remove never implemented HttpTransact::service_transaction_in_proxy_only_mode HttpTransact::service_transaction_in_proxy_only_mode was part of the original import with a TODO to implement. This was never done. Also remove proxy.process.http.throttled_proxy_only as it was only incremented in a code path never executed. (cherry picked from commit 51961cb54d448c94127028171c297ba3a40793db) --- .../statistics/core/bandwidth.en.rst | 1 - proxy/http/HttpConfig.cc | 3 --- proxy/http/HttpConfig.h | 1 - proxy/http/HttpTransact.cc | 27 ------------------- proxy/http/HttpTransact.h | 1 - 5 files changed, 33 deletions(-) diff --git a/doc/admin-guide/monitoring/statistics/core/bandwidth.en.rst b/doc/admin-guide/monitoring/statistics/core/bandwidth.en.rst index 0b5113b8ce8..73f99665b70 100644 --- a/doc/admin-guide/monitoring/statistics/core/bandwidth.en.rst +++ b/doc/admin-guide/monitoring/statistics/core/bandwidth.en.rst @@ -22,7 +22,6 @@ Bandwidth and Transfer ********************** -.. ts:stat:: global proxy.process.http.throttled_proxy_only integer .. ts:stat:: global proxy.process.http.user_agent_request_document_total_size integer :type: counter :units: bytes diff --git a/proxy/http/HttpConfig.cc b/proxy/http/HttpConfig.cc index 46f0f0979be..0d247f5866b 100644 --- a/proxy/http/HttpConfig.cc +++ b/proxy/http/HttpConfig.cc @@ -356,9 +356,6 @@ register_stat_callbacks() RecRegisterRawStat(http_rsb, RECT_PROCESS, "proxy.process.http.tunnels", RECD_COUNTER, RECP_PERSISTENT, (int)http_tunnels_stat, RecRawStatSyncCount); - RecRegisterRawStat(http_rsb, RECT_PROCESS, "proxy.process.http.throttled_proxy_only", RECD_COUNTER, RECP_PERSISTENT, - (int)http_throttled_proxy_only_stat, RecRawStatSyncCount); - RecRegisterRawStat(http_rsb, RECT_PROCESS, "proxy.process.http.parent_proxy_transaction_time", RECD_INT, RECP_PERSISTENT, (int)http_parent_proxy_transaction_time_stat, RecRawStatSyncSum); diff --git a/proxy/http/HttpConfig.h b/proxy/http/HttpConfig.h index 45f922d0ea8..c030fa58ca5 100644 --- a/proxy/http/HttpConfig.h +++ b/proxy/http/HttpConfig.h @@ -121,7 +121,6 @@ enum { http_cache_deletes_stat, http_tunnels_stat, - http_throttled_proxy_only_stat, // document size stats http_user_agent_request_header_total_size_stat, diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc index f5898f01676..0664a45a4df 100644 --- a/proxy/http/HttpTransact.cc +++ b/proxy/http/HttpTransact.cc @@ -1817,11 +1817,6 @@ HttpTransact::DecideCacheLookup(State *s) } } - if (service_transaction_in_proxy_only_mode(s)) { - s->cache_info.action = CACHE_DO_NO_ACTION; - s->current.mode = TUNNELLING_PROXY; - HTTP_INCREMENT_DYN_STAT(http_throttled_proxy_only_stat); - } // at this point the request is ready to continue down the // traffic server path. @@ -6325,28 +6320,6 @@ HttpTransact::is_response_valid(State *s, HTTPHdr *incoming_response) } } -/////////////////////////////////////////////////////////////////////////////// -// Name : service_transaction_in_proxy_only_mode -// Description: uses some metric to force this transaction to be proxy-only -// -// Details : -// -// Some metric may be employed to force the traffic server to enter -// a proxy-only mode temporarily. This function is called to determine -// if the current transaction should be proxy-only. The function is -// called from initialize_state_variables_from_request and is used to -// set s->current.mode to TUNNELLING_PROXY and just for safety to set -// s->cache_info.action to CACHE_DO_NO_ACTION. -// -// Currently the function is just a placeholder and always returns false. -// -/////////////////////////////////////////////////////////////////////////////// -bool -HttpTransact::service_transaction_in_proxy_only_mode(State * /* s ATS_UNUSED */) -{ - return false; -} - void HttpTransact::process_quick_http_filter(State *s, int method) { diff --git a/proxy/http/HttpTransact.h b/proxy/http/HttpTransact.h index f7bfef58cad..59948c7f133 100644 --- a/proxy/http/HttpTransact.h +++ b/proxy/http/HttpTransact.h @@ -997,7 +997,6 @@ class HttpTransact static bool get_ka_info_from_config(State *s, ConnectionAttributes *server_info); static void get_ka_info_from_host_db(State *s, ConnectionAttributes *server_info, ConnectionAttributes *client_info, HostDBInfo *host_db_info); - static bool service_transaction_in_proxy_only_mode(State *s); static void setup_plugin_request_intercept(State *s); static void add_client_ip_to_outgoing_request(State *s, HTTPHdr *request); static RequestError_t check_request_validity(State *s, HTTPHdr *incoming_hdr); From e36bc7a7f6d1bbb74630534482feffa45db91ab3 Mon Sep 17 00:00:00 2001 From: bneradt Date: Mon, 4 Nov 2019 17:09:18 +0000 Subject: [PATCH 116/718] Fixing include synopsis rendering for API docs. I noticed the include synopsis renders incorrectly for multiple includes. The method we're using for them is incorrect, even for a single include, but demonstrates itself as incorrect when there are multiple. The problem can currently be seen here: https://docs.trafficserver.apache.org/en/latest/developer-guide/api/functions/TSAPI.en.html I'm applying the solution which was already implemented here: https://raw.githubusercontent.com/apache/trafficserver/fa10c20b8ed43072fd7e214c62b195b525f24d8e/doc/developer-guide/internal-libraries/buffer-writer.en.rst (cherry picked from commit 85c0cd449d8ebe5e4c14b2263c4bac076607f35d) --- doc/developer-guide/api/functions/TSAPI.en.rst | 6 ++++-- doc/developer-guide/api/functions/TSAcceptor.en.rst | 4 +++- doc/developer-guide/api/functions/TSActionCancel.en.rst | 4 +++- doc/developer-guide/api/functions/TSActionDone.en.rst | 4 +++- doc/developer-guide/api/functions/TSCacheRead.en.rst | 4 +++- doc/developer-guide/api/functions/TSCacheRemove.en.rst | 4 +++- doc/developer-guide/api/functions/TSCacheWrite.en.rst | 4 +++- .../api/functions/TSClientProtocolStack.en.rst | 4 +++- doc/developer-guide/api/functions/TSConfig.en.rst | 4 +++- doc/developer-guide/api/functions/TSContCall.en.rst | 4 +++- doc/developer-guide/api/functions/TSContCreate.en.rst | 4 +++- doc/developer-guide/api/functions/TSContDataGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSContDataSet.en.rst | 4 +++- doc/developer-guide/api/functions/TSContDestroy.en.rst | 4 +++- doc/developer-guide/api/functions/TSContMutexGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSContSchedule.en.rst | 4 +++- .../api/functions/TSContScheduleOnPool.en.rst | 4 +++- .../api/functions/TSContScheduleOnThread.en.rst | 4 +++- .../api/functions/TSContThreadAffinityClear.en.rst | 4 +++- .../api/functions/TSContThreadAffinityGet.en.rst | 4 +++- .../api/functions/TSContThreadAffinitySet.en.rst | 4 +++- doc/developer-guide/api/functions/TSDebug.en.rst | 4 +++- .../api/functions/TSEventThreadSelf.en.rst | 4 +++- doc/developer-guide/api/functions/TSHostLookup.en.rst | 4 +++- .../api/functions/TSHostLookupResultAddrGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSHttpArgs.en.rst | 4 +++- doc/developer-guide/api/functions/TSHttpConnect.en.rst | 4 +++- .../api/functions/TSHttpConnectWithPluginId.en.rst | 4 +++- doc/developer-guide/api/functions/TSHttpHdrClone.en.rst | 4 +++- doc/developer-guide/api/functions/TSHttpHdrCopy.en.rst | 4 +++- doc/developer-guide/api/functions/TSHttpHdrCreate.en.rst | 4 +++- doc/developer-guide/api/functions/TSHttpHdrDestroy.en.rst | 4 +++- doc/developer-guide/api/functions/TSHttpHdrHostGet.en.rst | 4 +++- .../api/functions/TSHttpHdrLengthGet.en.rst | 4 +++- .../api/functions/TSHttpHdrMethodGet.en.rst | 4 +++- .../api/functions/TSHttpHdrMethodSet.en.rst | 4 +++- doc/developer-guide/api/functions/TSHttpHdrPrint.en.rst | 4 +++- .../api/functions/TSHttpHdrReasonGet.en.rst | 4 +++- .../api/functions/TSHttpHdrReasonLookup.en.rst | 4 +++- .../api/functions/TSHttpHdrReasonSet.en.rst | 4 +++- .../api/functions/TSHttpHdrStatusGet.en.rst | 4 +++- .../api/functions/TSHttpHdrStatusSet.en.rst | 4 +++- doc/developer-guide/api/functions/TSHttpHdrTypeGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSHttpHdrTypeSet.en.rst | 4 +++- doc/developer-guide/api/functions/TSHttpHdrUrlGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSHttpHdrUrlSet.en.rst | 4 +++- .../api/functions/TSHttpHdrVersionGet.en.rst | 4 +++- .../api/functions/TSHttpHdrVersionSet.en.rst | 4 +++- doc/developer-guide/api/functions/TSHttpHookAdd.en.rst | 4 +++- .../api/functions/TSHttpOverridableConfig.en.rst | 4 +++- .../api/functions/TSHttpParserCreate.en.rst | 4 +++- .../api/functions/TSHttpSsnClientFdGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSHttpSsnIdGet.en.rst | 4 +++- .../api/functions/TSHttpSsnReenable.en.rst | 4 +++- doc/developer-guide/api/functions/TSHttpTxnAborted.en.rst | 6 ++++-- .../api/functions/TSHttpTxnCacheLookupStatusGet.en.rst | 4 +++- .../api/functions/TSHttpTxnCacheLookupUrlGet.en.rst | 8 ++++++-- .../api/functions/TSHttpTxnCachedReqGet.en.rst | 4 +++- .../api/functions/TSHttpTxnCachedRespGet.en.rst | 4 +++- .../api/functions/TSHttpTxnClientFdGet.en.rst | 4 +++- .../api/functions/TSHttpTxnClientPacketDscpSet.en.rst | 4 +++- .../api/functions/TSHttpTxnClientPacketMarkSet.en.rst | 4 +++- .../api/functions/TSHttpTxnClientPacketTosSet.en.rst | 4 +++- .../api/functions/TSHttpTxnClientReqGet.en.rst | 4 +++- .../api/functions/TSHttpTxnClientRespGet.en.rst | 4 +++- .../api/functions/TSHttpTxnErrorBodySet.en.rst | 4 +++- .../api/functions/TSHttpTxnIncomingAddrGet.en.rst | 4 +++- .../api/functions/TSHttpTxnInfoIntGet.en.rst | 4 +++- .../api/functions/TSHttpTxnIntercept.en.rst | 4 +++- .../api/functions/TSHttpTxnIsCacheable.en.rst | 4 +++- .../api/functions/TSHttpTxnIsInternal.en.rst | 4 +++- .../api/functions/TSHttpTxnIsWebsocket.en.rst | 4 +++- .../api/functions/TSHttpTxnMilestoneGet.en.rst | 4 +++- .../api/functions/TSHttpTxnNextHopAddrGet.en.rst | 4 +++- .../api/functions/TSHttpTxnNextHopNameGet.en.rst | 4 +++- .../api/functions/TSHttpTxnOutgoingAddrGet.en.rst | 4 +++- .../api/functions/TSHttpTxnParentProxySet.en.rst | 4 +++- .../api/functions/TSHttpTxnParentSelectionUrlGet.en.rst | 4 +++- .../api/functions/TSHttpTxnPluginTagGet.en.rst | 4 +++- .../api/functions/TSHttpTxnRedoCacheLookup.en.rst | 4 +++- .../api/functions/TSHttpTxnReenable.en.rst | 4 +++- .../api/functions/TSHttpTxnServerAddrGet.en.rst | 4 +++- .../api/functions/TSHttpTxnServerAddrSet.en.rst | 4 +++- .../api/functions/TSHttpTxnServerFdGet.en.rst | 4 +++- .../api/functions/TSHttpTxnServerIntercept.en.rst | 4 +++- .../api/functions/TSHttpTxnServerPacketDscpSet.en.rst | 4 +++- .../api/functions/TSHttpTxnServerPacketMarkSet.en.rst | 4 +++- .../api/functions/TSHttpTxnServerPacketTosSet.en.rst | 4 +++- .../api/functions/TSHttpTxnServerPush.en.rst | 4 +++- .../api/functions/TSHttpTxnServerReqGet.en.rst | 4 +++- .../api/functions/TSHttpTxnServerRespGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSHttpTxnSsnGet.en.rst | 4 +++- .../api/functions/TSHttpTxnTransformRespGet.en.rst | 4 +++- .../api/functions/TSHttpTxnTransformedRespCache.en.rst | 4 +++- .../api/functions/TSHttpTxnUntransformedRespCache.en.rst | 4 +++- .../api/functions/TSIOBufferBlockReadStart.en.rst | 4 +++- doc/developer-guide/api/functions/TSIOBufferCopy.en.rst | 4 +++- doc/developer-guide/api/functions/TSIOBufferCreate.en.rst | 4 +++- doc/developer-guide/api/functions/TSIOBufferReader.en.rst | 5 ++++- doc/developer-guide/api/functions/TSInstallDirGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSIpStringToAddr.en.rst | 4 +++- .../api/functions/TSLifecycleHookAdd.en.rst | 4 +++- doc/developer-guide/api/functions/TSMBufferCreate.en.rst | 4 +++- doc/developer-guide/api/functions/TSMgmtCounterGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSMgmtFloatGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSMgmtIntGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSMgmtSourceGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSMgmtStringGet.en.rst | 4 +++- .../api/functions/TSMgmtUpdateRegister.en.rst | 4 +++- doc/developer-guide/api/functions/TSMimeHdrClone.en.rst | 4 +++- doc/developer-guide/api/functions/TSMimeHdrCopy.en.rst | 4 +++- doc/developer-guide/api/functions/TSMimeHdrCreate.en.rst | 4 +++- doc/developer-guide/api/functions/TSMimeHdrDestroy.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldAppend.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldClone.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldCopy.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldCopyValues.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldCreate.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldDestroy.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldFind.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldGet.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldLengthGet.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldNameGet.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldNameSet.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldNext.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldNextDup.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldRemove.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldValueAppend.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldValueDateInsert.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldValueDateSet.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldValueIntSet.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldValueStringGet.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldValueStringInsert.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldValueStringSet.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldValueUintInsert.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldValueUintSet.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldValuesClear.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldValuesCount.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldsClear.en.rst | 4 +++- .../api/functions/TSMimeHdrFieldsCount.en.rst | 4 +++- .../api/functions/TSMimeHdrLengthGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSMimeHdrParse.en.rst | 4 +++- doc/developer-guide/api/functions/TSMimeHdrPrint.en.rst | 4 +++- .../api/functions/TSMimeParserClear.en.rst | 4 +++- .../api/functions/TSMimeParserCreate.en.rst | 4 +++- .../api/functions/TSMimeParserDestroy.en.rst | 4 +++- doc/developer-guide/api/functions/TSMutexCreate.en.rst | 4 +++- doc/developer-guide/api/functions/TSMutexDestroy.en.rst | 4 +++- doc/developer-guide/api/functions/TSMutexLock.en.rst | 4 +++- doc/developer-guide/api/functions/TSMutexLockTry.en.rst | 4 +++- doc/developer-guide/api/functions/TSMutexUnlock.en.rst | 4 +++- doc/developer-guide/api/functions/TSNetAccept.en.rst | 4 +++- .../api/functions/TSNetAcceptNamedProtocol.en.rst | 4 +++- doc/developer-guide/api/functions/TSNetConnect.en.rst | 4 +++- doc/developer-guide/api/functions/TSNetInvokingGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSPluginInit.en.rst | 4 +++- doc/developer-guide/api/functions/TSRecords.en.rst | 4 +++- doc/developer-guide/api/functions/TSRemap.en.rst | 6 ++++-- .../api/functions/TSRemapFromToUrlGet.en.rst | 4 +++- .../api/functions/TSSslClientCertUpdate.en.rst | 4 +++- .../api/functions/TSSslClientContext.en.rst | 4 +++- doc/developer-guide/api/functions/TSSslContext.en.rst | 4 +++- .../api/functions/TSSslServerCertUpdate.en.rst | 4 +++- .../api/functions/TSSslServerContextCreate.en.rst | 4 +++- doc/developer-guide/api/functions/TSSslSession.en.rst | 4 +++- doc/developer-guide/api/functions/TSStat.en.rst | 4 +++- .../api/functions/TSTextLogObjectCreate.en.rst | 4 +++- doc/developer-guide/api/functions/TSThreadCreate.en.rst | 4 +++- doc/developer-guide/api/functions/TSThreadDestroy.en.rst | 4 +++- doc/developer-guide/api/functions/TSThreadInit.en.rst | 4 +++- doc/developer-guide/api/functions/TSThreadSelf.en.rst | 4 +++- .../api/functions/TSTrafficServerVersionGet.en.rst | 4 +++- .../api/functions/TSTransformCreate.en.rst | 4 +++- .../api/functions/TSTransformOutputVConnGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSTypes.en.rst | 6 ++++-- doc/developer-guide/api/functions/TSUrlCreate.en.rst | 4 +++- doc/developer-guide/api/functions/TSUrlFtpTypeGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSUrlFtpTypeSet.en.rst | 4 +++- doc/developer-guide/api/functions/TSUrlHostGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSUrlHostSet.en.rst | 4 +++- .../api/functions/TSUrlPercentEncode.en.rst | 4 +++- doc/developer-guide/api/functions/TSUrlStringGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSUuidCreate.en.rst | 4 +++- doc/developer-guide/api/functions/TSVConn.en.rst | 4 +++- doc/developer-guide/api/functions/TSVConnAbort.en.rst | 4 +++- doc/developer-guide/api/functions/TSVConnArgs.en.rst | 4 +++- .../api/functions/TSVConnCacheObjectSizeGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSVConnClose.en.rst | 4 +++- doc/developer-guide/api/functions/TSVConnClosedGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSVConnCreate.en.rst | 4 +++- doc/developer-guide/api/functions/TSVConnFdCreate.en.rst | 4 +++- doc/developer-guide/api/functions/TSVConnIsSsl.en.rst | 4 +++- doc/developer-guide/api/functions/TSVConnProtocol.en.rst | 4 +++- doc/developer-guide/api/functions/TSVConnRead.en.rst | 4 +++- .../api/functions/TSVConnReadVIOGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSVConnReenable.en.rst | 4 +++- doc/developer-guide/api/functions/TSVConnShutdown.en.rst | 4 +++- .../api/functions/TSVConnSslConnectionGet.en.rst | 4 +++- .../api/functions/TSVConnSslVerifyCTXGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSVConnTunnel.en.rst | 4 +++- doc/developer-guide/api/functions/TSVConnWrite.en.rst | 4 +++- .../api/functions/TSVConnWriteVIOGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSVIOBufferGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSVIOContGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSVIOMutexGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSVIONBytesGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSVIONBytesSet.en.rst | 4 +++- doc/developer-guide/api/functions/TSVIONDoneGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSVIONDoneSet.en.rst | 4 +++- doc/developer-guide/api/functions/TSVIONTodoGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSVIOReaderGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSVIOReenable.en.rst | 4 +++- doc/developer-guide/api/functions/TSVIOVConnGet.en.rst | 4 +++- doc/developer-guide/api/functions/TSfclose.en.rst | 4 +++- doc/developer-guide/api/functions/TSfflush.en.rst | 4 +++- doc/developer-guide/api/functions/TSfgets.en.rst | 4 +++- doc/developer-guide/api/functions/TSfopen.en.rst | 4 +++- doc/developer-guide/api/functions/TSfread.en.rst | 4 +++- doc/developer-guide/api/functions/TSfwrite.en.rst | 4 +++- doc/developer-guide/api/functions/TSmalloc.en.rst | 4 +++- doc/developer-guide/api/types/TSCacheDataType.en.rst | 4 +++- doc/developer-guide/api/types/TSCacheError.en.rst | 4 +++- doc/developer-guide/api/types/TSCacheLookupResult.en.rst | 4 +++- doc/developer-guide/api/types/TSCacheScanResult.en.rst | 4 +++- doc/developer-guide/api/types/TSEvent.en.rst | 4 +++- doc/developer-guide/api/types/TSFetchWakeUpOptions.en.rst | 4 +++- doc/developer-guide/api/types/TSHttpHookID.en.rst | 4 +++- doc/developer-guide/api/types/TSHttpStatus.en.rst | 4 +++- doc/developer-guide/api/types/TSHttpType.en.rst | 4 +++- doc/developer-guide/api/types/TSIOBuffersSizeIndex.en.rst | 4 +++- doc/developer-guide/api/types/TSLookingUpType.en.rst | 4 +++- .../api/types/TSOverridableConfigKey.en.rst | 4 +++- doc/developer-guide/api/types/TSParseResult.en.rst | 4 +++- doc/developer-guide/api/types/TSRecordAccessType.en.rst | 4 +++- doc/developer-guide/api/types/TSRecordCheckType.en.rst | 4 +++- doc/developer-guide/api/types/TSRecordDataType.en.rst | 4 +++- doc/developer-guide/api/types/TSRecordModeType.en.rst | 4 +++- doc/developer-guide/api/types/TSRecordPersistType.en.rst | 4 +++- doc/developer-guide/api/types/TSRecordType.en.rst | 4 +++- doc/developer-guide/api/types/TSRecordUpdateType.en.rst | 4 +++- doc/developer-guide/api/types/TSReturnCode.en.rst | 4 +++- doc/developer-guide/api/types/TSSDKVersion.en.rst | 4 +++- .../api/types/TSServerSessionSharingMatchType.en.rst | 4 +++- .../api/types/TSServerSessionSharingPoolType.en.rst | 4 +++- doc/developer-guide/api/types/TSServerState.en.rst | 4 +++- doc/developer-guide/api/types/TSSslSession.en.rst | 4 +++- doc/developer-guide/api/types/TSStatPeristence.en.rst | 6 ++++-- doc/developer-guide/api/types/TSStatSync.en.rst | 6 ++++-- doc/developer-guide/api/types/TSThreadPool.en.rst | 4 +++- doc/developer-guide/api/types/TSUuid.en.rst | 4 +++- doc/developer-guide/api/types/TSVConnCloseFlags.en.rst | 4 +++- doc/developer-guide/internal-libraries/MemSpan.en.rst | 4 +++- doc/developer-guide/internal-libraries/TextView.en.rst | 4 +++- 253 files changed, 769 insertions(+), 260 deletions(-) diff --git a/doc/developer-guide/api/functions/TSAPI.en.rst b/doc/developer-guide/api/functions/TSAPI.en.rst index 1a9da2a25ef..b47d0ec1136 100644 --- a/doc/developer-guide/api/functions/TSAPI.en.rst +++ b/doc/developer-guide/api/functions/TSAPI.en.rst @@ -28,8 +28,10 @@ Introduction to the Apache Traffic Server API. Synopsis ======== -`#include ` -`#include ` +.. code-block:: cpp + + #include + #include Description =========== diff --git a/doc/developer-guide/api/functions/TSAcceptor.en.rst b/doc/developer-guide/api/functions/TSAcceptor.en.rst index 35bc21e9902..b6ebb3c2bad 100644 --- a/doc/developer-guide/api/functions/TSAcceptor.en.rst +++ b/doc/developer-guide/api/functions/TSAcceptor.en.rst @@ -26,7 +26,9 @@ Traffic Server API's related to Accept objects Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSAcceptor TSAcceptorGet(TSVConn sslp) .. function:: TSAcceptor TSAcceptorGetbyID(int id) diff --git a/doc/developer-guide/api/functions/TSActionCancel.en.rst b/doc/developer-guide/api/functions/TSActionCancel.en.rst index c15afae8961..0626f748ef8 100644 --- a/doc/developer-guide/api/functions/TSActionCancel.en.rst +++ b/doc/developer-guide/api/functions/TSActionCancel.en.rst @@ -24,7 +24,9 @@ TSActionCancel Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSActionCancel(TSAction actionp) diff --git a/doc/developer-guide/api/functions/TSActionDone.en.rst b/doc/developer-guide/api/functions/TSActionDone.en.rst index d7190ccf56d..0990fc7d226 100644 --- a/doc/developer-guide/api/functions/TSActionDone.en.rst +++ b/doc/developer-guide/api/functions/TSActionDone.en.rst @@ -24,7 +24,9 @@ TSActionDone Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: int TSActionDone(TSAction actionp) diff --git a/doc/developer-guide/api/functions/TSCacheRead.en.rst b/doc/developer-guide/api/functions/TSCacheRead.en.rst index 6642d246898..e64dbdde426 100644 --- a/doc/developer-guide/api/functions/TSCacheRead.en.rst +++ b/doc/developer-guide/api/functions/TSCacheRead.en.rst @@ -24,7 +24,9 @@ TSCacheRead Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSAction TSCacheRead(TSCont contp, TSCacheKey key) diff --git a/doc/developer-guide/api/functions/TSCacheRemove.en.rst b/doc/developer-guide/api/functions/TSCacheRemove.en.rst index f5647d59a32..29fe5cf7ea7 100644 --- a/doc/developer-guide/api/functions/TSCacheRemove.en.rst +++ b/doc/developer-guide/api/functions/TSCacheRemove.en.rst @@ -24,7 +24,9 @@ TSCacheRemove Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSAction TSCacheRemove(TSCont contp, TSCacheKey key) diff --git a/doc/developer-guide/api/functions/TSCacheWrite.en.rst b/doc/developer-guide/api/functions/TSCacheWrite.en.rst index e00c8414d9e..92e270d8eeb 100644 --- a/doc/developer-guide/api/functions/TSCacheWrite.en.rst +++ b/doc/developer-guide/api/functions/TSCacheWrite.en.rst @@ -24,7 +24,9 @@ TSCacheWrite Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSAction TSCacheWrite(TSCont contp, TSCacheKey key) diff --git a/doc/developer-guide/api/functions/TSClientProtocolStack.en.rst b/doc/developer-guide/api/functions/TSClientProtocolStack.en.rst index 246b47d9bf0..aaff54e1c19 100644 --- a/doc/developer-guide/api/functions/TSClientProtocolStack.en.rst +++ b/doc/developer-guide/api/functions/TSClientProtocolStack.en.rst @@ -25,7 +25,9 @@ TSClientProtocolStack Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnClientProtocolStackGet(TSHttpTxn txnp, int n, char const** result, int* actual) diff --git a/doc/developer-guide/api/functions/TSConfig.en.rst b/doc/developer-guide/api/functions/TSConfig.en.rst index 0002853c488..73041fe43e4 100644 --- a/doc/developer-guide/api/functions/TSConfig.en.rst +++ b/doc/developer-guide/api/functions/TSConfig.en.rst @@ -24,7 +24,9 @@ TSConfig Functions Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. type:: void (*TSConfigDestroyFunc)(void*) .. function:: unsigned int TSConfigSet(unsigned int id, void * data, TSConfigDestroyFunc funcp) diff --git a/doc/developer-guide/api/functions/TSContCall.en.rst b/doc/developer-guide/api/functions/TSContCall.en.rst index 8f99332ac27..a5dcd569733 100644 --- a/doc/developer-guide/api/functions/TSContCall.en.rst +++ b/doc/developer-guide/api/functions/TSContCall.en.rst @@ -24,7 +24,9 @@ TSContCall Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: int TSContCall(TSCont contp, TSEvent event, void * edata) diff --git a/doc/developer-guide/api/functions/TSContCreate.en.rst b/doc/developer-guide/api/functions/TSContCreate.en.rst index 8a02884e12f..774343239e4 100644 --- a/doc/developer-guide/api/functions/TSContCreate.en.rst +++ b/doc/developer-guide/api/functions/TSContCreate.en.rst @@ -24,7 +24,9 @@ TSContCreate Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSCont TSContCreate(TSEventFunc funcp, TSMutex mutexp) diff --git a/doc/developer-guide/api/functions/TSContDataGet.en.rst b/doc/developer-guide/api/functions/TSContDataGet.en.rst index 79c6eb3e4e2..00ca8147f6f 100644 --- a/doc/developer-guide/api/functions/TSContDataGet.en.rst +++ b/doc/developer-guide/api/functions/TSContDataGet.en.rst @@ -24,7 +24,9 @@ TSContDataGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void* TSContDataGet(TSCont contp) diff --git a/doc/developer-guide/api/functions/TSContDataSet.en.rst b/doc/developer-guide/api/functions/TSContDataSet.en.rst index 349e724a975..4e00c31592c 100644 --- a/doc/developer-guide/api/functions/TSContDataSet.en.rst +++ b/doc/developer-guide/api/functions/TSContDataSet.en.rst @@ -24,7 +24,9 @@ TSContDataSet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSContDataSet(TSCont contp, void * data) diff --git a/doc/developer-guide/api/functions/TSContDestroy.en.rst b/doc/developer-guide/api/functions/TSContDestroy.en.rst index 53b6e1e8ce7..d973fcc3959 100644 --- a/doc/developer-guide/api/functions/TSContDestroy.en.rst +++ b/doc/developer-guide/api/functions/TSContDestroy.en.rst @@ -24,7 +24,9 @@ TSContDestroy Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSContDestroy(TSCont contp) diff --git a/doc/developer-guide/api/functions/TSContMutexGet.en.rst b/doc/developer-guide/api/functions/TSContMutexGet.en.rst index fe2b8f3eddd..4986b08eba3 100644 --- a/doc/developer-guide/api/functions/TSContMutexGet.en.rst +++ b/doc/developer-guide/api/functions/TSContMutexGet.en.rst @@ -24,7 +24,9 @@ TSContMutexGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSMutex TSContMutexGet(TSCont contp) diff --git a/doc/developer-guide/api/functions/TSContSchedule.en.rst b/doc/developer-guide/api/functions/TSContSchedule.en.rst index dea45b01004..8984174abf8 100644 --- a/doc/developer-guide/api/functions/TSContSchedule.en.rst +++ b/doc/developer-guide/api/functions/TSContSchedule.en.rst @@ -24,7 +24,9 @@ TSContSchedule Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSAction TSContSchedule(TSCont contp, TSHRTime timeout) diff --git a/doc/developer-guide/api/functions/TSContScheduleOnPool.en.rst b/doc/developer-guide/api/functions/TSContScheduleOnPool.en.rst index f35ddb95fa9..019aad39ac1 100644 --- a/doc/developer-guide/api/functions/TSContScheduleOnPool.en.rst +++ b/doc/developer-guide/api/functions/TSContScheduleOnPool.en.rst @@ -24,7 +24,9 @@ TSContScheduleOnPool Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSAction TSContScheduleOnPool(TSCont contp, TSHRTime timeout, TSThreadPool tp) diff --git a/doc/developer-guide/api/functions/TSContScheduleOnThread.en.rst b/doc/developer-guide/api/functions/TSContScheduleOnThread.en.rst index fed6313c4e8..5e196f9a833 100644 --- a/doc/developer-guide/api/functions/TSContScheduleOnThread.en.rst +++ b/doc/developer-guide/api/functions/TSContScheduleOnThread.en.rst @@ -24,7 +24,9 @@ TSContScheduleOnThread Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSAction TSContScheduleOnThread(TSCont contp, TSHRTime timeout, TSEventThread ethread) diff --git a/doc/developer-guide/api/functions/TSContThreadAffinityClear.en.rst b/doc/developer-guide/api/functions/TSContThreadAffinityClear.en.rst index ef17ae0cddc..b5d1e325473 100644 --- a/doc/developer-guide/api/functions/TSContThreadAffinityClear.en.rst +++ b/doc/developer-guide/api/functions/TSContThreadAffinityClear.en.rst @@ -24,7 +24,9 @@ TSContThreadAffinityClear Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSContThreadAffinityClear(TSCont contp) diff --git a/doc/developer-guide/api/functions/TSContThreadAffinityGet.en.rst b/doc/developer-guide/api/functions/TSContThreadAffinityGet.en.rst index 2bc4955ad19..322240395bb 100644 --- a/doc/developer-guide/api/functions/TSContThreadAffinityGet.en.rst +++ b/doc/developer-guide/api/functions/TSContThreadAffinityGet.en.rst @@ -24,7 +24,9 @@ TSContThreadAffinityGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSEventThread TSContThreadAffinityGet(TSCont contp) diff --git a/doc/developer-guide/api/functions/TSContThreadAffinitySet.en.rst b/doc/developer-guide/api/functions/TSContThreadAffinitySet.en.rst index 5b355130af8..56aaf85b580 100644 --- a/doc/developer-guide/api/functions/TSContThreadAffinitySet.en.rst +++ b/doc/developer-guide/api/functions/TSContThreadAffinitySet.en.rst @@ -24,7 +24,9 @@ TSContThreadAffinitySet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSContThreadAffinitySet(TSCont contp, TSEventThread ethread) diff --git a/doc/developer-guide/api/functions/TSDebug.en.rst b/doc/developer-guide/api/functions/TSDebug.en.rst index 110131bbf63..3273dbd91d2 100644 --- a/doc/developer-guide/api/functions/TSDebug.en.rst +++ b/doc/developer-guide/api/functions/TSDebug.en.rst @@ -26,7 +26,9 @@ Traffic Server Debugging APIs. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSError(const char * format, ...) .. function:: void TSFatal(const char * format, ...) diff --git a/doc/developer-guide/api/functions/TSEventThreadSelf.en.rst b/doc/developer-guide/api/functions/TSEventThreadSelf.en.rst index 0c7728aac6b..badb24a33ea 100644 --- a/doc/developer-guide/api/functions/TSEventThreadSelf.en.rst +++ b/doc/developer-guide/api/functions/TSEventThreadSelf.en.rst @@ -24,7 +24,9 @@ TSEventThreadSelf Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSEventThread TSEventThreadSelf(void) diff --git a/doc/developer-guide/api/functions/TSHostLookup.en.rst b/doc/developer-guide/api/functions/TSHostLookup.en.rst index dc350ad8f52..d4accda71d3 100644 --- a/doc/developer-guide/api/functions/TSHostLookup.en.rst +++ b/doc/developer-guide/api/functions/TSHostLookup.en.rst @@ -24,7 +24,9 @@ TSHostLookup Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSAction TSHostLookup(TSCont contp, const char * hostname, size_t namelen) diff --git a/doc/developer-guide/api/functions/TSHostLookupResultAddrGet.en.rst b/doc/developer-guide/api/functions/TSHostLookupResultAddrGet.en.rst index daff4e8ccfd..35522837e89 100644 --- a/doc/developer-guide/api/functions/TSHostLookupResultAddrGet.en.rst +++ b/doc/developer-guide/api/functions/TSHostLookupResultAddrGet.en.rst @@ -24,7 +24,9 @@ TSHostLookupResultAddrGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: sockaddr const* TSHostLookupResultAddrGet(TSHostLookupResult lookup_result) diff --git a/doc/developer-guide/api/functions/TSHttpArgs.en.rst b/doc/developer-guide/api/functions/TSHttpArgs.en.rst index d1526807d66..fec1dd00f86 100644 --- a/doc/developer-guide/api/functions/TSHttpArgs.en.rst +++ b/doc/developer-guide/api/functions/TSHttpArgs.en.rst @@ -23,7 +23,9 @@ TSHttpArgs Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnArgIndexReserve(const char * name, const char * description, int * arg_idx) .. function:: TSReturnCode TSHttpTxnArgIndexNameLookup(const char * name, int * arg__idx, const char ** description) diff --git a/doc/developer-guide/api/functions/TSHttpConnect.en.rst b/doc/developer-guide/api/functions/TSHttpConnect.en.rst index 958346ea853..547ec5079fa 100644 --- a/doc/developer-guide/api/functions/TSHttpConnect.en.rst +++ b/doc/developer-guide/api/functions/TSHttpConnect.en.rst @@ -24,7 +24,9 @@ TSHttpConnect Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSVConn TSHttpConnect(sockaddr const * addr) diff --git a/doc/developer-guide/api/functions/TSHttpConnectWithPluginId.en.rst b/doc/developer-guide/api/functions/TSHttpConnectWithPluginId.en.rst index 0f6186f5ec9..fd3b7cc1d96 100644 --- a/doc/developer-guide/api/functions/TSHttpConnectWithPluginId.en.rst +++ b/doc/developer-guide/api/functions/TSHttpConnectWithPluginId.en.rst @@ -29,7 +29,9 @@ as if it came from a client. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSVConn TSHttpConnectWithPluginId(sockaddr const * addr, char const * tag, int64_t id) diff --git a/doc/developer-guide/api/functions/TSHttpHdrClone.en.rst b/doc/developer-guide/api/functions/TSHttpHdrClone.en.rst index ab7ee2ab576..de88b09b35a 100644 --- a/doc/developer-guide/api/functions/TSHttpHdrClone.en.rst +++ b/doc/developer-guide/api/functions/TSHttpHdrClone.en.rst @@ -24,7 +24,9 @@ TSHttpHdrClone Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpHdrClone(TSMBuffer dest_bufp, TSMBuffer src_bufp, TSMLoc src_hdr, TSMLoc * locp) diff --git a/doc/developer-guide/api/functions/TSHttpHdrCopy.en.rst b/doc/developer-guide/api/functions/TSHttpHdrCopy.en.rst index feff3e2dd00..88e597d2844 100644 --- a/doc/developer-guide/api/functions/TSHttpHdrCopy.en.rst +++ b/doc/developer-guide/api/functions/TSHttpHdrCopy.en.rst @@ -28,7 +28,9 @@ Copies the contents of the HTTP header located at :arg:`src_loc` within Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpHdrCopy(TSMBuffer dest_bufp, TSMLoc dest_offset, TSMBuffer src_bufp, TSMLoc src_offset) diff --git a/doc/developer-guide/api/functions/TSHttpHdrCreate.en.rst b/doc/developer-guide/api/functions/TSHttpHdrCreate.en.rst index a4a7a8226e9..a478a66dab8 100644 --- a/doc/developer-guide/api/functions/TSHttpHdrCreate.en.rst +++ b/doc/developer-guide/api/functions/TSHttpHdrCreate.en.rst @@ -24,7 +24,9 @@ TSHttpHdrCreate Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSMLoc TSHttpHdrCreate(TSMBuffer bufp) diff --git a/doc/developer-guide/api/functions/TSHttpHdrDestroy.en.rst b/doc/developer-guide/api/functions/TSHttpHdrDestroy.en.rst index 2bf8254d1ff..a56b2b6d454 100644 --- a/doc/developer-guide/api/functions/TSHttpHdrDestroy.en.rst +++ b/doc/developer-guide/api/functions/TSHttpHdrDestroy.en.rst @@ -24,7 +24,9 @@ TSHttpHdrDestroy Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSHttpHdrDestroy(TSMBuffer bufp, TSMLoc offset) diff --git a/doc/developer-guide/api/functions/TSHttpHdrHostGet.en.rst b/doc/developer-guide/api/functions/TSHttpHdrHostGet.en.rst index 710834f2965..420b17307e9 100644 --- a/doc/developer-guide/api/functions/TSHttpHdrHostGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpHdrHostGet.en.rst @@ -24,7 +24,9 @@ TSHttpHdrHostGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: const char* TSHttpHdrHostGet(TSMBuffer bufp, TSMLoc offset, int * length) diff --git a/doc/developer-guide/api/functions/TSHttpHdrLengthGet.en.rst b/doc/developer-guide/api/functions/TSHttpHdrLengthGet.en.rst index 495ef1a991c..12e4a43870b 100644 --- a/doc/developer-guide/api/functions/TSHttpHdrLengthGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpHdrLengthGet.en.rst @@ -24,7 +24,9 @@ TSHttpHdrLengthGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: int TSHttpHdrLengthGet(TSMBuffer bufp, TSMLoc mloc) diff --git a/doc/developer-guide/api/functions/TSHttpHdrMethodGet.en.rst b/doc/developer-guide/api/functions/TSHttpHdrMethodGet.en.rst index f3eaec8c17c..eda364a4d2f 100644 --- a/doc/developer-guide/api/functions/TSHttpHdrMethodGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpHdrMethodGet.en.rst @@ -24,7 +24,9 @@ TSHttpHdrMethodGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: const char* TSHttpHdrMethodGet(TSMBuffer bufp, TSMLoc offset, int * length) diff --git a/doc/developer-guide/api/functions/TSHttpHdrMethodSet.en.rst b/doc/developer-guide/api/functions/TSHttpHdrMethodSet.en.rst index bded2e11616..1ec1973226e 100644 --- a/doc/developer-guide/api/functions/TSHttpHdrMethodSet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpHdrMethodSet.en.rst @@ -24,7 +24,9 @@ TSHttpHdrMethodSet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpHdrMethodSet(TSMBuffer bufp, TSMLoc offset, const char * value, int length) diff --git a/doc/developer-guide/api/functions/TSHttpHdrPrint.en.rst b/doc/developer-guide/api/functions/TSHttpHdrPrint.en.rst index 1f6c1d75392..51b7b998914 100644 --- a/doc/developer-guide/api/functions/TSHttpHdrPrint.en.rst +++ b/doc/developer-guide/api/functions/TSHttpHdrPrint.en.rst @@ -24,7 +24,9 @@ TSHttpHdrPrint Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSHttpHdrPrint(TSMBuffer bufp, TSMLoc offset, TSIOBuffer iobufp) diff --git a/doc/developer-guide/api/functions/TSHttpHdrReasonGet.en.rst b/doc/developer-guide/api/functions/TSHttpHdrReasonGet.en.rst index b3565197710..2a49d5fcc58 100644 --- a/doc/developer-guide/api/functions/TSHttpHdrReasonGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpHdrReasonGet.en.rst @@ -24,7 +24,9 @@ TSHttpHdrReasonGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: const char* TSHttpHdrReasonGet(TSMBuffer bufp, TSMLoc offset, int * length) diff --git a/doc/developer-guide/api/functions/TSHttpHdrReasonLookup.en.rst b/doc/developer-guide/api/functions/TSHttpHdrReasonLookup.en.rst index 9b85b15e0bb..4d97f2e319a 100644 --- a/doc/developer-guide/api/functions/TSHttpHdrReasonLookup.en.rst +++ b/doc/developer-guide/api/functions/TSHttpHdrReasonLookup.en.rst @@ -21,7 +21,9 @@ TSHttpHdrReasonLookup Synopsis -------- -`#include ` +.. code-block:: cpp + + #include .. c:function:: const char* TSHttpHdrReasonLookup(TSHttpStatus status) diff --git a/doc/developer-guide/api/functions/TSHttpHdrReasonSet.en.rst b/doc/developer-guide/api/functions/TSHttpHdrReasonSet.en.rst index a1b15249e8d..3f35d99bb77 100644 --- a/doc/developer-guide/api/functions/TSHttpHdrReasonSet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpHdrReasonSet.en.rst @@ -24,7 +24,9 @@ TSHttpHdrReasonSet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpHdrReasonSet(TSMBuffer bufp, TSMLoc offset, const char * value, int length) diff --git a/doc/developer-guide/api/functions/TSHttpHdrStatusGet.en.rst b/doc/developer-guide/api/functions/TSHttpHdrStatusGet.en.rst index 7d2e31dbfbe..5a6c9e499f7 100644 --- a/doc/developer-guide/api/functions/TSHttpHdrStatusGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpHdrStatusGet.en.rst @@ -24,7 +24,9 @@ TSHttpHdrStatusGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSHttpStatus TSHttpHdrStatusGet(TSMBuffer bufp, TSMLoc offset) diff --git a/doc/developer-guide/api/functions/TSHttpHdrStatusSet.en.rst b/doc/developer-guide/api/functions/TSHttpHdrStatusSet.en.rst index bccc5e4bfeb..5dbb3a70d58 100644 --- a/doc/developer-guide/api/functions/TSHttpHdrStatusSet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpHdrStatusSet.en.rst @@ -24,7 +24,9 @@ TSHttpHdrStatusSet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpHdrStatusSet(TSMBuffer bufp, TSMLoc offset, TSHttpStatus status) diff --git a/doc/developer-guide/api/functions/TSHttpHdrTypeGet.en.rst b/doc/developer-guide/api/functions/TSHttpHdrTypeGet.en.rst index c0adeeb5c3a..4c3ce6769fb 100644 --- a/doc/developer-guide/api/functions/TSHttpHdrTypeGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpHdrTypeGet.en.rst @@ -24,7 +24,9 @@ TSHttpHdrTypeGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSHttpType TSHttpHdrTypeGet(TSMBuffer bufp, TSMLoc offset) diff --git a/doc/developer-guide/api/functions/TSHttpHdrTypeSet.en.rst b/doc/developer-guide/api/functions/TSHttpHdrTypeSet.en.rst index edfada47594..302af2adede 100644 --- a/doc/developer-guide/api/functions/TSHttpHdrTypeSet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpHdrTypeSet.en.rst @@ -24,7 +24,9 @@ TSHttpHdrTypeSet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpHdrTypeSet(TSMBuffer bufp, TSMLoc offset, TSHttpType type) diff --git a/doc/developer-guide/api/functions/TSHttpHdrUrlGet.en.rst b/doc/developer-guide/api/functions/TSHttpHdrUrlGet.en.rst index 555ede1715c..f474ce4981d 100644 --- a/doc/developer-guide/api/functions/TSHttpHdrUrlGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpHdrUrlGet.en.rst @@ -24,7 +24,9 @@ TSHttpHdrUrlGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpHdrUrlGet(TSMBuffer bufp, TSMLoc offset, TSMLoc * locp) diff --git a/doc/developer-guide/api/functions/TSHttpHdrUrlSet.en.rst b/doc/developer-guide/api/functions/TSHttpHdrUrlSet.en.rst index 5a10097f81f..6b64f3b6268 100644 --- a/doc/developer-guide/api/functions/TSHttpHdrUrlSet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpHdrUrlSet.en.rst @@ -24,7 +24,9 @@ TSHttpHdrUrlSet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpHdrUrlSet(TSMBuffer bufp, TSMLoc offset, TSMLoc url) diff --git a/doc/developer-guide/api/functions/TSHttpHdrVersionGet.en.rst b/doc/developer-guide/api/functions/TSHttpHdrVersionGet.en.rst index 6dfceada1fb..861a7822d0e 100644 --- a/doc/developer-guide/api/functions/TSHttpHdrVersionGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpHdrVersionGet.en.rst @@ -24,7 +24,9 @@ TSHttpHdrVersionGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: int TSHttpHdrVersionGet(TSMBuffer bufp, TSMLoc offset) diff --git a/doc/developer-guide/api/functions/TSHttpHdrVersionSet.en.rst b/doc/developer-guide/api/functions/TSHttpHdrVersionSet.en.rst index a63cbd83a73..5abc6db7904 100644 --- a/doc/developer-guide/api/functions/TSHttpHdrVersionSet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpHdrVersionSet.en.rst @@ -24,7 +24,9 @@ TSHttpHdrVersionSet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpHdrVersionSet(TSMBuffer bufp, TSMLoc offset, int ver) diff --git a/doc/developer-guide/api/functions/TSHttpHookAdd.en.rst b/doc/developer-guide/api/functions/TSHttpHookAdd.en.rst index 6443ae10b75..9536a3f88d1 100644 --- a/doc/developer-guide/api/functions/TSHttpHookAdd.en.rst +++ b/doc/developer-guide/api/functions/TSHttpHookAdd.en.rst @@ -27,7 +27,9 @@ Intercept Traffic Server events. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSHttpHookAdd(TSHttpHookID id, TSCont contp) .. function:: void TSHttpSsnHookAdd(TSHttpSsn ssnp, TSHttpHookID id, TSCont contp) diff --git a/doc/developer-guide/api/functions/TSHttpOverridableConfig.en.rst b/doc/developer-guide/api/functions/TSHttpOverridableConfig.en.rst index a3c063ba3c6..2af73e20b93 100644 --- a/doc/developer-guide/api/functions/TSHttpOverridableConfig.en.rst +++ b/doc/developer-guide/api/functions/TSHttpOverridableConfig.en.rst @@ -27,7 +27,9 @@ TSHttpOverridableConfig Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnConfigIntSet(TSHttpTxn txnp, TSOverridableConfigKey key, TSMgmtInt value) diff --git a/doc/developer-guide/api/functions/TSHttpParserCreate.en.rst b/doc/developer-guide/api/functions/TSHttpParserCreate.en.rst index e8974ac6f50..d03d1fb37ac 100644 --- a/doc/developer-guide/api/functions/TSHttpParserCreate.en.rst +++ b/doc/developer-guide/api/functions/TSHttpParserCreate.en.rst @@ -27,7 +27,9 @@ Parse HTTP headers from memory buffers. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSHttpParser TSHttpParserCreate(void) .. function:: void TSHttpParserClear(TSHttpParser parser) diff --git a/doc/developer-guide/api/functions/TSHttpSsnClientFdGet.en.rst b/doc/developer-guide/api/functions/TSHttpSsnClientFdGet.en.rst index 8ecf094eba2..1134ad4822d 100644 --- a/doc/developer-guide/api/functions/TSHttpSsnClientFdGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpSsnClientFdGet.en.rst @@ -21,7 +21,9 @@ TSHttpSsnClientFdGet Synopsis -------- -`#include ` +.. code-block:: cpp + + #include .. c:function:: TSReturnCode TSHttpSsnClientFdGet(TSHttpTxn txnp, int *fdp) diff --git a/doc/developer-guide/api/functions/TSHttpSsnIdGet.en.rst b/doc/developer-guide/api/functions/TSHttpSsnIdGet.en.rst index a9b30aef44d..23ee8b2bf34 100644 --- a/doc/developer-guide/api/functions/TSHttpSsnIdGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpSsnIdGet.en.rst @@ -24,7 +24,9 @@ Returns the unique identifier for client session. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: int64_t TSHttpSsnIdGet(TSHttpSsn ssnp) diff --git a/doc/developer-guide/api/functions/TSHttpSsnReenable.en.rst b/doc/developer-guide/api/functions/TSHttpSsnReenable.en.rst index 9dd0002d2ff..450f5ce554d 100644 --- a/doc/developer-guide/api/functions/TSHttpSsnReenable.en.rst +++ b/doc/developer-guide/api/functions/TSHttpSsnReenable.en.rst @@ -24,7 +24,9 @@ TSHttpSsnReenable Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSHttpSsnReenable(TSHttpSsn ssnp, TSEvent event) diff --git a/doc/developer-guide/api/functions/TSHttpTxnAborted.en.rst b/doc/developer-guide/api/functions/TSHttpTxnAborted.en.rst index d0638c51adf..afa0658a4a7 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnAborted.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnAborted.en.rst @@ -24,7 +24,9 @@ TSHttpTxnAborted Synopsis -------- -`#include ` +.. code-block:: cpp + + #include .. c:function:: TSReturnCode TSHttpTxnAborted(TSHttpTxn txnp) @@ -39,4 +41,4 @@ Return values ------------- The API returns :c:data:`TS_SUCCESS`, if the requested transaction is aborted, -:c:data:`TS_ERROR` otherwise. \ No newline at end of file +:c:data:`TS_ERROR` otherwise. diff --git a/doc/developer-guide/api/functions/TSHttpTxnCacheLookupStatusGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnCacheLookupStatusGet.en.rst index d9d1b6fd44d..04a33bac3a6 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnCacheLookupStatusGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnCacheLookupStatusGet.en.rst @@ -24,7 +24,9 @@ TSHttpTxnCacheLookupStatusGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnCacheLookupStatusGet(TSHttpTxn txnp, int * lookup_status) diff --git a/doc/developer-guide/api/functions/TSHttpTxnCacheLookupUrlGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnCacheLookupUrlGet.en.rst index 7f6545941ae..4b5acc346db 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnCacheLookupUrlGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnCacheLookupUrlGet.en.rst @@ -24,7 +24,9 @@ TSHttpTxnCacheLookupUrlGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnCacheLookupUrlGet(TSHttpTxn txnp, TSMBuffer bufp, TSMLoc offset) @@ -41,7 +43,9 @@ TSHttpTxnCacheLookupUrlSet Synopsis -------- -`#include ` +.. code-block:: cpp + + #include .. c:function:: TSReturnCode TSHttpTxnCacheLookupUrlSet(TSHttpTxn txnp, TSMBuffer bufp, TSMLoc offset) diff --git a/doc/developer-guide/api/functions/TSHttpTxnCachedReqGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnCachedReqGet.en.rst index 7fb6117b95c..215f6f73f93 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnCachedReqGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnCachedReqGet.en.rst @@ -24,7 +24,9 @@ TSHttpTxnCachedReqGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnCachedReqGet(TSHttpTxn txnp, TSMBuffer * bufp, TSMLoc * offset) diff --git a/doc/developer-guide/api/functions/TSHttpTxnCachedRespGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnCachedRespGet.en.rst index 15823039ce3..48257a4d446 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnCachedRespGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnCachedRespGet.en.rst @@ -24,7 +24,9 @@ TSHttpTxnCachedRespGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnCachedRespGet(TSHttpTxn txnp, TSMBuffer * bufp, TSMLoc * offset) diff --git a/doc/developer-guide/api/functions/TSHttpTxnClientFdGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnClientFdGet.en.rst index 4c61160696e..5a4f68239ce 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnClientFdGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnClientFdGet.en.rst @@ -21,7 +21,9 @@ TSHttpTxnClientFdGet Synopsis -------- -`#include ` +.. code-block:: cpp + + #include .. c:function:: TSReturnCode TSHttpTxnClientFdGet(TSHttpTxn txnp, int *fdp) diff --git a/doc/developer-guide/api/functions/TSHttpTxnClientPacketDscpSet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnClientPacketDscpSet.en.rst index 0370735f463..47fc7ab3ca3 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnClientPacketDscpSet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnClientPacketDscpSet.en.rst @@ -23,7 +23,9 @@ TSHttpTxnClientPacketDscpSet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnClientPacketDscpSet(TSHttpTxn txnp, int dscp) diff --git a/doc/developer-guide/api/functions/TSHttpTxnClientPacketMarkSet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnClientPacketMarkSet.en.rst index 437f528b036..1f3cac5f72d 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnClientPacketMarkSet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnClientPacketMarkSet.en.rst @@ -23,7 +23,9 @@ TSHttpTxnClientPacketMarkSet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnClientPacketMarkSet(TSHttpTxn txnp, int mark) diff --git a/doc/developer-guide/api/functions/TSHttpTxnClientPacketTosSet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnClientPacketTosSet.en.rst index f1b694b9167..47b6dce243a 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnClientPacketTosSet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnClientPacketTosSet.en.rst @@ -23,7 +23,9 @@ TSHttpTxnClientPacketTosSet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnClientPacketTosSet(TSHttpTxn txnp, int tos) diff --git a/doc/developer-guide/api/functions/TSHttpTxnClientReqGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnClientReqGet.en.rst index 1d59ab13970..b421e35a848 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnClientReqGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnClientReqGet.en.rst @@ -24,7 +24,9 @@ TSHttpTxnClientReqGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnClientReqGet(TSHttpTxn txnp, TSMBuffer * bufp, TSMLoc * offset) diff --git a/doc/developer-guide/api/functions/TSHttpTxnClientRespGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnClientRespGet.en.rst index cd93d94b3e6..fb5a72c0773 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnClientRespGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnClientRespGet.en.rst @@ -24,7 +24,9 @@ TSHttpTxnClientRespGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnClientRespGet(TSHttpTxn txnp, TSMBuffer * bufp, TSMLoc * offset) diff --git a/doc/developer-guide/api/functions/TSHttpTxnErrorBodySet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnErrorBodySet.en.rst index 52fc4c01c71..082ba18d7b1 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnErrorBodySet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnErrorBodySet.en.rst @@ -26,7 +26,9 @@ Sets an error type body to a transaction. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSHttpTxnErrorBodySet(TSHttpTxn txnp, char * buf, size_t buflength, char * mimetype) diff --git a/doc/developer-guide/api/functions/TSHttpTxnIncomingAddrGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnIncomingAddrGet.en.rst index cd691c13464..773b523be84 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnIncomingAddrGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnIncomingAddrGet.en.rst @@ -24,7 +24,9 @@ Get the incoming proxy address on which a client's connection is accepted. Synopsis -------- -`#include ` +.. code-block:: cpp + + #include .. c:function:: sockaddr const* TSHttpTxnIncomingAddrGet(TSHttpTxn txnp) diff --git a/doc/developer-guide/api/functions/TSHttpTxnInfoIntGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnInfoIntGet.en.rst index a8d2eeaa882..f2899660c65 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnInfoIntGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnInfoIntGet.en.rst @@ -21,7 +21,9 @@ TSHttpTxnInfoIntGet Synopsis -------- -`#include ` +.. code-block:: cpp + + #include .. c:function:: TSReturnCode TSHttpTxnInfoIntGet(TSHttpTxn txnp, TSHttpTxnInfoKey key, TSMgmtInt * value) diff --git a/doc/developer-guide/api/functions/TSHttpTxnIntercept.en.rst b/doc/developer-guide/api/functions/TSHttpTxnIntercept.en.rst index 52db4ab8ee6..43160b18f7b 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnIntercept.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnIntercept.en.rst @@ -27,7 +27,9 @@ origin server. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSHttpTxnIntercept(TSCont contp, TSHttpTxn txnp) diff --git a/doc/developer-guide/api/functions/TSHttpTxnIsCacheable.en.rst b/doc/developer-guide/api/functions/TSHttpTxnIsCacheable.en.rst index 58f40e467a9..bfb61cf9eaa 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnIsCacheable.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnIsCacheable.en.rst @@ -21,7 +21,9 @@ TSHttpTxnIsCacheable Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnIsCacheable(TSHttpTxn txnp, TSMBuffer request, TSMBuffer response) diff --git a/doc/developer-guide/api/functions/TSHttpTxnIsInternal.en.rst b/doc/developer-guide/api/functions/TSHttpTxnIsInternal.en.rst index d0804bbc538..a3dd6757d51 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnIsInternal.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnIsInternal.en.rst @@ -24,7 +24,9 @@ Test whether a request is internally-generated. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: int TSHttpTxnIsInternal(TSHttpTxn txnp) .. function:: int TSHttpSsnIsInternal(TSHttpSsn ssnp) diff --git a/doc/developer-guide/api/functions/TSHttpTxnIsWebsocket.en.rst b/doc/developer-guide/api/functions/TSHttpTxnIsWebsocket.en.rst index c60dc9dbf72..e73f84556b0 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnIsWebsocket.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnIsWebsocket.en.rst @@ -24,7 +24,9 @@ Test whether a request is attempting to initiate Websocket connection. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: int TSHttpTxnIsWebsocket(TSHttpTxn txnp) diff --git a/doc/developer-guide/api/functions/TSHttpTxnMilestoneGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnMilestoneGet.en.rst index 1c0ee733053..d7bf321082a 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnMilestoneGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnMilestoneGet.en.rst @@ -27,7 +27,9 @@ Get a specified :arg:`milestone` timer value for the current transaction. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnMilestoneGet(TSHttpTxn txnp, TSMilestonesType milestone, TSHRTime * time) diff --git a/doc/developer-guide/api/functions/TSHttpTxnNextHopAddrGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnNextHopAddrGet.en.rst index 366acdb7379..34440ccc5bf 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnNextHopAddrGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnNextHopAddrGet.en.rst @@ -24,7 +24,9 @@ TSHttpTxnNextHopAddrGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: sockaddr const * TSHttpTxnNextHopAddrGet(TSHttpTxn txnp) diff --git a/doc/developer-guide/api/functions/TSHttpTxnNextHopNameGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnNextHopNameGet.en.rst index b1feeb7ebc0..a918da067d6 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnNextHopNameGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnNextHopNameGet.en.rst @@ -24,7 +24,9 @@ TSHttpTxnNextHopNameGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: const char *TSHttpTxnNextHopNameGet(TSHttpTxn txnp) diff --git a/doc/developer-guide/api/functions/TSHttpTxnOutgoingAddrGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnOutgoingAddrGet.en.rst index c20ed298f82..4f1b99ad336 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnOutgoingAddrGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnOutgoingAddrGet.en.rst @@ -26,7 +26,9 @@ Get or set the local IP address for outbound connections. Synopsis -------- -`#include ` +.. code-block:: cpp + + #include .. c:function:: sockaddr const* TSHttpTxnOutgoingAddrGet(TSHttpTxn txnp) .. c:function:: TSReturnCode TSHttpTxnOutgoingAddrSet(TSHttpTxn txnp, sockaddr const* addr) diff --git a/doc/developer-guide/api/functions/TSHttpTxnParentProxySet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnParentProxySet.en.rst index 8da767d5a41..33e976999ff 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnParentProxySet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnParentProxySet.en.rst @@ -26,7 +26,9 @@ Sets the parent proxy :arg:`hostname` and :arg:`port`. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSHttpTxnParentProxySet(TSHttpTxn txnp, const char * hostname, int port) diff --git a/doc/developer-guide/api/functions/TSHttpTxnParentSelectionUrlGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnParentSelectionUrlGet.en.rst index 405423407b2..5c48e2b2973 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnParentSelectionUrlGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnParentSelectionUrlGet.en.rst @@ -27,7 +27,9 @@ Traffic Server Parent Selection consistent hash URL manipulation API. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnParentSelectionUrlSet(TSHttpTxn txnp, TSMBuffer bufp, TSMLoc offset) .. function:: TSReturnCode TSHttpTxnParentSelectionUrlGet(TSHttpTxn txnp, TSMBuffer bufp, TSMLoc offset) diff --git a/doc/developer-guide/api/functions/TSHttpTxnPluginTagGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnPluginTagGet.en.rst index 4bf895b51f4..5286c277879 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnPluginTagGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnPluginTagGet.en.rst @@ -24,7 +24,9 @@ Fetch the tag of the plugin that created this transaction. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: const char * TSHttpTxnPluginTagGet(TSHttpTxn txnp) diff --git a/doc/developer-guide/api/functions/TSHttpTxnRedoCacheLookup.en.rst b/doc/developer-guide/api/functions/TSHttpTxnRedoCacheLookup.en.rst index 01f174b274a..ee3da4210c8 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnRedoCacheLookup.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnRedoCacheLookup.en.rst @@ -24,7 +24,9 @@ TSHttpTxnRedoCacheLookup Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnRedoCacheLookup(TSHttpTxn txnp, const char *url, int length) diff --git a/doc/developer-guide/api/functions/TSHttpTxnReenable.en.rst b/doc/developer-guide/api/functions/TSHttpTxnReenable.en.rst index 4fc364aae10..808226f6983 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnReenable.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnReenable.en.rst @@ -27,7 +27,9 @@ processing the current hook. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSHttpTxnReenable(TSHttpTxn txnp, TSEvent event) diff --git a/doc/developer-guide/api/functions/TSHttpTxnServerAddrGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnServerAddrGet.en.rst index 800634e8e58..e5f327a39de 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnServerAddrGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnServerAddrGet.en.rst @@ -24,7 +24,9 @@ TSHttpTxnServerAddrGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: sockaddr const* TSHttpTxnServerAddrGet(TSHttpTxn txnp) diff --git a/doc/developer-guide/api/functions/TSHttpTxnServerAddrSet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnServerAddrSet.en.rst index 5100513e1a2..1633f3f0b21 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnServerAddrSet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnServerAddrSet.en.rst @@ -24,7 +24,9 @@ TSHttpTxnServerAddrSet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnServerAddrSet(TSHttpTxn txnp, struct sockaddr const* addr) diff --git a/doc/developer-guide/api/functions/TSHttpTxnServerFdGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnServerFdGet.en.rst index 1b0f6e0baa6..10254dcbed5 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnServerFdGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnServerFdGet.en.rst @@ -21,7 +21,9 @@ TSHttpTxnServerFdGet Synopsis -------- -`#include ` +.. code-block:: cpp + + #include .. c:function:: TSReturnCode TSHttpTxnServerFdGet(TSHttpTxn txnp, int *fdp) diff --git a/doc/developer-guide/api/functions/TSHttpTxnServerIntercept.en.rst b/doc/developer-guide/api/functions/TSHttpTxnServerIntercept.en.rst index bc70ecc5883..50c7d8839ab 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnServerIntercept.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnServerIntercept.en.rst @@ -27,7 +27,9 @@ Intercept origin server requests. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSHttpTxnServerIntercept(TSCont contp, TSHttpTxn txnp) diff --git a/doc/developer-guide/api/functions/TSHttpTxnServerPacketDscpSet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnServerPacketDscpSet.en.rst index 1fc10085f9f..0ff43285b53 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnServerPacketDscpSet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnServerPacketDscpSet.en.rst @@ -25,7 +25,9 @@ Change packet DSCP for the server side connection. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnServerPacketDscpSet(TSHttpTxn txnp, int dscp) diff --git a/doc/developer-guide/api/functions/TSHttpTxnServerPacketMarkSet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnServerPacketMarkSet.en.rst index af31dd84ed3..0fb6c1d5c28 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnServerPacketMarkSet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnServerPacketMarkSet.en.rst @@ -25,7 +25,9 @@ Change packet firewall mark for the server side connection. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnServerPacketMarkSet(TSHttpTxn txnp, int mark) diff --git a/doc/developer-guide/api/functions/TSHttpTxnServerPacketTosSet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnServerPacketTosSet.en.rst index c412be1d08f..04ef74c3c5e 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnServerPacketTosSet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnServerPacketTosSet.en.rst @@ -25,7 +25,9 @@ Change packet TOS for the server side connection. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnServerPacketTosSet(TSHttpTxn txnp, int tos) diff --git a/doc/developer-guide/api/functions/TSHttpTxnServerPush.en.rst b/doc/developer-guide/api/functions/TSHttpTxnServerPush.en.rst index ca37c3122bc..3e43cd26ad3 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnServerPush.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnServerPush.en.rst @@ -24,7 +24,9 @@ TSHttpTxnServerPush Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len) diff --git a/doc/developer-guide/api/functions/TSHttpTxnServerReqGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnServerReqGet.en.rst index f9cb31e6a85..bed19dc5b6c 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnServerReqGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnServerReqGet.en.rst @@ -24,7 +24,9 @@ TSHttpTxnServerReqGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnServerReqGet(TSHttpTxn txnp, TSMBuffer * bufp, TSMLoc * obj) diff --git a/doc/developer-guide/api/functions/TSHttpTxnServerRespGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnServerRespGet.en.rst index 3113297b871..0665ba868b4 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnServerRespGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnServerRespGet.en.rst @@ -24,7 +24,9 @@ TSHttpTxnServerRespGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnServerRespGet(TSHttpTxn txnp, TSMBuffer * bufp, TSMLoc * offset) diff --git a/doc/developer-guide/api/functions/TSHttpTxnSsnGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnSsnGet.en.rst index 9c0b8ea1dce..f963f1ef453 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnSsnGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnSsnGet.en.rst @@ -24,7 +24,9 @@ TSHttpTxnSsnGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSHttpSsn TSHttpTxnSsnGet(TSHttpTxn txnp) diff --git a/doc/developer-guide/api/functions/TSHttpTxnTransformRespGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnTransformRespGet.en.rst index f27fc1eba34..bd3922d2db1 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnTransformRespGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnTransformRespGet.en.rst @@ -24,7 +24,9 @@ TSHttpTxnTransformRespGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSHttpTxnTransformRespGet(TSHttpTxn txnp, TSMBuffer * bufp, TSMLoc * offset) diff --git a/doc/developer-guide/api/functions/TSHttpTxnTransformedRespCache.en.rst b/doc/developer-guide/api/functions/TSHttpTxnTransformedRespCache.en.rst index a84077f75bf..3864b67af9f 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnTransformedRespCache.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnTransformedRespCache.en.rst @@ -24,7 +24,9 @@ TSHttpTxnTransformedRespCache Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSHttpTxnTransformedRespCache(TSHttpTxn txnp, int on) diff --git a/doc/developer-guide/api/functions/TSHttpTxnUntransformedRespCache.en.rst b/doc/developer-guide/api/functions/TSHttpTxnUntransformedRespCache.en.rst index 33e77db4028..5a1047d33dc 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnUntransformedRespCache.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnUntransformedRespCache.en.rst @@ -24,7 +24,9 @@ TSHttpTxnUntransformedRespCache Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSHttpTxnUntransformedRespCache(TSHttpTxn txnp, int on) diff --git a/doc/developer-guide/api/functions/TSIOBufferBlockReadStart.en.rst b/doc/developer-guide/api/functions/TSIOBufferBlockReadStart.en.rst index 1208e4eac11..bf0122f34fb 100644 --- a/doc/developer-guide/api/functions/TSIOBufferBlockReadStart.en.rst +++ b/doc/developer-guide/api/functions/TSIOBufferBlockReadStart.en.rst @@ -24,7 +24,9 @@ TSIOBufferBlockReadStart Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: const char * TSIOBufferBlockReadStart(TSIOBufferBlock blockp, TSIOBufferReader readerp, int64_t * avail) diff --git a/doc/developer-guide/api/functions/TSIOBufferCopy.en.rst b/doc/developer-guide/api/functions/TSIOBufferCopy.en.rst index 81f70a00df5..a46d8a9124a 100644 --- a/doc/developer-guide/api/functions/TSIOBufferCopy.en.rst +++ b/doc/developer-guide/api/functions/TSIOBufferCopy.en.rst @@ -24,7 +24,9 @@ TSIOBufferCopy Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: int64_t TSIOBufferCopy(TSIOBuffer bufp, TSIOBufferReader readerp, int64_t length, int64_t offset) diff --git a/doc/developer-guide/api/functions/TSIOBufferCreate.en.rst b/doc/developer-guide/api/functions/TSIOBufferCreate.en.rst index ee7086316df..55fe62cd361 100644 --- a/doc/developer-guide/api/functions/TSIOBufferCreate.en.rst +++ b/doc/developer-guide/api/functions/TSIOBufferCreate.en.rst @@ -27,7 +27,9 @@ Traffic Server IO buffer API. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSIOBuffer TSIOBufferCreate(void) .. function:: TSIOBuffer TSIOBufferSizedCreate(TSIOBufferSizeIndex index) diff --git a/doc/developer-guide/api/functions/TSIOBufferReader.en.rst b/doc/developer-guide/api/functions/TSIOBufferReader.en.rst index 031eb9591b4..ad0243baa89 100644 --- a/doc/developer-guide/api/functions/TSIOBufferReader.en.rst +++ b/doc/developer-guide/api/functions/TSIOBufferReader.en.rst @@ -25,7 +25,10 @@ Traffic Server IO buffer reader API. Synopsis ======== -`#include ` + +.. code-block:: cpp + + #include .. function:: TSIOBufferReader TSIOBufferReaderAlloc(TSIOBuffer bufp) .. function:: TSIOBufferReader TSIOBufferReaderClone(TSIOBufferReader readerp) diff --git a/doc/developer-guide/api/functions/TSInstallDirGet.en.rst b/doc/developer-guide/api/functions/TSInstallDirGet.en.rst index e9097a3ca02..023bbc5e7ea 100644 --- a/doc/developer-guide/api/functions/TSInstallDirGet.en.rst +++ b/doc/developer-guide/api/functions/TSInstallDirGet.en.rst @@ -27,7 +27,9 @@ Return Traffic Server installation directories. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: const char * TSInstallDirGet(void) .. function:: const char * TSConfigDirGet(void) diff --git a/doc/developer-guide/api/functions/TSIpStringToAddr.en.rst b/doc/developer-guide/api/functions/TSIpStringToAddr.en.rst index 298705a976d..2b74ed1d16e 100644 --- a/doc/developer-guide/api/functions/TSIpStringToAddr.en.rst +++ b/doc/developer-guide/api/functions/TSIpStringToAddr.en.rst @@ -24,7 +24,9 @@ TSIpStringToAddr Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSIpStringToAddr(const char * str, int str_len, sockaddr* addr) diff --git a/doc/developer-guide/api/functions/TSLifecycleHookAdd.en.rst b/doc/developer-guide/api/functions/TSLifecycleHookAdd.en.rst index 0d150dc7b66..e3913c1a615 100644 --- a/doc/developer-guide/api/functions/TSLifecycleHookAdd.en.rst +++ b/doc/developer-guide/api/functions/TSLifecycleHookAdd.en.rst @@ -26,7 +26,9 @@ TSLifecycleHookAdd Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSLifecycleHookAdd(TSLifecycleHookID id, TSCont contp) diff --git a/doc/developer-guide/api/functions/TSMBufferCreate.en.rst b/doc/developer-guide/api/functions/TSMBufferCreate.en.rst index 4b7e3c7ed77..cf6c38b6500 100644 --- a/doc/developer-guide/api/functions/TSMBufferCreate.en.rst +++ b/doc/developer-guide/api/functions/TSMBufferCreate.en.rst @@ -25,7 +25,9 @@ Traffic Server marshall buffer API. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSMBuffer TSMBufferCreate(void) .. function:: TSReturnCode TSMBufferDestroy(TSMBuffer bufp) diff --git a/doc/developer-guide/api/functions/TSMgmtCounterGet.en.rst b/doc/developer-guide/api/functions/TSMgmtCounterGet.en.rst index 860a603eb4c..31641dd5783 100644 --- a/doc/developer-guide/api/functions/TSMgmtCounterGet.en.rst +++ b/doc/developer-guide/api/functions/TSMgmtCounterGet.en.rst @@ -24,7 +24,9 @@ TSMgmtCounterGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMgmtCounterGet(const char * var_name, TSMgmtCounter * result) diff --git a/doc/developer-guide/api/functions/TSMgmtFloatGet.en.rst b/doc/developer-guide/api/functions/TSMgmtFloatGet.en.rst index 651f16eca69..77cee428786 100644 --- a/doc/developer-guide/api/functions/TSMgmtFloatGet.en.rst +++ b/doc/developer-guide/api/functions/TSMgmtFloatGet.en.rst @@ -24,7 +24,9 @@ TSMgmtFloatGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMgmtFloatGet(const char * var_name, TSMgmtFloat * result) diff --git a/doc/developer-guide/api/functions/TSMgmtIntGet.en.rst b/doc/developer-guide/api/functions/TSMgmtIntGet.en.rst index e7f6c082d80..3c920ebe069 100644 --- a/doc/developer-guide/api/functions/TSMgmtIntGet.en.rst +++ b/doc/developer-guide/api/functions/TSMgmtIntGet.en.rst @@ -24,7 +24,9 @@ TSMgmtIntGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMgmtIntGet(const char * var_name, TSMgmtInt * result) diff --git a/doc/developer-guide/api/functions/TSMgmtSourceGet.en.rst b/doc/developer-guide/api/functions/TSMgmtSourceGet.en.rst index 593d3dd6dfe..6839b5044c7 100644 --- a/doc/developer-guide/api/functions/TSMgmtSourceGet.en.rst +++ b/doc/developer-guide/api/functions/TSMgmtSourceGet.en.rst @@ -24,7 +24,9 @@ TSMgmtSourceGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMgmtSourceGet(const char * var_name, TSMgmtSource * result) diff --git a/doc/developer-guide/api/functions/TSMgmtStringGet.en.rst b/doc/developer-guide/api/functions/TSMgmtStringGet.en.rst index 0fe3e088738..c507f1f1d14 100644 --- a/doc/developer-guide/api/functions/TSMgmtStringGet.en.rst +++ b/doc/developer-guide/api/functions/TSMgmtStringGet.en.rst @@ -24,7 +24,9 @@ TSMgmtStringGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMgmtStringGet(const char * var_name, TSMgmtString * result) diff --git a/doc/developer-guide/api/functions/TSMgmtUpdateRegister.en.rst b/doc/developer-guide/api/functions/TSMgmtUpdateRegister.en.rst index d9f2f9d6f70..b841466bae1 100644 --- a/doc/developer-guide/api/functions/TSMgmtUpdateRegister.en.rst +++ b/doc/developer-guide/api/functions/TSMgmtUpdateRegister.en.rst @@ -24,7 +24,9 @@ TSMgmtUpdateRegister Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSMgmtUpdateRegister(TSCont contp, const char * plugin_name) diff --git a/doc/developer-guide/api/functions/TSMimeHdrClone.en.rst b/doc/developer-guide/api/functions/TSMimeHdrClone.en.rst index b7cc1ada9fb..ef41671b2e4 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrClone.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrClone.en.rst @@ -24,7 +24,9 @@ TSMimeHdrClone Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrClone(TSMBuffer dest_bufp, TSMBuffer src_bufp, TSMLoc src_hdr, TSMLoc * locp) diff --git a/doc/developer-guide/api/functions/TSMimeHdrCopy.en.rst b/doc/developer-guide/api/functions/TSMimeHdrCopy.en.rst index ea43b688efa..21a1c25778f 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrCopy.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrCopy.en.rst @@ -24,7 +24,9 @@ TSMimeHdrCopy Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrCopy(TSMBuffer dest_bufp, TSMLoc dest_offset, TSMBuffer src_bufp, TSMLoc src_offset) diff --git a/doc/developer-guide/api/functions/TSMimeHdrCreate.en.rst b/doc/developer-guide/api/functions/TSMimeHdrCreate.en.rst index d8a7c08f75b..52928a3af4d 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrCreate.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrCreate.en.rst @@ -24,7 +24,9 @@ TSMimeHdrCreate Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrCreate(TSMBuffer bufp, TSMLoc * locp) diff --git a/doc/developer-guide/api/functions/TSMimeHdrDestroy.en.rst b/doc/developer-guide/api/functions/TSMimeHdrDestroy.en.rst index 532c27fc92b..412cfcfc9fe 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrDestroy.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrDestroy.en.rst @@ -24,7 +24,9 @@ TSMimeHdrDestroy Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrDestroy(TSMBuffer bufp, TSMLoc offset) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldAppend.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldAppend.en.rst index 7690fa8b5c6..0cee4dfd455 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldAppend.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldAppend.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldAppend Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrFieldAppend(TSMBuffer bufp, TSMLoc hdr, TSMLoc field) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldClone.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldClone.en.rst index 5f712cd742c..2e9b0de4a80 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldClone.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldClone.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldClone Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrFieldClone(TSMBuffer dest_bufp, TSMLoc dest_hdr, TSMBuffer src_bufp, TSMLoc src_hdr, TSMLoc src_field, TSMLoc * locp) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldCopy.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldCopy.en.rst index 8f7390e3c72..f6efc1a9789 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldCopy.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldCopy.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldCopy Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrFieldCopy(TSMBuffer dest_bufp, TSMLoc dest_hdr, TSMLoc dest_field, TSMBuffer src_bufp, TSMLoc src_hdr, TSMLoc src_field) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldCopyValues.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldCopyValues.en.rst index a7e6ef6870a..e973cfb4121 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldCopyValues.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldCopyValues.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldCopyValues Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrFieldCopyValues(TSMBuffer dest_bufp, TSMLoc dest_hdr, TSMLoc dest_field, TSMBuffer src_bufp, TSMLoc src_hdr, TSMLoc src_field) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldCreate.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldCreate.en.rst index 80cf6351882..76803ee3a7c 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldCreate.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldCreate.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldCreate Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrFieldCreate(TSMBuffer bufp, TSMLoc hdr, TSMLoc * out) .. function:: TSReturnCode TSMimeHdrFieldCreateNamed(TSMBuffer bufp, TSMLoc hdr, const char * name, int name_len, TSMLoc * out) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldDestroy.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldDestroy.en.rst index f14d01dad15..9858e14f861 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldDestroy.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldDestroy.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldDestroy Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrFieldDestroy(TSMBuffer bufp, TSMLoc hdr, TSMLoc field) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldFind.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldFind.en.rst index 3e26efb5e2f..149e07bb262 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldFind.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldFind.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldFind Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSMLoc TSMimeHdrFieldFind(TSMBuffer bufp, TSMLoc hdr, const char * name, int length) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldGet.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldGet.en.rst index 27cbdc38c80..f9f03c6c1b6 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldGet.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldGet.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSMLoc TSMimeHdrFieldGet(TSMBuffer bufp, TSMLoc hdr, int idx) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldLengthGet.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldLengthGet.en.rst index 0b066f9a68a..901ce3d43f1 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldLengthGet.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldLengthGet.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldLengthGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: int TSMimeHdrFieldLengthGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldNameGet.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldNameGet.en.rst index 20a370b528e..72d4cb92974 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldNameGet.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldNameGet.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldNameGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: const char * TSMimeHdrFieldNameGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int * length) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldNameSet.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldNameSet.en.rst index d013f3ee796..a0d033c2bb1 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldNameSet.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldNameSet.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldNameSet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrFieldNameSet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, const char * name, int length) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldNext.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldNext.en.rst index 83e535ff7be..69dd763ea2d 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldNext.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldNext.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldNext Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSMLoc TSMimeHdrFieldNext(TSMBuffer bufp, TSMLoc hdr, TSMLoc field) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldNextDup.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldNextDup.en.rst index 099bf165400..a4877981cc4 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldNextDup.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldNextDup.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldNextDup Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSMLoc TSMimeHdrFieldNextDup(TSMBuffer bufp, TSMLoc hdr, TSMLoc field) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldRemove.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldRemove.en.rst index b35741e80bd..07fe987f2bc 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldRemove.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldRemove.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldRemove Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrFieldRemove(TSMBuffer bufp, TSMLoc hdr, TSMLoc field) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldValueAppend.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldValueAppend.en.rst index 21b5edf8ac3..0596663ba6a 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldValueAppend.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldValueAppend.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldValueAppend Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrFieldValueAppend(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, const char * value, int length) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldValueDateInsert.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldValueDateInsert.en.rst index f80d6218543..4a9789ef9b3 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldValueDateInsert.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldValueDateInsert.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldValueDateInsert Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrFieldValueDateInsert(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, time_t value) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldValueDateSet.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldValueDateSet.en.rst index c8efee44aba..2ed5086c37d 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldValueDateSet.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldValueDateSet.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldValueDateSet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrFieldValueDateSet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, time_t value) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldValueIntSet.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldValueIntSet.en.rst index 3df3feda17e..034ccc06c8e 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldValueIntSet.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldValueIntSet.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldValueIntSet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrFieldValueIntSet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, int value) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldValueStringGet.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldValueStringGet.en.rst index 73237531d75..2a2beb71566 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldValueStringGet.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldValueStringGet.en.rst @@ -26,7 +26,9 @@ Get HTTP MIME header values. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: const char * TSMimeHdrFieldValueStringGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, int * value_len_ptr) .. function:: int TSMimeHdrFieldValueIntGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldValueStringInsert.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldValueStringInsert.en.rst index f679995c780..fcf8e1f9041 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldValueStringInsert.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldValueStringInsert.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldValueStringInsert Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrFieldValueStringInsert(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, const char * value, int length) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldValueStringSet.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldValueStringSet.en.rst index a53a7d503ef..285f3317d66 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldValueStringSet.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldValueStringSet.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldValueStringSet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrFieldValueStringSet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, const char * value, int length) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldValueUintInsert.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldValueUintInsert.en.rst index d7eb5589cfe..5a7ef0852b0 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldValueUintInsert.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldValueUintInsert.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldValueUintInsert Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrFieldValueUintInsert(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, unsigned int value) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldValueUintSet.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldValueUintSet.en.rst index bc8d667a80e..484b17b6c9f 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldValueUintSet.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldValueUintSet.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldValueUintSet Synopsis ========= -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrFieldValueUintSet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, unsigned int value) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldValuesClear.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldValuesClear.en.rst index 0e8eefcb146..7285599f196 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldValuesClear.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldValuesClear.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldValuesClear Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrFieldValuesClear(TSMBuffer bufp, TSMLoc hdr, TSMLoc field) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldValuesCount.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldValuesCount.en.rst index ccadb1fb8ba..d0701f3cccb 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldValuesCount.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldValuesCount.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldValuesCount Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: int TSMimeHdrFieldValuesCount(TSMBuffer bufp, TSMLoc hdr, TSMLoc field) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldsClear.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldsClear.en.rst index 2b43cf7fdb6..1ff98449fe3 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldsClear.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldsClear.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldsClear Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMimeHdrFieldsClear(TSMBuffer bufp, TSMLoc offset) diff --git a/doc/developer-guide/api/functions/TSMimeHdrFieldsCount.en.rst b/doc/developer-guide/api/functions/TSMimeHdrFieldsCount.en.rst index d841e73e663..cc293a39c6c 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrFieldsCount.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrFieldsCount.en.rst @@ -24,7 +24,9 @@ TSMimeHdrFieldsCount Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: int TSMimeHdrFieldsCount(TSMBuffer bufp, TSMLoc offset) diff --git a/doc/developer-guide/api/functions/TSMimeHdrLengthGet.en.rst b/doc/developer-guide/api/functions/TSMimeHdrLengthGet.en.rst index 5f499004817..b8bca00e844 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrLengthGet.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrLengthGet.en.rst @@ -24,7 +24,9 @@ TSMimeHdrLengthGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: int TSMimeHdrLengthGet(TSMBuffer bufp, TSMLoc offset) diff --git a/doc/developer-guide/api/functions/TSMimeHdrParse.en.rst b/doc/developer-guide/api/functions/TSMimeHdrParse.en.rst index 49e4bd083fa..2bcbcbd38e5 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrParse.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrParse.en.rst @@ -24,7 +24,9 @@ TSMimeHdrParse Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSParseResult TSMimeHdrParse(TSMimeParser parser, TSMBuffer bufp, TSMLoc offset, const char ** start, const char * end) diff --git a/doc/developer-guide/api/functions/TSMimeHdrPrint.en.rst b/doc/developer-guide/api/functions/TSMimeHdrPrint.en.rst index 38625e2619b..4cf5af99977 100644 --- a/doc/developer-guide/api/functions/TSMimeHdrPrint.en.rst +++ b/doc/developer-guide/api/functions/TSMimeHdrPrint.en.rst @@ -24,7 +24,9 @@ TSMimeHdrPrint Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSMimeHdrPrint(TSMBuffer bufp, TSMLoc offset, TSIOBuffer iobufp) diff --git a/doc/developer-guide/api/functions/TSMimeParserClear.en.rst b/doc/developer-guide/api/functions/TSMimeParserClear.en.rst index 957f1706842..2d8383f0526 100644 --- a/doc/developer-guide/api/functions/TSMimeParserClear.en.rst +++ b/doc/developer-guide/api/functions/TSMimeParserClear.en.rst @@ -24,7 +24,9 @@ TSMimeParserClear Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSMimeParserClear(TSMimeParser parser) diff --git a/doc/developer-guide/api/functions/TSMimeParserCreate.en.rst b/doc/developer-guide/api/functions/TSMimeParserCreate.en.rst index 8382efdc564..af50929e131 100644 --- a/doc/developer-guide/api/functions/TSMimeParserCreate.en.rst +++ b/doc/developer-guide/api/functions/TSMimeParserCreate.en.rst @@ -24,7 +24,9 @@ TSMimeParserCreate Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSMimeParser TSMimeParserCreate(void) diff --git a/doc/developer-guide/api/functions/TSMimeParserDestroy.en.rst b/doc/developer-guide/api/functions/TSMimeParserDestroy.en.rst index e0367be2929..8bcb98df6c0 100644 --- a/doc/developer-guide/api/functions/TSMimeParserDestroy.en.rst +++ b/doc/developer-guide/api/functions/TSMimeParserDestroy.en.rst @@ -24,7 +24,9 @@ TSMimeParserDestroy Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSMimeParserDestroy(TSMimeParser parser) diff --git a/doc/developer-guide/api/functions/TSMutexCreate.en.rst b/doc/developer-guide/api/functions/TSMutexCreate.en.rst index 0bf24ebc0b7..5a6a25e9a2a 100644 --- a/doc/developer-guide/api/functions/TSMutexCreate.en.rst +++ b/doc/developer-guide/api/functions/TSMutexCreate.en.rst @@ -24,7 +24,9 @@ TSMutexCreate Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSMutex TSMutexCreate(void) diff --git a/doc/developer-guide/api/functions/TSMutexDestroy.en.rst b/doc/developer-guide/api/functions/TSMutexDestroy.en.rst index ab978dba2c0..ca841085046 100644 --- a/doc/developer-guide/api/functions/TSMutexDestroy.en.rst +++ b/doc/developer-guide/api/functions/TSMutexDestroy.en.rst @@ -24,7 +24,9 @@ TSMutexDestroy Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSMutexDestroy(TSMutex mutexp) diff --git a/doc/developer-guide/api/functions/TSMutexLock.en.rst b/doc/developer-guide/api/functions/TSMutexLock.en.rst index 6c9539092e3..11558f2dbae 100644 --- a/doc/developer-guide/api/functions/TSMutexLock.en.rst +++ b/doc/developer-guide/api/functions/TSMutexLock.en.rst @@ -24,7 +24,9 @@ TSMutexLock Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSMutexLock(TSMutex mutexp) diff --git a/doc/developer-guide/api/functions/TSMutexLockTry.en.rst b/doc/developer-guide/api/functions/TSMutexLockTry.en.rst index ed5b56cdf43..8f810b7d870 100644 --- a/doc/developer-guide/api/functions/TSMutexLockTry.en.rst +++ b/doc/developer-guide/api/functions/TSMutexLockTry.en.rst @@ -24,7 +24,9 @@ TSMutexLockTry Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMutexLockTry(TSMutex mutexp) diff --git a/doc/developer-guide/api/functions/TSMutexUnlock.en.rst b/doc/developer-guide/api/functions/TSMutexUnlock.en.rst index 887a12c76a0..37a96a99f23 100644 --- a/doc/developer-guide/api/functions/TSMutexUnlock.en.rst +++ b/doc/developer-guide/api/functions/TSMutexUnlock.en.rst @@ -24,7 +24,9 @@ TSMutexUnlock Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSMutexUnlock(TSMutex mutexp) diff --git a/doc/developer-guide/api/functions/TSNetAccept.en.rst b/doc/developer-guide/api/functions/TSNetAccept.en.rst index bc3646daafd..e7bf427befe 100644 --- a/doc/developer-guide/api/functions/TSNetAccept.en.rst +++ b/doc/developer-guide/api/functions/TSNetAccept.en.rst @@ -24,7 +24,9 @@ TSNetAccept Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSAction TSNetAccept(TSCont contp, int port, int domain, int accept_threads) diff --git a/doc/developer-guide/api/functions/TSNetAcceptNamedProtocol.en.rst b/doc/developer-guide/api/functions/TSNetAcceptNamedProtocol.en.rst index 1edaed44d6d..4d7eefbb9a2 100644 --- a/doc/developer-guide/api/functions/TSNetAcceptNamedProtocol.en.rst +++ b/doc/developer-guide/api/functions/TSNetAcceptNamedProtocol.en.rst @@ -26,7 +26,9 @@ Listen on all SSL ports for connections for the specified protocol name. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSNetAcceptNamedProtocol(TSCont contp, const char * protocol) diff --git a/doc/developer-guide/api/functions/TSNetConnect.en.rst b/doc/developer-guide/api/functions/TSNetConnect.en.rst index 0dea9482757..f661e0533b3 100644 --- a/doc/developer-guide/api/functions/TSNetConnect.en.rst +++ b/doc/developer-guide/api/functions/TSNetConnect.en.rst @@ -24,7 +24,9 @@ TSNetConnect Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSAction TSNetConnect(TSCont contp, sockaddr const * addr) diff --git a/doc/developer-guide/api/functions/TSNetInvokingGet.en.rst b/doc/developer-guide/api/functions/TSNetInvokingGet.en.rst index 876196e4099..0941369e80b 100644 --- a/doc/developer-guide/api/functions/TSNetInvokingGet.en.rst +++ b/doc/developer-guide/api/functions/TSNetInvokingGet.en.rst @@ -24,7 +24,9 @@ TSNetInvokingContGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSCont TSNetInvokingContGet(TSVConn conn) diff --git a/doc/developer-guide/api/functions/TSPluginInit.en.rst b/doc/developer-guide/api/functions/TSPluginInit.en.rst index 232bb79fbe3..6e3c4503599 100644 --- a/doc/developer-guide/api/functions/TSPluginInit.en.rst +++ b/doc/developer-guide/api/functions/TSPluginInit.en.rst @@ -26,7 +26,9 @@ Traffic Server plugin loading and registration. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSPluginInit(int argc, const char* argv[]) .. function:: TSReturnCode TSPluginRegister(TSPluginRegistrationInfo* plugin_info) diff --git a/doc/developer-guide/api/functions/TSRecords.en.rst b/doc/developer-guide/api/functions/TSRecords.en.rst index 37441395e10..b52cb39d4b1 100644 --- a/doc/developer-guide/api/functions/TSRecords.en.rst +++ b/doc/developer-guide/api/functions/TSRecords.en.rst @@ -26,7 +26,9 @@ Traffic Server Records Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSMgmtStringCreate(TSRecordType rec_type, const char* name, \ const TSMgmtString data_default, TSRecordUpdateType update_type, \ diff --git a/doc/developer-guide/api/functions/TSRemap.en.rst b/doc/developer-guide/api/functions/TSRemap.en.rst index 0e8ad4eb8e6..89df430907d 100644 --- a/doc/developer-guide/api/functions/TSRemap.en.rst +++ b/doc/developer-guide/api/functions/TSRemap.en.rst @@ -26,8 +26,10 @@ Traffic Server remap plugin entry points. Synopsis ======== -`#include ` -`#include ` +.. code-block:: cpp + + #include + #include .. function:: TSReturnCode TSRemapInit(TSRemapInterface * api_info, char * errbuff, int errbuff_size) .. function:: void TSRemapPreConfigReload(void) diff --git a/doc/developer-guide/api/functions/TSRemapFromToUrlGet.en.rst b/doc/developer-guide/api/functions/TSRemapFromToUrlGet.en.rst index 75c23e9ed16..6fd5e666327 100644 --- a/doc/developer-guide/api/functions/TSRemapFromToUrlGet.en.rst +++ b/doc/developer-guide/api/functions/TSRemapFromToUrlGet.en.rst @@ -24,7 +24,9 @@ TSRemapFrom/ToUrlGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSRemapFromUrlGet(TSHttpTxn txnp, TSMLoc * urlLocp) .. function:: TSReturnCode TSRemapToUrlGet(TSHttpTxn txnp, TSMLoc * urlLocp) diff --git a/doc/developer-guide/api/functions/TSSslClientCertUpdate.en.rst b/doc/developer-guide/api/functions/TSSslClientCertUpdate.en.rst index 62fa469eaf2..f1abe938c25 100644 --- a/doc/developer-guide/api/functions/TSSslClientCertUpdate.en.rst +++ b/doc/developer-guide/api/functions/TSSslClientCertUpdate.en.rst @@ -26,7 +26,9 @@ Traffic Server TLS client cert update Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSSslClientCertUpdate(const char *cert_path, const char *key_path) diff --git a/doc/developer-guide/api/functions/TSSslClientContext.en.rst b/doc/developer-guide/api/functions/TSSslClientContext.en.rst index f8d4db417e0..ca14c17b11c 100644 --- a/doc/developer-guide/api/functions/TSSslClientContext.en.rst +++ b/doc/developer-guide/api/functions/TSSslClientContext.en.rst @@ -23,7 +23,9 @@ TSSslClientContext Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSSslClientContextsNamesGet(int n, const char **result, int *actual) diff --git a/doc/developer-guide/api/functions/TSSslContext.en.rst b/doc/developer-guide/api/functions/TSSslContext.en.rst index 415e644adcd..e98606c150c 100644 --- a/doc/developer-guide/api/functions/TSSslContext.en.rst +++ b/doc/developer-guide/api/functions/TSSslContext.en.rst @@ -26,7 +26,9 @@ Traffic Server TLS server context. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSSslContext TSSslContextFindByName(const char * name) diff --git a/doc/developer-guide/api/functions/TSSslServerCertUpdate.en.rst b/doc/developer-guide/api/functions/TSSslServerCertUpdate.en.rst index 44acf21105c..6c31ab39802 100644 --- a/doc/developer-guide/api/functions/TSSslServerCertUpdate.en.rst +++ b/doc/developer-guide/api/functions/TSSslServerCertUpdate.en.rst @@ -26,7 +26,9 @@ Traffic Server TLS server cert update Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSSslServerCertUpdate(const char *cert_path, const char *key_path) diff --git a/doc/developer-guide/api/functions/TSSslServerContextCreate.en.rst b/doc/developer-guide/api/functions/TSSslServerContextCreate.en.rst index 4cae0645917..097044c33af 100644 --- a/doc/developer-guide/api/functions/TSSslServerContextCreate.en.rst +++ b/doc/developer-guide/api/functions/TSSslServerContextCreate.en.rst @@ -26,7 +26,9 @@ Traffic Server TLS server context creation. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSSslContext TSSslServerContextCreate(TSSslX509 *cert, char *certname) .. function:: void TSSslContextDestroy(TSSslContext ctx) diff --git a/doc/developer-guide/api/functions/TSSslSession.en.rst b/doc/developer-guide/api/functions/TSSslSession.en.rst index d0870a1f4c0..df902046ecb 100644 --- a/doc/developer-guide/api/functions/TSSslSession.en.rst +++ b/doc/developer-guide/api/functions/TSSslSession.en.rst @@ -24,7 +24,9 @@ TSSslSession Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSSslSession TSSslSessionGet(const TSSslSessionID * sessionid) .. function:: int TSSslSessionGetBuffer(const TSSslSessionID * sessionid, char * buffer, int * len_ptr) diff --git a/doc/developer-guide/api/functions/TSStat.en.rst b/doc/developer-guide/api/functions/TSStat.en.rst index 64b539f2bbc..2988bc17cef 100644 --- a/doc/developer-guide/api/functions/TSStat.en.rst +++ b/doc/developer-guide/api/functions/TSStat.en.rst @@ -28,7 +28,9 @@ in contrast to processing log files. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: int TSStatCreate(const char * name, TSRecordDataType type, TSStatPersistence persistence, TSStatSync sync_style) .. function:: TSReturnCode TSStatFindName(const char * name, int * idx_ptr) diff --git a/doc/developer-guide/api/functions/TSTextLogObjectCreate.en.rst b/doc/developer-guide/api/functions/TSTextLogObjectCreate.en.rst index 10990248134..063bd8a4b07 100644 --- a/doc/developer-guide/api/functions/TSTextLogObjectCreate.en.rst +++ b/doc/developer-guide/api/functions/TSTextLogObjectCreate.en.rst @@ -27,7 +27,9 @@ Traffic Server text logging API. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSTextLogObjectCreate(const char * filename, int mode, TSTextLogObject * new_log_obj) .. function:: TSReturnCode TSTextLogObjectWrite(TSTextLogObject the_object, const char * format, ...) diff --git a/doc/developer-guide/api/functions/TSThreadCreate.en.rst b/doc/developer-guide/api/functions/TSThreadCreate.en.rst index 9d1c5be16ba..b0cc86cf71a 100644 --- a/doc/developer-guide/api/functions/TSThreadCreate.en.rst +++ b/doc/developer-guide/api/functions/TSThreadCreate.en.rst @@ -24,7 +24,9 @@ TSThreadCreate Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSThread TSThreadCreate(TSThreadFunc func, void * data) diff --git a/doc/developer-guide/api/functions/TSThreadDestroy.en.rst b/doc/developer-guide/api/functions/TSThreadDestroy.en.rst index 46df4be89b9..91ffc4a3261 100644 --- a/doc/developer-guide/api/functions/TSThreadDestroy.en.rst +++ b/doc/developer-guide/api/functions/TSThreadDestroy.en.rst @@ -24,7 +24,9 @@ TSThreadDestroy Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSThreadDestroy(TSThread thread) diff --git a/doc/developer-guide/api/functions/TSThreadInit.en.rst b/doc/developer-guide/api/functions/TSThreadInit.en.rst index 0c3590f5308..4d1f88b0fd4 100644 --- a/doc/developer-guide/api/functions/TSThreadInit.en.rst +++ b/doc/developer-guide/api/functions/TSThreadInit.en.rst @@ -24,7 +24,9 @@ TSThreadInit Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSThread TSThreadInit(void) diff --git a/doc/developer-guide/api/functions/TSThreadSelf.en.rst b/doc/developer-guide/api/functions/TSThreadSelf.en.rst index b0d059013de..eedfbddd7f5 100644 --- a/doc/developer-guide/api/functions/TSThreadSelf.en.rst +++ b/doc/developer-guide/api/functions/TSThreadSelf.en.rst @@ -24,7 +24,9 @@ TSThreadSelf Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSThread TSThreadSelf(void) diff --git a/doc/developer-guide/api/functions/TSTrafficServerVersionGet.en.rst b/doc/developer-guide/api/functions/TSTrafficServerVersionGet.en.rst index 076ab1e7294..1d98ab992fd 100644 --- a/doc/developer-guide/api/functions/TSTrafficServerVersionGet.en.rst +++ b/doc/developer-guide/api/functions/TSTrafficServerVersionGet.en.rst @@ -26,7 +26,9 @@ Return Traffic Server version information. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: const char * TSTrafficServerVersionGet(void) .. function:: int TSTrafficServerVersionGetMajor(void) diff --git a/doc/developer-guide/api/functions/TSTransformCreate.en.rst b/doc/developer-guide/api/functions/TSTransformCreate.en.rst index 4beea2ead2b..6735ca8586a 100644 --- a/doc/developer-guide/api/functions/TSTransformCreate.en.rst +++ b/doc/developer-guide/api/functions/TSTransformCreate.en.rst @@ -24,7 +24,9 @@ TSTransformCreate Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSVConn TSTransformCreate(TSEventFunc event_funcp, TSHttpTxn txnp) diff --git a/doc/developer-guide/api/functions/TSTransformOutputVConnGet.en.rst b/doc/developer-guide/api/functions/TSTransformOutputVConnGet.en.rst index 236b9b238cd..a272315c98a 100644 --- a/doc/developer-guide/api/functions/TSTransformOutputVConnGet.en.rst +++ b/doc/developer-guide/api/functions/TSTransformOutputVConnGet.en.rst @@ -24,7 +24,9 @@ TSTransformOutputVConnGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSVConn TSTransformOutputVConnGet(TSVConn connp) diff --git a/doc/developer-guide/api/functions/TSTypes.en.rst b/doc/developer-guide/api/functions/TSTypes.en.rst index 20bed4490ad..e158c97ee62 100644 --- a/doc/developer-guide/api/functions/TSTypes.en.rst +++ b/doc/developer-guide/api/functions/TSTypes.en.rst @@ -28,8 +28,10 @@ TSAPI Types Synopsis ======== -`#include ` -`#include ` +.. code-block:: cpp + + #include + #include Description =========== diff --git a/doc/developer-guide/api/functions/TSUrlCreate.en.rst b/doc/developer-guide/api/functions/TSUrlCreate.en.rst index 6b096d0f51b..7d5a027d67e 100644 --- a/doc/developer-guide/api/functions/TSUrlCreate.en.rst +++ b/doc/developer-guide/api/functions/TSUrlCreate.en.rst @@ -27,7 +27,9 @@ Traffic Server URL object construction API. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSUrlCreate(TSMBuffer bufp, TSMLoc * locp) .. function:: TSReturnCode TSUrlClone(TSMBuffer dest_bufp, TSMBuffer src_bufp, TSMLoc src_url, TSMLoc * locp) diff --git a/doc/developer-guide/api/functions/TSUrlFtpTypeGet.en.rst b/doc/developer-guide/api/functions/TSUrlFtpTypeGet.en.rst index ad363f963c4..ed4edd6f1b5 100644 --- a/doc/developer-guide/api/functions/TSUrlFtpTypeGet.en.rst +++ b/doc/developer-guide/api/functions/TSUrlFtpTypeGet.en.rst @@ -24,7 +24,9 @@ TSUrlFtpTypeGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: int TSUrlFtpTypeGet(TSMBuffer bufp, TSMLoc offset) diff --git a/doc/developer-guide/api/functions/TSUrlFtpTypeSet.en.rst b/doc/developer-guide/api/functions/TSUrlFtpTypeSet.en.rst index f6e99c0b972..fbf2316cb12 100644 --- a/doc/developer-guide/api/functions/TSUrlFtpTypeSet.en.rst +++ b/doc/developer-guide/api/functions/TSUrlFtpTypeSet.en.rst @@ -24,7 +24,9 @@ TSUrlFtpTypeSet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSUrlFtpTypeSet(TSMBuffer bufp, TSMLoc offset, int type) diff --git a/doc/developer-guide/api/functions/TSUrlHostGet.en.rst b/doc/developer-guide/api/functions/TSUrlHostGet.en.rst index d5d2db116e0..3db194cd166 100644 --- a/doc/developer-guide/api/functions/TSUrlHostGet.en.rst +++ b/doc/developer-guide/api/functions/TSUrlHostGet.en.rst @@ -27,7 +27,9 @@ Traffic Server URL component retrieval API. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: const char * TSUrlHostGet(TSMBuffer bufp, TSMLoc offset, int * length) .. function:: const char * TSUrlSchemeGet(TSMBuffer bufp, TSMLoc offset, int * length) diff --git a/doc/developer-guide/api/functions/TSUrlHostSet.en.rst b/doc/developer-guide/api/functions/TSUrlHostSet.en.rst index 4ace0b61356..0b89f8e6e12 100644 --- a/doc/developer-guide/api/functions/TSUrlHostSet.en.rst +++ b/doc/developer-guide/api/functions/TSUrlHostSet.en.rst @@ -27,7 +27,9 @@ Traffic Server URL component manipulation API. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSUrlHostSet(TSMBuffer bufp, TSMLoc offset, const char * value, int length) .. function:: TSReturnCode TSUrlSchemeSet(TSMBuffer bufp, TSMLoc offset, const char * value, int length) diff --git a/doc/developer-guide/api/functions/TSUrlPercentEncode.en.rst b/doc/developer-guide/api/functions/TSUrlPercentEncode.en.rst index f5f13b2916b..4e79ad4e6b6 100644 --- a/doc/developer-guide/api/functions/TSUrlPercentEncode.en.rst +++ b/doc/developer-guide/api/functions/TSUrlPercentEncode.en.rst @@ -27,7 +27,9 @@ Traffic Server URL percent encoding API. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSUrlPercentEncode(TSMBuffer bufp, TSMLoc offset, char * dst, size_t dst_size, size_t * length, const unsigned char * map) .. function:: TSReturnCode TSStringPercentEncode(const char * str, int str_len, char * dst, size_t dst_size, size_t * length, const unsigned char * map) diff --git a/doc/developer-guide/api/functions/TSUrlStringGet.en.rst b/doc/developer-guide/api/functions/TSUrlStringGet.en.rst index 506a5e8d237..1e58cf6c2fc 100644 --- a/doc/developer-guide/api/functions/TSUrlStringGet.en.rst +++ b/doc/developer-guide/api/functions/TSUrlStringGet.en.rst @@ -27,7 +27,9 @@ Traffic Server URL string representations API. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: char * TSUrlStringGet(TSMBuffer bufp, TSMLoc offset, int * length) .. function:: char * TSHttpTxnEffectiveUrlStringGet(TSHttpTxn txn, int * length) diff --git a/doc/developer-guide/api/functions/TSUuidCreate.en.rst b/doc/developer-guide/api/functions/TSUuidCreate.en.rst index 7def6f38813..4e3a68dfd9d 100644 --- a/doc/developer-guide/api/functions/TSUuidCreate.en.rst +++ b/doc/developer-guide/api/functions/TSUuidCreate.en.rst @@ -26,7 +26,9 @@ Traffic Server UUID construction APIs. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSUuid TSUuidCreate(void) .. function:: TSReturnCode TSUuidInitialize(TSUuid uuid, TSUuidVersion v) diff --git a/doc/developer-guide/api/functions/TSVConn.en.rst b/doc/developer-guide/api/functions/TSVConn.en.rst index e3f625b1eb7..e73b7872e72 100644 --- a/doc/developer-guide/api/functions/TSVConn.en.rst +++ b/doc/developer-guide/api/functions/TSVConn.en.rst @@ -26,7 +26,9 @@ Traffic Server APIs to get :type:`TSVConn` from :type:`TSHttpSsn` object Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSVConn TSHttpSsnClientVConnGet(TSHttpSsn ssnp) .. function:: TSVConn TSHttpSsnServerVConnGet(TSHttpSsn ssnp) diff --git a/doc/developer-guide/api/functions/TSVConnAbort.en.rst b/doc/developer-guide/api/functions/TSVConnAbort.en.rst index bb2d528984e..41f98b76af1 100644 --- a/doc/developer-guide/api/functions/TSVConnAbort.en.rst +++ b/doc/developer-guide/api/functions/TSVConnAbort.en.rst @@ -24,7 +24,9 @@ TSVConnAbort Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSVConnAbort(TSVConn connp, int error) diff --git a/doc/developer-guide/api/functions/TSVConnArgs.en.rst b/doc/developer-guide/api/functions/TSVConnArgs.en.rst index 21036694a03..d6e7febad4f 100644 --- a/doc/developer-guide/api/functions/TSVConnArgs.en.rst +++ b/doc/developer-guide/api/functions/TSVConnArgs.en.rst @@ -25,7 +25,9 @@ TSVConnArgs Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSVConnArgIndexReserve(const char * name, const char * description, int * arg_idx) .. function:: TSReturnCode TSVConnArgIndexNameLookup(const char * name, int * arg_idx, const char ** description) diff --git a/doc/developer-guide/api/functions/TSVConnCacheObjectSizeGet.en.rst b/doc/developer-guide/api/functions/TSVConnCacheObjectSizeGet.en.rst index 9411a97302b..c75780e25d4 100644 --- a/doc/developer-guide/api/functions/TSVConnCacheObjectSizeGet.en.rst +++ b/doc/developer-guide/api/functions/TSVConnCacheObjectSizeGet.en.rst @@ -24,7 +24,9 @@ TSVConnCacheObjectSizeGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: int64_t TSVConnCacheObjectSizeGet(TSVConn connp) diff --git a/doc/developer-guide/api/functions/TSVConnClose.en.rst b/doc/developer-guide/api/functions/TSVConnClose.en.rst index a0edc3efb3b..bbd67d9379a 100644 --- a/doc/developer-guide/api/functions/TSVConnClose.en.rst +++ b/doc/developer-guide/api/functions/TSVConnClose.en.rst @@ -24,7 +24,9 @@ TSVConnClose Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSVConnClose(TSVConn connp) diff --git a/doc/developer-guide/api/functions/TSVConnClosedGet.en.rst b/doc/developer-guide/api/functions/TSVConnClosedGet.en.rst index ec102777018..e3608b1d49d 100644 --- a/doc/developer-guide/api/functions/TSVConnClosedGet.en.rst +++ b/doc/developer-guide/api/functions/TSVConnClosedGet.en.rst @@ -24,7 +24,9 @@ TSVConnClosedGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: int TSVConnClosedGet(TSVConn connp) diff --git a/doc/developer-guide/api/functions/TSVConnCreate.en.rst b/doc/developer-guide/api/functions/TSVConnCreate.en.rst index 1e0cd50865b..35d9eec84ad 100644 --- a/doc/developer-guide/api/functions/TSVConnCreate.en.rst +++ b/doc/developer-guide/api/functions/TSVConnCreate.en.rst @@ -24,7 +24,9 @@ TSVConnCreate Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSCont TSVConnCreate(TSEventFunc funcp, TSMutex mutexp) diff --git a/doc/developer-guide/api/functions/TSVConnFdCreate.en.rst b/doc/developer-guide/api/functions/TSVConnFdCreate.en.rst index 48e9aec4392..03fccfa2afd 100644 --- a/doc/developer-guide/api/functions/TSVConnFdCreate.en.rst +++ b/doc/developer-guide/api/functions/TSVConnFdCreate.en.rst @@ -26,7 +26,9 @@ Create a TSVConn from a socket. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSVConn TSVConnFdCreate(int fd) diff --git a/doc/developer-guide/api/functions/TSVConnIsSsl.en.rst b/doc/developer-guide/api/functions/TSVConnIsSsl.en.rst index ba4bbf0cf18..94443bc1a38 100644 --- a/doc/developer-guide/api/functions/TSVConnIsSsl.en.rst +++ b/doc/developer-guide/api/functions/TSVConnIsSsl.en.rst @@ -24,7 +24,9 @@ TSVConnIsSsl Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: int TSVConnIsSsl(TSVConn svc) diff --git a/doc/developer-guide/api/functions/TSVConnProtocol.en.rst b/doc/developer-guide/api/functions/TSVConnProtocol.en.rst index 49d1b88d47d..7bcf994c06b 100644 --- a/doc/developer-guide/api/functions/TSVConnProtocol.en.rst +++ b/doc/developer-guide/api/functions/TSVConnProtocol.en.rst @@ -24,7 +24,9 @@ TSVConnProtocolEnable/Disable Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSVConnProtocolEnable(TSVConn vconn, const char* protocol) .. function:: TSReturnCode TSVConnProtocolDisable(TSVConn vconn, const char* protocol) diff --git a/doc/developer-guide/api/functions/TSVConnRead.en.rst b/doc/developer-guide/api/functions/TSVConnRead.en.rst index 7334de244e5..965b8bc8946 100644 --- a/doc/developer-guide/api/functions/TSVConnRead.en.rst +++ b/doc/developer-guide/api/functions/TSVConnRead.en.rst @@ -24,7 +24,9 @@ TSVConnRead Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSVIO TSVConnRead(TSVConn connp, TSCont contp, TSIOBuffer bufp, int64_t nbytes) diff --git a/doc/developer-guide/api/functions/TSVConnReadVIOGet.en.rst b/doc/developer-guide/api/functions/TSVConnReadVIOGet.en.rst index 33369bb49e2..dfbafd4d9e3 100644 --- a/doc/developer-guide/api/functions/TSVConnReadVIOGet.en.rst +++ b/doc/developer-guide/api/functions/TSVConnReadVIOGet.en.rst @@ -24,7 +24,9 @@ TSVConnReadVIOGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSVIO TSVConnReadVIOGet(TSVConn connp) diff --git a/doc/developer-guide/api/functions/TSVConnReenable.en.rst b/doc/developer-guide/api/functions/TSVConnReenable.en.rst index a7075fc8e7e..fd691128a3a 100644 --- a/doc/developer-guide/api/functions/TSVConnReenable.en.rst +++ b/doc/developer-guide/api/functions/TSVConnReenable.en.rst @@ -24,7 +24,9 @@ TSVConnReenable Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSVConnReenable(TSVConn svc) diff --git a/doc/developer-guide/api/functions/TSVConnShutdown.en.rst b/doc/developer-guide/api/functions/TSVConnShutdown.en.rst index 25b05800bbd..4e36e6bf6d3 100644 --- a/doc/developer-guide/api/functions/TSVConnShutdown.en.rst +++ b/doc/developer-guide/api/functions/TSVConnShutdown.en.rst @@ -24,7 +24,9 @@ TSVConnShutdown Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSVConnShutdown(TSVConn connp, int read, int write) diff --git a/doc/developer-guide/api/functions/TSVConnSslConnectionGet.en.rst b/doc/developer-guide/api/functions/TSVConnSslConnectionGet.en.rst index e4c1c490350..5cb3b60b90c 100644 --- a/doc/developer-guide/api/functions/TSVConnSslConnectionGet.en.rst +++ b/doc/developer-guide/api/functions/TSVConnSslConnectionGet.en.rst @@ -24,7 +24,9 @@ TSVConnSslConnectionGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSSslConnection TSVConnSslConnectionGet(TSVConn svc) diff --git a/doc/developer-guide/api/functions/TSVConnSslVerifyCTXGet.en.rst b/doc/developer-guide/api/functions/TSVConnSslVerifyCTXGet.en.rst index c35a25c5658..f84e4b44507 100644 --- a/doc/developer-guide/api/functions/TSVConnSslVerifyCTXGet.en.rst +++ b/doc/developer-guide/api/functions/TSVConnSslVerifyCTXGet.en.rst @@ -24,7 +24,9 @@ TSVConnSslVerifyCTXGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSSslVerifyCTX TSVConnSslVerifyCTXGet(TSVConn svc) diff --git a/doc/developer-guide/api/functions/TSVConnTunnel.en.rst b/doc/developer-guide/api/functions/TSVConnTunnel.en.rst index e27b8113760..cfbb8a18d94 100644 --- a/doc/developer-guide/api/functions/TSVConnTunnel.en.rst +++ b/doc/developer-guide/api/functions/TSVConnTunnel.en.rst @@ -24,7 +24,9 @@ TSVConnTunnel Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSReturnCode TSVConnTunnel(TSVConn svc) diff --git a/doc/developer-guide/api/functions/TSVConnWrite.en.rst b/doc/developer-guide/api/functions/TSVConnWrite.en.rst index 10b0fa611cb..acce4d8edc2 100644 --- a/doc/developer-guide/api/functions/TSVConnWrite.en.rst +++ b/doc/developer-guide/api/functions/TSVConnWrite.en.rst @@ -24,7 +24,9 @@ TSVConnWrite Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSVIO TSVConnWrite(TSVConn connp, TSCont contp, TSIOBufferReader readerp, int64_t nbytes) diff --git a/doc/developer-guide/api/functions/TSVConnWriteVIOGet.en.rst b/doc/developer-guide/api/functions/TSVConnWriteVIOGet.en.rst index 802812a1f5e..25061f2c81d 100644 --- a/doc/developer-guide/api/functions/TSVConnWriteVIOGet.en.rst +++ b/doc/developer-guide/api/functions/TSVConnWriteVIOGet.en.rst @@ -24,7 +24,9 @@ TSVConnWriteVIOGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSVIO TSVConnWriteVIOGet(TSVConn connp) diff --git a/doc/developer-guide/api/functions/TSVIOBufferGet.en.rst b/doc/developer-guide/api/functions/TSVIOBufferGet.en.rst index bf90c841496..0c6db9c7c7b 100644 --- a/doc/developer-guide/api/functions/TSVIOBufferGet.en.rst +++ b/doc/developer-guide/api/functions/TSVIOBufferGet.en.rst @@ -24,7 +24,9 @@ TSVIOBufferGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSIOBuffer TSVIOBufferGet(TSVIO viop) diff --git a/doc/developer-guide/api/functions/TSVIOContGet.en.rst b/doc/developer-guide/api/functions/TSVIOContGet.en.rst index 418eeeb5b37..37dd977530f 100644 --- a/doc/developer-guide/api/functions/TSVIOContGet.en.rst +++ b/doc/developer-guide/api/functions/TSVIOContGet.en.rst @@ -24,7 +24,9 @@ TSVIOContGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSCont TSVIOContGet(TSVIO viop) diff --git a/doc/developer-guide/api/functions/TSVIOMutexGet.en.rst b/doc/developer-guide/api/functions/TSVIOMutexGet.en.rst index 160cc1bdcb3..0b28ef2e6db 100644 --- a/doc/developer-guide/api/functions/TSVIOMutexGet.en.rst +++ b/doc/developer-guide/api/functions/TSVIOMutexGet.en.rst @@ -24,7 +24,9 @@ TSVIOMutexGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSMutex TSVIOMutexGet(TSVIO viop) diff --git a/doc/developer-guide/api/functions/TSVIONBytesGet.en.rst b/doc/developer-guide/api/functions/TSVIONBytesGet.en.rst index 242deb83a0a..6e15b46afbb 100644 --- a/doc/developer-guide/api/functions/TSVIONBytesGet.en.rst +++ b/doc/developer-guide/api/functions/TSVIONBytesGet.en.rst @@ -24,7 +24,9 @@ TSVIONBytesGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: int64_t TSVIONBytesGet(TSVIO viop) diff --git a/doc/developer-guide/api/functions/TSVIONBytesSet.en.rst b/doc/developer-guide/api/functions/TSVIONBytesSet.en.rst index 27a1bfe01dc..bd4ec83bfd6 100644 --- a/doc/developer-guide/api/functions/TSVIONBytesSet.en.rst +++ b/doc/developer-guide/api/functions/TSVIONBytesSet.en.rst @@ -24,7 +24,9 @@ TSVIONBytesSet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSVIONBytesSet(TSVIO viop, int64_t nbytes) diff --git a/doc/developer-guide/api/functions/TSVIONDoneGet.en.rst b/doc/developer-guide/api/functions/TSVIONDoneGet.en.rst index 79f7edfb7a1..fccb2776763 100644 --- a/doc/developer-guide/api/functions/TSVIONDoneGet.en.rst +++ b/doc/developer-guide/api/functions/TSVIONDoneGet.en.rst @@ -24,7 +24,9 @@ TSVIONDoneGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: int64_t TSVIONDoneGet(TSVIO viop) diff --git a/doc/developer-guide/api/functions/TSVIONDoneSet.en.rst b/doc/developer-guide/api/functions/TSVIONDoneSet.en.rst index f4483798d07..0580c7cb401 100644 --- a/doc/developer-guide/api/functions/TSVIONDoneSet.en.rst +++ b/doc/developer-guide/api/functions/TSVIONDoneSet.en.rst @@ -24,7 +24,9 @@ TSVIONDoneSet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSVIONDoneSet(TSVIO viop, int64_t ndone) diff --git a/doc/developer-guide/api/functions/TSVIONTodoGet.en.rst b/doc/developer-guide/api/functions/TSVIONTodoGet.en.rst index 91c6acd597c..249c5483843 100644 --- a/doc/developer-guide/api/functions/TSVIONTodoGet.en.rst +++ b/doc/developer-guide/api/functions/TSVIONTodoGet.en.rst @@ -24,7 +24,9 @@ TSVIONTodoGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: int64_t TSVIONTodoGet(TSVIO viop) diff --git a/doc/developer-guide/api/functions/TSVIOReaderGet.en.rst b/doc/developer-guide/api/functions/TSVIOReaderGet.en.rst index 559a6e6f941..22f1782fbc6 100644 --- a/doc/developer-guide/api/functions/TSVIOReaderGet.en.rst +++ b/doc/developer-guide/api/functions/TSVIOReaderGet.en.rst @@ -24,7 +24,9 @@ TSVIOReaderGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSIOBufferReader TSVIOReaderGet(TSVIO viop) diff --git a/doc/developer-guide/api/functions/TSVIOReenable.en.rst b/doc/developer-guide/api/functions/TSVIOReenable.en.rst index 7103f882296..c1f5d8ead0e 100644 --- a/doc/developer-guide/api/functions/TSVIOReenable.en.rst +++ b/doc/developer-guide/api/functions/TSVIOReenable.en.rst @@ -24,7 +24,9 @@ TSVIOReenable Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSVIOReenable(TSVIO viop) diff --git a/doc/developer-guide/api/functions/TSVIOVConnGet.en.rst b/doc/developer-guide/api/functions/TSVIOVConnGet.en.rst index 21b27ec53d2..781304e32be 100644 --- a/doc/developer-guide/api/functions/TSVIOVConnGet.en.rst +++ b/doc/developer-guide/api/functions/TSVIOVConnGet.en.rst @@ -24,7 +24,9 @@ TSVIOVConnGet Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSVConn TSVIOVConnGet(TSVIO viop) diff --git a/doc/developer-guide/api/functions/TSfclose.en.rst b/doc/developer-guide/api/functions/TSfclose.en.rst index 47b3f857b10..ac49f90def5 100644 --- a/doc/developer-guide/api/functions/TSfclose.en.rst +++ b/doc/developer-guide/api/functions/TSfclose.en.rst @@ -24,7 +24,9 @@ TSfclose Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSfclose(TSFile filep) diff --git a/doc/developer-guide/api/functions/TSfflush.en.rst b/doc/developer-guide/api/functions/TSfflush.en.rst index 0f73c130a02..68ff2310703 100644 --- a/doc/developer-guide/api/functions/TSfflush.en.rst +++ b/doc/developer-guide/api/functions/TSfflush.en.rst @@ -24,7 +24,9 @@ TSfflush Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void TSfflush(TSFile filep) diff --git a/doc/developer-guide/api/functions/TSfgets.en.rst b/doc/developer-guide/api/functions/TSfgets.en.rst index 1a55ff05f8f..eaf0143e05f 100644 --- a/doc/developer-guide/api/functions/TSfgets.en.rst +++ b/doc/developer-guide/api/functions/TSfgets.en.rst @@ -24,7 +24,9 @@ TSfgets Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: char* TSfgets(TSFile filep, char * buf, size_t length) diff --git a/doc/developer-guide/api/functions/TSfopen.en.rst b/doc/developer-guide/api/functions/TSfopen.en.rst index 52e3f176048..7e45be7afc0 100644 --- a/doc/developer-guide/api/functions/TSfopen.en.rst +++ b/doc/developer-guide/api/functions/TSfopen.en.rst @@ -24,7 +24,9 @@ TSfopen Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: TSFile TSfopen(const char * filename, const char * mode) diff --git a/doc/developer-guide/api/functions/TSfread.en.rst b/doc/developer-guide/api/functions/TSfread.en.rst index 52b14211a09..1a87e24c8e8 100644 --- a/doc/developer-guide/api/functions/TSfread.en.rst +++ b/doc/developer-guide/api/functions/TSfread.en.rst @@ -24,7 +24,9 @@ TSfread Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: ssize_t TSfread(TSFile filep, void * buf, size_t length) diff --git a/doc/developer-guide/api/functions/TSfwrite.en.rst b/doc/developer-guide/api/functions/TSfwrite.en.rst index 3b064ace9db..f716b7e1e89 100644 --- a/doc/developer-guide/api/functions/TSfwrite.en.rst +++ b/doc/developer-guide/api/functions/TSfwrite.en.rst @@ -24,7 +24,9 @@ TSfwrite Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: ssize_t TSfwrite(TSFile filep, const void * buf, size_t length) diff --git a/doc/developer-guide/api/functions/TSmalloc.en.rst b/doc/developer-guide/api/functions/TSmalloc.en.rst index 79bc249504d..cbaf27568c5 100644 --- a/doc/developer-guide/api/functions/TSmalloc.en.rst +++ b/doc/developer-guide/api/functions/TSmalloc.en.rst @@ -27,7 +27,9 @@ Traffic Server memory allocation API. Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. function:: void * TSmalloc(size_t size) .. function:: void * TSrealloc(void * ptr , size_t size) diff --git a/doc/developer-guide/api/types/TSCacheDataType.en.rst b/doc/developer-guide/api/types/TSCacheDataType.en.rst index 39dfdd72f89..15f0f5746ec 100644 --- a/doc/developer-guide/api/types/TSCacheDataType.en.rst +++ b/doc/developer-guide/api/types/TSCacheDataType.en.rst @@ -22,7 +22,9 @@ TSCacheDataType Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSCacheDataType diff --git a/doc/developer-guide/api/types/TSCacheError.en.rst b/doc/developer-guide/api/types/TSCacheError.en.rst index 3d1e22a7885..f7b83447fc7 100644 --- a/doc/developer-guide/api/types/TSCacheError.en.rst +++ b/doc/developer-guide/api/types/TSCacheError.en.rst @@ -22,7 +22,9 @@ TSCacheError Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSCacheError diff --git a/doc/developer-guide/api/types/TSCacheLookupResult.en.rst b/doc/developer-guide/api/types/TSCacheLookupResult.en.rst index b6d364d26c4..92862a29a73 100644 --- a/doc/developer-guide/api/types/TSCacheLookupResult.en.rst +++ b/doc/developer-guide/api/types/TSCacheLookupResult.en.rst @@ -22,7 +22,9 @@ TSCacheLookupResult Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSCacheLookupResult diff --git a/doc/developer-guide/api/types/TSCacheScanResult.en.rst b/doc/developer-guide/api/types/TSCacheScanResult.en.rst index 1e29c5688ba..302a1e09d8f 100644 --- a/doc/developer-guide/api/types/TSCacheScanResult.en.rst +++ b/doc/developer-guide/api/types/TSCacheScanResult.en.rst @@ -22,7 +22,9 @@ TSCacheScanResult Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSCacheScanResult diff --git a/doc/developer-guide/api/types/TSEvent.en.rst b/doc/developer-guide/api/types/TSEvent.en.rst index 8261cfcef1d..b557a27a2fc 100644 --- a/doc/developer-guide/api/types/TSEvent.en.rst +++ b/doc/developer-guide/api/types/TSEvent.en.rst @@ -23,7 +23,9 @@ TSEvent Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSEvent diff --git a/doc/developer-guide/api/types/TSFetchWakeUpOptions.en.rst b/doc/developer-guide/api/types/TSFetchWakeUpOptions.en.rst index b2e14cdb19e..17e78197530 100644 --- a/doc/developer-guide/api/types/TSFetchWakeUpOptions.en.rst +++ b/doc/developer-guide/api/types/TSFetchWakeUpOptions.en.rst @@ -22,7 +22,9 @@ TSFetchWakeUpOptions Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSFetchWakeUpOptions diff --git a/doc/developer-guide/api/types/TSHttpHookID.en.rst b/doc/developer-guide/api/types/TSHttpHookID.en.rst index 663759581fc..02715b2b48a 100644 --- a/doc/developer-guide/api/types/TSHttpHookID.en.rst +++ b/doc/developer-guide/api/types/TSHttpHookID.en.rst @@ -24,7 +24,9 @@ TSHttpHookID Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSHttpHookID diff --git a/doc/developer-guide/api/types/TSHttpStatus.en.rst b/doc/developer-guide/api/types/TSHttpStatus.en.rst index f68904967b9..7c4a524a8b5 100644 --- a/doc/developer-guide/api/types/TSHttpStatus.en.rst +++ b/doc/developer-guide/api/types/TSHttpStatus.en.rst @@ -24,7 +24,9 @@ TSHttpStatus Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSHttpStatus diff --git a/doc/developer-guide/api/types/TSHttpType.en.rst b/doc/developer-guide/api/types/TSHttpType.en.rst index c8ddc9d9b10..f067cbee547 100644 --- a/doc/developer-guide/api/types/TSHttpType.en.rst +++ b/doc/developer-guide/api/types/TSHttpType.en.rst @@ -22,7 +22,9 @@ TSHttpType Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSHttpType diff --git a/doc/developer-guide/api/types/TSIOBuffersSizeIndex.en.rst b/doc/developer-guide/api/types/TSIOBuffersSizeIndex.en.rst index 4b67491a46d..901045fd036 100644 --- a/doc/developer-guide/api/types/TSIOBuffersSizeIndex.en.rst +++ b/doc/developer-guide/api/types/TSIOBuffersSizeIndex.en.rst @@ -22,7 +22,9 @@ TSIOBuffersSizeIndex Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSIOBuffersSizeIndex diff --git a/doc/developer-guide/api/types/TSLookingUpType.en.rst b/doc/developer-guide/api/types/TSLookingUpType.en.rst index 51ee7d298c9..d71c9a76d02 100644 --- a/doc/developer-guide/api/types/TSLookingUpType.en.rst +++ b/doc/developer-guide/api/types/TSLookingUpType.en.rst @@ -22,7 +22,9 @@ TSLookingUpType Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSLookingUpType diff --git a/doc/developer-guide/api/types/TSOverridableConfigKey.en.rst b/doc/developer-guide/api/types/TSOverridableConfigKey.en.rst index 7eeb349b748..d24b1a26152 100644 --- a/doc/developer-guide/api/types/TSOverridableConfigKey.en.rst +++ b/doc/developer-guide/api/types/TSOverridableConfigKey.en.rst @@ -22,7 +22,9 @@ TSOverridableConfigKey Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSOverridableConfigKey diff --git a/doc/developer-guide/api/types/TSParseResult.en.rst b/doc/developer-guide/api/types/TSParseResult.en.rst index 5fb321d4439..8777709c72d 100644 --- a/doc/developer-guide/api/types/TSParseResult.en.rst +++ b/doc/developer-guide/api/types/TSParseResult.en.rst @@ -22,7 +22,9 @@ TSParseResult Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSParseResult diff --git a/doc/developer-guide/api/types/TSRecordAccessType.en.rst b/doc/developer-guide/api/types/TSRecordAccessType.en.rst index 84f71e19653..a6105ce8c67 100644 --- a/doc/developer-guide/api/types/TSRecordAccessType.en.rst +++ b/doc/developer-guide/api/types/TSRecordAccessType.en.rst @@ -22,7 +22,9 @@ TSRecordAccessType Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSRecordAccessType diff --git a/doc/developer-guide/api/types/TSRecordCheckType.en.rst b/doc/developer-guide/api/types/TSRecordCheckType.en.rst index a6fc51f6e05..ad3967bb0b4 100644 --- a/doc/developer-guide/api/types/TSRecordCheckType.en.rst +++ b/doc/developer-guide/api/types/TSRecordCheckType.en.rst @@ -22,7 +22,9 @@ TSRecordCheckType Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSRecordCheckType diff --git a/doc/developer-guide/api/types/TSRecordDataType.en.rst b/doc/developer-guide/api/types/TSRecordDataType.en.rst index 6ea96108aca..f2f09b1caa2 100644 --- a/doc/developer-guide/api/types/TSRecordDataType.en.rst +++ b/doc/developer-guide/api/types/TSRecordDataType.en.rst @@ -22,7 +22,9 @@ TSRecordDataType Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSRecordDataType diff --git a/doc/developer-guide/api/types/TSRecordModeType.en.rst b/doc/developer-guide/api/types/TSRecordModeType.en.rst index cdfa6c32c4d..4e8c3e4fded 100644 --- a/doc/developer-guide/api/types/TSRecordModeType.en.rst +++ b/doc/developer-guide/api/types/TSRecordModeType.en.rst @@ -22,7 +22,9 @@ TSRecordModeType Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSRecordModeType diff --git a/doc/developer-guide/api/types/TSRecordPersistType.en.rst b/doc/developer-guide/api/types/TSRecordPersistType.en.rst index 448e832dac6..076d7ff1760 100644 --- a/doc/developer-guide/api/types/TSRecordPersistType.en.rst +++ b/doc/developer-guide/api/types/TSRecordPersistType.en.rst @@ -22,7 +22,9 @@ TSRecordPersistType Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSRecordPersistType diff --git a/doc/developer-guide/api/types/TSRecordType.en.rst b/doc/developer-guide/api/types/TSRecordType.en.rst index bb8e0247a33..cb72926b5ed 100644 --- a/doc/developer-guide/api/types/TSRecordType.en.rst +++ b/doc/developer-guide/api/types/TSRecordType.en.rst @@ -22,7 +22,9 @@ TSRecordType Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSRecordType diff --git a/doc/developer-guide/api/types/TSRecordUpdateType.en.rst b/doc/developer-guide/api/types/TSRecordUpdateType.en.rst index 53ce764a403..af6c1c2d23a 100644 --- a/doc/developer-guide/api/types/TSRecordUpdateType.en.rst +++ b/doc/developer-guide/api/types/TSRecordUpdateType.en.rst @@ -22,7 +22,9 @@ TSRecordUpdateType Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSRecordUpdateType diff --git a/doc/developer-guide/api/types/TSReturnCode.en.rst b/doc/developer-guide/api/types/TSReturnCode.en.rst index 5885fc3eae0..ac37ab5e7f8 100644 --- a/doc/developer-guide/api/types/TSReturnCode.en.rst +++ b/doc/developer-guide/api/types/TSReturnCode.en.rst @@ -22,7 +22,9 @@ TSReturnCode Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSReturnCode diff --git a/doc/developer-guide/api/types/TSSDKVersion.en.rst b/doc/developer-guide/api/types/TSSDKVersion.en.rst index 2fa3b0e698b..323e911a383 100644 --- a/doc/developer-guide/api/types/TSSDKVersion.en.rst +++ b/doc/developer-guide/api/types/TSSDKVersion.en.rst @@ -22,7 +22,9 @@ TSSDKVersion Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSSDKVersion diff --git a/doc/developer-guide/api/types/TSServerSessionSharingMatchType.en.rst b/doc/developer-guide/api/types/TSServerSessionSharingMatchType.en.rst index 6b2c36941d9..4e52c8235b2 100644 --- a/doc/developer-guide/api/types/TSServerSessionSharingMatchType.en.rst +++ b/doc/developer-guide/api/types/TSServerSessionSharingMatchType.en.rst @@ -22,7 +22,9 @@ TSServerSessionSharingMatchType Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSServerSessionSharingMatchType diff --git a/doc/developer-guide/api/types/TSServerSessionSharingPoolType.en.rst b/doc/developer-guide/api/types/TSServerSessionSharingPoolType.en.rst index e21b88e38a3..da6e9c4474c 100644 --- a/doc/developer-guide/api/types/TSServerSessionSharingPoolType.en.rst +++ b/doc/developer-guide/api/types/TSServerSessionSharingPoolType.en.rst @@ -22,7 +22,9 @@ TSServerSessionSharingPoolType Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSServerSessionSharingPoolType diff --git a/doc/developer-guide/api/types/TSServerState.en.rst b/doc/developer-guide/api/types/TSServerState.en.rst index 6af8837df64..adf25901617 100644 --- a/doc/developer-guide/api/types/TSServerState.en.rst +++ b/doc/developer-guide/api/types/TSServerState.en.rst @@ -22,7 +22,9 @@ TSServerState Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSServerState diff --git a/doc/developer-guide/api/types/TSSslSession.en.rst b/doc/developer-guide/api/types/TSSslSession.en.rst index 60a184f0778..74e6e0a9a46 100644 --- a/doc/developer-guide/api/types/TSSslSession.en.rst +++ b/doc/developer-guide/api/types/TSSslSession.en.rst @@ -24,7 +24,9 @@ TSSslSession Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. type:: TSSslSessionID diff --git a/doc/developer-guide/api/types/TSStatPeristence.en.rst b/doc/developer-guide/api/types/TSStatPeristence.en.rst index a8a75151c4b..7d383ab712c 100644 --- a/doc/developer-guide/api/types/TSStatPeristence.en.rst +++ b/doc/developer-guide/api/types/TSStatPeristence.en.rst @@ -22,7 +22,9 @@ TSStatPersistence Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSStatPersistence @@ -42,4 +44,4 @@ Enumeration Members Description =========== -The level of persistence for a statistic value. \ No newline at end of file +The level of persistence for a statistic value. diff --git a/doc/developer-guide/api/types/TSStatSync.en.rst b/doc/developer-guide/api/types/TSStatSync.en.rst index 9b4b51e2839..f7867ae5d49 100644 --- a/doc/developer-guide/api/types/TSStatSync.en.rst +++ b/doc/developer-guide/api/types/TSStatSync.en.rst @@ -22,7 +22,9 @@ TSStatSync Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSStatSync @@ -50,4 +52,4 @@ Enumeration Members Description =========== -The level of persistence for a statistic value. \ No newline at end of file +The level of persistence for a statistic value. diff --git a/doc/developer-guide/api/types/TSThreadPool.en.rst b/doc/developer-guide/api/types/TSThreadPool.en.rst index 298a8505b15..8366b2021b2 100644 --- a/doc/developer-guide/api/types/TSThreadPool.en.rst +++ b/doc/developer-guide/api/types/TSThreadPool.en.rst @@ -22,7 +22,9 @@ TSThreadPool Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSThreadPool diff --git a/doc/developer-guide/api/types/TSUuid.en.rst b/doc/developer-guide/api/types/TSUuid.en.rst index abf5044558f..a810bd5cdf9 100644 --- a/doc/developer-guide/api/types/TSUuid.en.rst +++ b/doc/developer-guide/api/types/TSUuid.en.rst @@ -22,7 +22,9 @@ TSUuid Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSUuid diff --git a/doc/developer-guide/api/types/TSVConnCloseFlags.en.rst b/doc/developer-guide/api/types/TSVConnCloseFlags.en.rst index fff34731f01..7045a7af32d 100644 --- a/doc/developer-guide/api/types/TSVConnCloseFlags.en.rst +++ b/doc/developer-guide/api/types/TSVConnCloseFlags.en.rst @@ -22,7 +22,9 @@ TSVConnCloseFlags Synopsis ======== -`#include ` +.. code-block:: cpp + + #include .. c:type:: TSVConnCloseFlags diff --git a/doc/developer-guide/internal-libraries/MemSpan.en.rst b/doc/developer-guide/internal-libraries/MemSpan.en.rst index a9b6775e2ac..e832c80bb37 100644 --- a/doc/developer-guide/internal-libraries/MemSpan.en.rst +++ b/doc/developer-guide/internal-libraries/MemSpan.en.rst @@ -25,7 +25,9 @@ MemSpan Synopsis ======== -:code:`#include ` +.. code-block:: cpp + + #include :class:`MemSpan` is a view on a contiguous section of writeable memory. A view does not own the memory and neither allocates nor de-allocates. The memory in the view is always owned by some other container diff --git a/doc/developer-guide/internal-libraries/TextView.en.rst b/doc/developer-guide/internal-libraries/TextView.en.rst index da4849d7f62..f3dc72efc7a 100644 --- a/doc/developer-guide/internal-libraries/TextView.en.rst +++ b/doc/developer-guide/internal-libraries/TextView.en.rst @@ -25,7 +25,9 @@ TextView Synopsis ======== -:code:`#include ` +.. code-block:: cpp + + #include ` .. class:: TextView From 617c6f5a3587f3fb63f2fab1c11e909d9a487cf9 Mon Sep 17 00:00:00 2001 From: bneradt Date: Fri, 1 Nov 2019 16:22:14 +0000 Subject: [PATCH 117/718] Adding an autest for traffic_dump. (cherry picked from commit 452d60ea7878b202e45b297083641ed3968fc3fb) --- .../experimental/traffic_dump/traffic_dump.cc | 2 +- tests/Pipfile | 1 + .../pluginTest/traffic_dump/gold/200.gold | 12 ++ .../traffic_dump/traffic_dump.test.py | 112 ++++++++++++++++++ .../pluginTest/traffic_dump/verify_replay.py | 96 +++++++++++++++ 5 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 tests/gold_tests/pluginTest/traffic_dump/gold/200.gold create mode 100644 tests/gold_tests/pluginTest/traffic_dump/traffic_dump.test.py create mode 100644 tests/gold_tests/pluginTest/traffic_dump/verify_replay.py diff --git a/plugins/experimental/traffic_dump/traffic_dump.cc b/plugins/experimental/traffic_dump/traffic_dump.cc index dc73e16cf02..464dd41d1b2 100644 --- a/plugins/experimental/traffic_dump/traffic_dump.cc +++ b/plugins/experimental/traffic_dump/traffic_dump.cc @@ -602,7 +602,7 @@ TSPluginInit(int argc, const char *argv[]) TSHttpHookAdd(TS_HTTP_SSN_START_HOOK, ssncont); TSHttpHookAdd(TS_HTTP_SSN_CLOSE_HOOK, ssncont); TSLifecycleHookAdd(TS_LIFECYCLE_MSG_HOOK, ssncont); - TSDebug(PLUGIN_NAME, "Initialized with sample pool size %" PRId64 " bytes and disk limit %" PRId64 "bytes", + TSDebug(PLUGIN_NAME, "Initialized with sample pool size %" PRId64 " bytes and disk limit %" PRId64 " bytes", sample_pool_size.load(), max_disk_usage.load()); } diff --git a/tests/Pipfile b/tests/Pipfile index f8a6bcc5009..aa4a6e8abd0 100644 --- a/tests/Pipfile +++ b/tests/Pipfile @@ -31,6 +31,7 @@ requests = "*" gunicorn = "*" httpbin = "*" microserver = ">=1.0.4" +jsonschema = "*" [requires] python_version = "3" diff --git a/tests/gold_tests/pluginTest/traffic_dump/gold/200.gold b/tests/gold_tests/pluginTest/traffic_dump/gold/200.gold new file mode 100644 index 00000000000..71aa5d5a0d5 --- /dev/null +++ b/tests/gold_tests/pluginTest/traffic_dump/gold/200.gold @@ -0,0 +1,12 @@ +`` +> GET /`` HTTP/1.1 +> Host: www.example.com`` +> User-Agent: curl/`` +> Accept: */* +`` +< HTTP/1.1 200 OK +< Content-Length: 0 +< Date: `` +< Age: `` +< Server: ATS/`` +`` diff --git a/tests/gold_tests/pluginTest/traffic_dump/traffic_dump.test.py b/tests/gold_tests/pluginTest/traffic_dump/traffic_dump.test.py new file mode 100644 index 00000000000..1b4be842380 --- /dev/null +++ b/tests/gold_tests/pluginTest/traffic_dump/traffic_dump.test.py @@ -0,0 +1,112 @@ +""" +Verify traffic_dump functionality. +""" +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +Test.Summary = ''' +Verify traffic_dump functionality. +''' + +Test.SkipUnless( + Condition.PluginExists('traffic_dump.so'), +) + +# Configure the origin server. +server = Test.MakeOriginServer("server") + +request_header = {"headers": "GET / HTTP/1.1\r\nHost: www.example.com\r\nContent-Length: 0\r\n\r\n", + "timestamp": "1469733493.993", "body": ""} +response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: 0\r\n\r\n", + "timestamp": "1469733493.993", "body": ""} +server.addResponse("sessionfile.log", request_header, response_header) + +# Define ATS and configure +ts = Test.MakeATSProcess("ts") +replay_dir = os.path.join(ts.RunDirectory, "ts", "log") +ts.Disk.records_config.update({ + 'proxy.config.diags.debug.enabled': 1, + 'proxy.config.diags.debug.tags': 'traffic_dump', +}) +ts.Disk.remap_config.AddLine( + 'map / http://127.0.0.1:{0}'.format(server.Variables.Port) +) +# Configure traffic_dump. +ts.Disk.plugin_config.AddLine( + 'traffic_dump.so --logdir {0} --sample 1 --limit 1000000000'.format(replay_dir) +) + +# Set up trafficserver expectations. +ts.Disk.diags_log.Content = Testers.ContainsExpression( + "loading plugin.*traffic_dump.so", + "Verify the traffic_dump plugin got loaded.") +ts.Streams.stderr = Testers.ContainsExpression( + "Initialized with log directory: {0}".format(replay_dir), + "Verify traffic_dump initialized with the configured directory.") +ts.Streams.stderr += Testers.ContainsExpression( + "Initialized with sample pool size 1 bytes and disk limit 1000000000 bytes", + "Verify traffic_dump initialized with the configured disk limit.") + +# Set up the json replay file expectations. +replay_file_session_1 = os.path.join(replay_dir, "127", "0000000000000000") +ts.Disk.File(replay_file_session_1, exists=True) +replay_file_session_2 = os.path.join(replay_dir, "127", "0000000000000001") +ts.Disk.File(replay_file_session_2, exists=True) + +# Execute the first transaction. +tr = Test.AddTestRun("First transaction") + +tr.Processes.Default.StartBefore(server, ready=When.PortOpen(server.Variables.Port)) +tr.Processes.Default.StartBefore(Test.Processes.ts) +tr.Processes.Default.Command = 'curl http://127.0.0.1:{0} -H\'Host: www.example.com\' --verbose'.format( + ts.Variables.port) +tr.Processes.Default.ReturnCode = 0 +tr.Processes.Default.Streams.stderr = "gold/200.gold" +tr.StillRunningAfter = server +tr.StillRunningAfter = ts + +# Execute the second transaction. +tr = Test.AddTestRun("Second transaction") +tr.Processes.Default.Command = 'curl http://127.0.0.1:{0} -H\'Host: www.example.com\' --verbose'.format( + ts.Variables.port) +tr.Processes.Default.ReturnCode = 0 +tr.Processes.Default.Streams.stderr = "gold/200.gold" +tr.StillRunningAfter = server +tr.StillRunningAfter = ts + +# Verify the properties of the replay file for the first transaction. +tr = Test.AddTestRun("Verify the json content of the first session") +verify_replay = "verify_replay.py" +tr.Setup.CopyAs(verify_replay, Test.RunDirectory) +tr.Processes.Default.Command = "python3 {0} {1} {2}".format( + verify_replay, + os.path.join(Test.Variables.AtsTestToolsDir, 'lib', 'replay_schema.json'), + replay_file_session_1) +tr.Processes.Default.ReturnCode = 0 +tr.StillRunningAfter = server +tr.StillRunningAfter = ts + +# Verify the properties of the replay file for the second transaction. +tr = Test.AddTestRun("Verify the json content of the second session") +tr.Setup.CopyAs(verify_replay, Test.RunDirectory) +tr.Processes.Default.Command = "python3 {0} {1} {2}".format( + verify_replay, + os.path.join(Test.Variables.AtsTestToolsDir, 'lib', 'replay_schema.json'), + replay_file_session_2) +tr.Processes.Default.ReturnCode = 0 +tr.StillRunningAfter = server +tr.StillRunningAfter = ts diff --git a/tests/gold_tests/pluginTest/traffic_dump/verify_replay.py b/tests/gold_tests/pluginTest/traffic_dump/verify_replay.py new file mode 100644 index 00000000000..5b5738a8e7f --- /dev/null +++ b/tests/gold_tests/pluginTest/traffic_dump/verify_replay.py @@ -0,0 +1,96 @@ +""" +Verify that a given JSON replay file fulfills basic expectations. +""" +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import json +import jsonschema +import sys + + +def validate_json(schema_json, replay_json): + """ + Validate the replay file against the provided schema. + """ + try: + jsonschema.validate(instance=replay_json, schema=schema_json) + except jsonschema.ValidationError: + print("The replay file does not validate against the schema.") + return False + else: + return True + + +def verify_there_was_a_transaction(replay_json): + """ + Verify that the replay file has a sensible looking transaction. + """ + try: + transactions = replay_json['sessions'][0]['transactions'] + except KeyError: + print("The replay file did not have transactions in it.") + return False + + if len(transactions) < 1: + print("There are no transactions in the replay file.") + return False + transaction = transactions[0] + if not ('client-request' in transaction and 'server-response' in transaction): + print("There was not request and response in the transaction of the replay file.") + return False + + return True + + +def parse_args(): + parser = argparse.ArgumentParser() + parser.add_argument("schema_file", + type=argparse.FileType('r'), + help="The schema in which to interpret validate the replay file.") + parser.add_argument("replay_file", + type=argparse.FileType('r'), + help="The replay file to validate.") + return parser.parse_args() + + +def main(): + args = parse_args() + + schema_json = json.load(args.schema_file) + replay_json = json.load(args.replay_file) + + if not validate_json(schema_json, replay_json): + return 1 + + # Verifying that there is a transaction in the replay file may seem + # unnecessary since the replay file validated against the schema. But a JSON + # file that doesn't have conflicting entry names will pass the schema. For + # instance, this passes against our replay schema: + # + # {"name": "Bob", "languages": ["English", "French"]} + # + # Thus we do the following sanity check to make sure that the replay file + # appears to have some transaction in it. + if not verify_there_was_a_transaction(replay_json): + return 1 + + return 0 + + +if __name__ == '__main__': + sys.exit(main()) From 83ae3c88863187b9ee367dd5ba489182fc31454c Mon Sep 17 00:00:00 2001 From: Sudheer Vinukonda Date: Fri, 1 Nov 2019 10:35:58 -0700 Subject: [PATCH 118/718] Add Metrics to track SSL Handshake attempts Remove debug logs (cherry picked from commit d22de244f665237ec68346691ef8bb455bcde356) --- iocore/net/SSLNetVConnection.cc | 2 ++ iocore/net/SSLStats.cc | 4 ++++ iocore/net/SSLStats.h | 2 ++ 3 files changed, 8 insertions(+) diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc index a29f1b241dc..d5771f5b10a 100644 --- a/iocore/net/SSLNetVConnection.cc +++ b/iocore/net/SSLNetVConnection.cc @@ -1107,6 +1107,7 @@ SSLNetVConnection::sslServerHandShakeEvent(int &err) // Go do the preaccept hooks if (sslHandshakeHookState == HANDSHAKE_HOOKS_PRE) { + SSL_INCREMENT_DYN_STAT(ssl_total_attempts_handshake_count_in_stat); if (!curHook) { Debug("ssl", "Initialize preaccept curHook from NULL"); curHook = ssl_hooks->get(TSSslHookInternalID(TS_VCONN_START_HOOK)); @@ -1352,6 +1353,7 @@ SSLNetVConnection::sslClientHandShakeEvent(int &err) // Go do the preaccept hooks if (sslHandshakeHookState == HANDSHAKE_HOOKS_OUTBOUND_PRE) { + SSL_INCREMENT_DYN_STAT(ssl_total_attempts_handshake_count_out_stat); if (!curHook) { Debug("ssl", "Initialize outbound connect curHook from NULL"); curHook = ssl_hooks->get(TSSslHookInternalID(TS_VCONN_OUTBOUND_START_HOOK)); diff --git a/iocore/net/SSLStats.cc b/iocore/net/SSLStats.cc index 9ab09eda41a..a29adc3b597 100644 --- a/iocore/net/SSLStats.cc +++ b/iocore/net/SSLStats.cc @@ -132,8 +132,12 @@ SSLInitializeStatistics() // SSL handshake time RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.total_handshake_time", RECD_COUNTER, RECP_PERSISTENT, (int)ssl_total_handshake_time_stat, RecRawStatSyncSum); + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.total_attempts_handshake_count_in", RECD_COUNTER, RECP_PERSISTENT, + (int)ssl_total_attempts_handshake_count_in_stat, RecRawStatSyncCount); RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.total_success_handshake_count_in", RECD_COUNTER, RECP_PERSISTENT, (int)ssl_total_success_handshake_count_in_stat, RecRawStatSyncCount); + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.total_attempts_handshake_count_out", RECD_COUNTER, RECP_PERSISTENT, + (int)ssl_total_attempts_handshake_count_out_stat, RecRawStatSyncCount); RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.total_success_handshake_count_out", RECD_COUNTER, RECP_PERSISTENT, (int)ssl_total_success_handshake_count_out_stat, RecRawStatSyncCount); diff --git a/iocore/net/SSLStats.h b/iocore/net/SSLStats.h index 2ad0ce0b87e..ccd6e93411c 100644 --- a/iocore/net/SSLStats.h +++ b/iocore/net/SSLStats.h @@ -68,6 +68,7 @@ enum SSL_Stats { ssl_user_agent_session_miss_stat, ssl_user_agent_session_timeout_stat, ssl_total_handshake_time_stat, + ssl_total_attempts_handshake_count_in_stat, ssl_total_success_handshake_count_in_stat, ssl_total_tickets_created_stat, ssl_total_tickets_verified_stat, @@ -89,6 +90,7 @@ enum SSL_Stats { ssl_error_read_eos, ssl_error_ssl, ssl_sni_name_set_failure, + ssl_total_attempts_handshake_count_out_stat, ssl_total_success_handshake_count_out_stat, /* ocsp stapling stats */ From 71a545598fac113256fac2805c12bddc9ed43c0a Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Wed, 6 Nov 2019 16:04:30 -0700 Subject: [PATCH 119/718] Disable the most expensive "make check" tests by default This is at least a 2x improvement in runtime, which will help on the CI. Also, worth noting is that the cache tests are insanely disk write and storage heavy, it essentially builds ~23 traffic_server binaries. (cherry picked from commit ea1202a7d655130ef240a901e10e7b38f69191a4) --- configure.ac | 14 ++++++++++++++ iocore/cache/Makefile.am | 2 ++ src/tscore/Makefile.am | 6 +++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 68c348796ec..ac20103d639 100644 --- a/configure.ac +++ b/configure.ac @@ -283,6 +283,20 @@ AC_MSG_RESULT([$enable_tests]) TS_ARG_ENABLE_VAR([has], [tests]) AM_CONDITIONAL([BUILD_TESTS], [test 0 -ne $has_tests]) +# +# Build expensive unit tests ? +# + +AC_MSG_CHECKING([whether to enable expensive unit tests]) +AC_ARG_ENABLE([expensive-tests], + [AS_HELP_STRING([--enable-expensive-tests],[turn on expensive unit tests])], + [], + [enable_expensive_tests=no] +) +AC_MSG_RESULT([$enable_expensive_tests]) +TS_ARG_ENABLE_VAR([has], [expensive_tests]) +AM_CONDITIONAL([EXPENSIVE_TESTS], [test 0 -ne $has_expensive_tests]) + # # Build documentation? # diff --git a/iocore/cache/Makefile.am b/iocore/cache/Makefile.am index 3c528880f28..307f05bf7c4 100644 --- a/iocore/cache/Makefile.am +++ b/iocore/cache/Makefile.am @@ -116,6 +116,7 @@ test_LDADD = \ @YAMLCPP_LIBS@ \ -lm +if EXPENSIVE_TESTS check_PROGRAMS = \ test_Cache \ test_RWW \ @@ -128,6 +129,7 @@ check_PROGRAMS = \ test_Update_L_to_S \ test_Update_S_to_L \ test_Update_header +endif test_main_SOURCES = \ ./test/main.cc \ diff --git a/src/tscore/Makefile.am b/src/tscore/Makefile.am index 11b7285ce6a..faa2fc02ca3 100644 --- a/src/tscore/Makefile.am +++ b/src/tscore/Makefile.am @@ -19,7 +19,11 @@ include $(top_srcdir)/build/tidy.mk noinst_PROGRAMS = mkdfa CompileParseRules -check_PROGRAMS = test_atomic test_freelist test_geometry test_X509HostnameValidator test_tscore +check_PROGRAMS = test_geometry test_X509HostnameValidator test_tscore + +if EXPENSIVE_TESTS +check_PROGRAMS += test_atomic test_freelist +endif TESTS_ENVIRONMENT = LSAN_OPTIONS=suppressions=$(abs_top_srcdir)/ci/asan_leak_suppression/unit_tests.txt From 78137564d4e30720a579c9495db8de6c46ebf9ae Mon Sep 17 00:00:00 2001 From: Bryan Call Date: Tue, 5 Nov 2019 17:36:55 -0800 Subject: [PATCH 120/718] Remove including sys/sysctl.h for Linux (cherry picked from commit 3ea8301d1572073072063233b6974244d1827e81) --- include/tscore/ink_platform.h | 2 ++ src/tscore/ink_hrtime.cc | 2 ++ tests/include/catch.hpp | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/include/tscore/ink_platform.h b/include/tscore/ink_platform.h index 6bef79d7855..922b474c57c 100644 --- a/include/tscore/ink_platform.h +++ b/include/tscore/ink_platform.h @@ -157,9 +157,11 @@ typedef unsigned int in_addr_t; #include #endif +#if defined(darwin) || defined(freebsd) #ifdef HAVE_SYS_SYSCTL_H #include #endif +#endif #ifdef HAVE_SYS_SYSTEMINFO_H #include diff --git a/src/tscore/ink_hrtime.cc b/src/tscore/ink_hrtime.cc index ad47f335f63..c8babcff944 100644 --- a/src/tscore/ink_hrtime.cc +++ b/src/tscore/ink_hrtime.cc @@ -35,8 +35,10 @@ #if defined(freebsd) #include #include +#ifdef HAVE_SYS_SYSCTL_H #include #endif +#endif #include #include diff --git a/tests/include/catch.hpp b/tests/include/catch.hpp index ecd8907ea30..d7bb0377b4f 100644 --- a/tests/include/catch.hpp +++ b/tests/include/catch.hpp @@ -7093,7 +7093,11 @@ namespace Catch { # include # include # include +#if defined(darwin) || defined(freebsd) +#ifdef HAVE_SYS_SYSCTL_H # include +#endif +#endif # include # include From f6d1551617087c966f6cdba0e8f5996d83541a93 Mon Sep 17 00:00:00 2001 From: Sudheer Vinukonda Date: Tue, 5 Nov 2019 08:13:41 -0800 Subject: [PATCH 121/718] Update docs for SSL Handshake stats (cherry picked from commit 032cedbc752dfdec238b3b48f18f05e79b592057) --- .../monitoring/statistics/core/ssl.en.rst | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/doc/admin-guide/monitoring/statistics/core/ssl.en.rst b/doc/admin-guide/monitoring/statistics/core/ssl.en.rst index 34e35a96b75..3b6ee48dbba 100644 --- a/doc/admin-guide/monitoring/statistics/core/ssl.en.rst +++ b/doc/admin-guide/monitoring/statistics/core/ssl.en.rst @@ -108,10 +108,28 @@ SSL/TLS The total amount of time spent performing SSL/TLS handshakes for new sessions since statistics collection began. -.. ts:stat:: global proxy.process.ssl.total_success_handshake_count integer +.. ts:stat:: global proxy.process.ssl.total_attempts_handshake_count_in integer :type: counter - The total number of SSL/TLS handshakes successfully performed since + The total number of inbound SSL/TLS handshake attempts received since + statistics collection began. + +.. ts:stat:: global proxy.process.ssl.total_success_handshake_count_in integer + :type: counter + + The total number of inbound SSL/TLS handshakes successfully performed since + statistics collection began. + +.. ts:stat:: global proxy.process.ssl.total_attempts_handshake_count_out integer + :type: counter + + The total number of outbound SSL/TLS handshake attempts made since + statistics collection began. + +.. ts:stat:: global proxy.process.ssl.total_success_handshake_count_out integer + :type: counter + + The total number of outbound SSL/TLS handshakes successfully performed since statistics collection began. .. ts:stat:: global proxy.process.ssl.total_ticket_keys_renewed integer From 94f6c8129464019fd5fee325469aa6c4dc4ff9a2 Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Wed, 6 Nov 2019 08:47:29 +0900 Subject: [PATCH 122/718] Remove using namespace std To fix build issue on FreeBSD 12.1 & LLVM-9 on macOS (cherry picked from commit e50520f4a4954ed8375e00594d86a11556e3d95c) --- iocore/cache/CacheTest.cc | 4 +--- src/traffic_top/stats.h | 13 ++++++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/iocore/cache/CacheTest.cc b/iocore/cache/CacheTest.cc index d7d42e24cda..79b33bd1af9 100644 --- a/iocore/cache/CacheTest.cc +++ b/iocore/cache/CacheTest.cc @@ -28,8 +28,6 @@ #include #include -using namespace std; - CacheTestSM::CacheTestSM(RegressionTest *t, const char *name) : RegressionSM(t), cache_test_name(name) { SET_HANDLER(&CacheTestSM::event_handler); @@ -553,7 +551,7 @@ test_RamCache(RegressionTest *t, RamCache *cache, const char *name, int64_t cach bool pass = true; CacheKey key; Vol *vol = theCache->key_to_vol(&key, "example.com", sizeof("example.com") - 1); - vector> data; + std::vector> data; cache->init(cache_size, vol); diff --git a/src/traffic_top/stats.h b/src/traffic_top/stats.h index 1789fd0ed02..79214e1aa1d 100644 --- a/src/traffic_top/stats.h +++ b/src/traffic_top/stats.h @@ -32,8 +32,6 @@ #include #include "mgmtapi.h" -using namespace std; - struct LookupItem { LookupItem(const char *s, const char *n, const int t) : pretty(s), name(n), numerator(""), denominator(""), type(t) {} LookupItem(const char *s, const char *n, const char *d, const int t) : pretty(s), name(n), numerator(n), denominator(d), type(t) @@ -49,7 +47,7 @@ extern size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream); #if HAS_CURL extern char curl_error[CURL_ERROR_SIZE]; #endif -extern string response; +extern std::string response; namespace constant { @@ -62,6 +60,9 @@ const char end[] = "\",\n"; //---------------------------------------------------------------------------- class Stats { + using string = std::string; + template using map = std::map; + public: Stats(const string &url) : _url(url) { @@ -524,6 +525,12 @@ class Stats } private: + std::pair + make_pair(std::string s, LookupItem i) + { + return std::make_pair(s, i); + } + map *_stats; map *_old_stats; map lookup_table; From 821947e1b902d2deee4101759090fb8d62e4ebee Mon Sep 17 00:00:00 2001 From: bneradt Date: Tue, 5 Nov 2019 19:19:53 +0000 Subject: [PATCH 123/718] A couple simple tweaks. (cherry picked from commit 2d7a47773dfb92b92f3d5347990e8d39c503aeba) --- .../plugins/hooks-and-transactions/http-transactions.en.rst | 2 +- doc/developer-guide/plugins/introduction.en.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/developer-guide/plugins/hooks-and-transactions/http-transactions.en.rst b/doc/developer-guide/plugins/hooks-and-transactions/http-transactions.en.rst index f58bf3cc626..1c6aae2b250 100644 --- a/doc/developer-guide/plugins/hooks-and-transactions/http-transactions.en.rst +++ b/doc/developer-guide/plugins/hooks-and-transactions/http-transactions.en.rst @@ -28,7 +28,7 @@ transactions. As described in the section on HTTP sessions, an **HTTP transaction** is an object defined for the lifetime of a single request from a client and -the corresponding response from Traffic Server. The **``TSHttpTxn``** +the corresponding response from Traffic Server. The ``TSHttpTxn`` structure is the main handle given to a plugin for manipulating a transaction's internal state. Additionally, an HTTP transaction has a reference back to the HTTP session that created it. diff --git a/doc/developer-guide/plugins/introduction.en.rst b/doc/developer-guide/plugins/introduction.en.rst index 5a5469bae12..58aaf32860d 100644 --- a/doc/developer-guide/plugins/introduction.en.rst +++ b/doc/developer-guide/plugins/introduction.en.rst @@ -90,7 +90,7 @@ Below are some guidelines for creating a plugin: These examples are discussed in the following chapters. #. Determine where your plugin needs to hook on to Traffic Server's HTTP - processing (view the :ref:`http-txn-state-diagram`. + processing (view the :ref:`http-txn-state-diagram`). #. Read :ref:`developer-plugins-header-based-examples` to learn the basics of writing plugins: creating continuations and setting up hooks. If you @@ -101,7 +101,7 @@ Below are some guidelines for creating a plugin: then read about the details of those APIs in this manual's reference chapters. -#. Compile and load your plugin (see :ref:`developer-plugins-getting-started`. +#. Compile and load your plugin (see :ref:`developer-plugins-getting-started`). #. Depending on your plugin's functionality, you might start testing it by issuing requests by hand and checking for the desired behavior in From 49bbb4bdcb1a9ba88920dd8cd746caa6f6321d91 Mon Sep 17 00:00:00 2001 From: Randall Meyer Date: Thu, 24 Oct 2019 10:30:42 -0500 Subject: [PATCH 124/718] Fixes help message for traffic_top's sleep switch Closes issue #6051 (cherry picked from commit 0a455638854e3f771c2e92521bf8f17aa38fc836) --- src/traffic_top/traffic_top.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/traffic_top/traffic_top.cc b/src/traffic_top/traffic_top.cc index 539e9853c7b..625589c5eb8 100644 --- a/src/traffic_top/traffic_top.cc +++ b/src/traffic_top/traffic_top.cc @@ -400,7 +400,7 @@ main(int argc, const char **argv) version.setup(PACKAGE_NAME, "traffic_top", PACKAGE_VERSION, __DATE__, __TIME__, BUILD_MACHINE, BUILD_PERSON, ""); const ArgumentDescription argument_descriptions[] = { - {"sleep", 's', "Enable debugging output", "I", &sleep_time, nullptr, nullptr}, + {"sleep", 's', "Sets the delay between updates (in seconds)", "I", &sleep_time, nullptr, nullptr}, HELP_ARGUMENT_DESCRIPTION(), VERSION_ARGUMENT_DESCRIPTION(), RUNROOT_ARGUMENT_DESCRIPTION(), From 20a72cdbea59bc86301d61003dc195547e4f07f4 Mon Sep 17 00:00:00 2001 From: Miles Libbey Date: Mon, 21 Oct 2019 13:49:23 -0700 Subject: [PATCH 125/718] Clarify relation of nameservers and resolv.conf Clarifying the behavior here. (cherry picked from commit 2888052d71c9c192eec96cdbff20f0c6b1076c7e) Conflicts: doc/admin-guide/files/records.config.en.rst --- doc/admin-guide/files/records.config.en.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst index 5e605988cb8..5c482439f4d 100644 --- a/doc/admin-guide/files/records.config.en.rst +++ b/doc/admin-guide/files/records.config.en.rst @@ -335,7 +335,7 @@ Thread Variables ``0`` ``1`` All worker threads listen on the same port using SO_REUSEPORT. Each thread has its own listen fd and new connections are accepted on all the threads. ==================== ====================== ===================== - By default, `proxy.config.accept_threads` is set to 1 and `proxy.config.exec_thread.listen` is set to 0. + By default, `proxy.config.accept_threads` is set to 1 and `proxy.config.exec_thread.listen` is set to 0. .. ts:cv:: CONFIG proxy.config.thread.default.stacksize INT 1048576 Default thread stack size, in bytes, for all threads (default is 1 MB). @@ -2452,7 +2452,8 @@ DNS Allows one to specify which ``resolv.conf`` file to use for finding resolvers. While the format of this file must be the same as the standard ``resolv.conf`` file, this option allows an administrator to manage the set of resolvers in an external configuration file, - without affecting how the rest of the operating system uses DNS. + without affecting how the rest of the operating system uses DNS. Note that this setting works in conjunction with + :ts:cv:`proxy.config.dns.nameservers`, with its settings appended to the ``resolv.conf`` contents. .. ts:cv:: CONFIG proxy.config.dns.round_robin_nameservers INT 1 :reloadable: From e7e981ab8c1cb2feae8d8f634dafb6538c965d79 Mon Sep 17 00:00:00 2001 From: Brian Olsen Date: Mon, 30 Sep 2019 19:04:12 +0000 Subject: [PATCH 126/718] url_sig: fix memory leak with urlParse and pristine flag (cherry picked from commit b271b85aa64784e507c55697aabd0a2118480c9a) --- plugins/experimental/url_sig/url_sig.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/plugins/experimental/url_sig/url_sig.c b/plugins/experimental/url_sig/url_sig.c index 6782869c416..249a011366c 100644 --- a/plugins/experimental/url_sig/url_sig.c +++ b/plugins/experimental/url_sig/url_sig.c @@ -165,11 +165,11 @@ TSRemapNewInstance(int argc, char *argv[], void **ih, char *errbuf, int errbuf_s return TS_ERROR; } if (strncmp(line, "key", 3) == 0) { - if (strncmp((line + 3), "0", 1) == 0) { + if (strncmp(line + 3, "0", 1) == 0) { keynum = 0; } else { TSDebug(PLUGIN_NAME, ">>> %s <<<", line + 3); - keynum = atoi((line + 3)); + keynum = atoi(line + 3); if (keynum == 0) { keynum = -1; // Not a Number } @@ -349,14 +349,18 @@ fixedBufferWrite(char **dest_end, int *dest_len, const char *src, int src_len) } static char * -urlParse(char *url, char *anchor, char *new_path_seg, int new_path_seg_len, char *signed_seg, unsigned int signed_seg_len) +urlParse(char const *const url_in, char *anchor, char *new_path_seg, int new_path_seg_len, char *signed_seg, + unsigned int signed_seg_len) { char *segment[MAX_SEGMENTS]; + char url[8192] = {'\0'}; unsigned char decoded_string[2048] = {'\0'}; char new_url[8192]; /* new_url is not null_terminated */ char *p = NULL, *sig_anchor = NULL, *saveptr = NULL; int i = 0, numtoks = 0, decoded_len = 0, sig_anchor_seg = 0; + strncat(url, url_in, sizeof(url) - strlen(url) - 1); + char *new_url_end = new_url; int new_url_len_left = sizeof(new_url); @@ -373,7 +377,7 @@ urlParse(char *url, char *anchor, char *new_path_seg, int new_path_seg_len, char TSError("insufficient space to copy schema into new_path_seg buffer."); return NULL; } - TSDebug(PLUGIN_NAME, "%s:%d - new_url: %*s\n", __FILE__, __LINE__, (int)(new_url_end - new_url), new_url); + TSDebug(PLUGIN_NAME, "%s:%d - new_url: %.*s\n", __FILE__, __LINE__, (int)(new_url_end - new_url), new_url); // parse the url. if ((p = strtok_r(skip, "/", &saveptr)) != NULL) { @@ -582,19 +586,25 @@ TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo *rri) // check for path params. if (query == NULL || strstr(query, "E=") == NULL) { char *const parsed = urlParse(url, cfg->sig_anchor, new_path, 8192, path_params, 8192); - if (NULL == parsed) { - err_log(url, "Has no signing query string or signing path parameters."); + if (parsed == NULL) { + err_log(url, "Unable to parse/decode new url path parameters"); goto deny; } - url = parsed; has_path_params = true; - query = strstr(url, ";"); + query = strstr(parsed, ";"); if (query == NULL) { err_log(url, "Has no signing query string or signing path parameters."); + TSfree(parsed); goto deny; } + + if (url != current_url) { + TSfree(url); + } + + url = parsed; } /* first, parse the query string */ From 2baa388c3e3cb3ff71c468c8b0b4c68d8a0320fe Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Mon, 2 Sep 2019 14:31:56 +0900 Subject: [PATCH 127/718] Dechunk chunked contents on HttpTunnel if client protocol is HTTP/2 or HTTP/3 (cherry picked from commit 3ac74b5157cf6705b94d5eeb910953e25a6cdfc0) --- proxy/http/HttpTransact.cc | 15 +++--- proxy/http2/Http2Stream.cc | 93 ++------------------------------------ proxy/http2/Http2Stream.h | 18 +------- 3 files changed, 15 insertions(+), 111 deletions(-) diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc index 0664a45a4df..918a4b0b0c5 100644 --- a/proxy/http/HttpTransact.cc +++ b/proxy/http/HttpTransact.cc @@ -6730,11 +6730,10 @@ HttpTransact::handle_response_keep_alive_headers(State *s, HTTPVersion ver, HTTP // to the client to keep the connection alive. // Insert a Transfer-Encoding header in the response if necessary. - // check that the client is HTTP 1.1 and the conf allows chunking or the client - // protocol unchunks before returning to the user agent (i.e. is http/2) - if (s->client_info.http_version == HTTPVersion(1, 1) && - (s->txn_conf->chunking_enabled == 1 || - (s->state_machine->plugin_tag && (!strncmp(s->state_machine->plugin_tag, "http/2", 6)))) && + // check that the client protocol is HTTP/1.1 and the conf allows chunking or + // the client protocol doesn't support chunked transfer coding (i.e. HTTP/1.0, HTTP/2, and HTTP/3) + if (s->state_machine->ua_txn && s->state_machine->ua_txn->is_chunked_encoding_supported() && + s->client_info.http_version == HTTPVersion(1, 1) && s->txn_conf->chunking_enabled == 1 && // if we're not sending a body, don't set a chunked header regardless of server response !is_response_body_precluded(s->hdr_info.client_response.status_get(), s->method) && // we do not need chunked encoding for internal error messages @@ -6767,10 +6766,12 @@ HttpTransact::handle_response_keep_alive_headers(State *s, HTTPVersion ver, HTTP // Close the connection if client_info is not keep-alive. // Otherwise, if we cannot trust the content length, we will close the connection - // unless we are going to use chunked encoding or the client issued - // a PUSH request + // unless we are going to use chunked encoding on HTTP/1.1 or the client issued a PUSH request if (s->client_info.keep_alive != HTTP_KEEPALIVE) { ka_action = KA_DISABLED; + } else if (s->state_machine->client_protocol && (IP_PROTO_TAG_HTTP_3.compare(s->state_machine->client_protocol) == 0 || + strncmp(s->state_machine->client_protocol, "http/2", 6) == 0)) { + ka_action = KA_CONNECTION; } else if (s->hdr_info.trust_response_cl == false && !(s->client_info.receive_chunked_response == true || (s->method == HTTP_WKSIDX_PUSH && s->client_info.keep_alive == HTTP_KEEPALIVE))) { diff --git a/proxy/http2/Http2Stream.cc b/proxy/http2/Http2Stream.cc index fad170cf55e..8d2d5c62a49 100644 --- a/proxy/http2/Http2Stream.cc +++ b/proxy/http2/Http2Stream.cc @@ -575,7 +575,7 @@ void Http2Stream::update_write_request(IOBufferReader *buf_reader, int64_t write_len, bool call_update) { if (!this->is_client_state_writeable() || closed || _proxy_ssn == nullptr || write_vio.mutex == nullptr || - (buf_reader == nullptr && write_len == 0)) { + (buf_reader == nullptr && write_len == 0) || this->response_reader == nullptr) { return; } @@ -589,22 +589,7 @@ Http2Stream::update_write_request(IOBufferReader *buf_reader, int64_t write_len, SCOPED_MUTEX_LOCK(lock, write_vio.mutex, this_ethread()); - // if response is chunked, limit the dechunked_buffer size. - bool is_done = false; - if (this->chunked) { - if (chunked_handler.dechunked_buffer && chunked_handler.dechunked_buffer->max_read_avail() > HTTP2_MAX_BUFFER_USAGE) { - if (buffer_full_write_event == nullptr) { - buffer_full_write_event = _thread->schedule_imm(this, VC_EVENT_WRITE_READY); - } - } else { - this->response_process_data(is_done); - } - } - - if (this->response_get_data_reader() == nullptr) { - return; - } - int64_t bytes_avail = this->response_get_data_reader()->read_avail(); + int64_t bytes_avail = this->response_reader->read_avail(); if (write_vio.nbytes > 0 && write_vio.ntodo() > 0) { int64_t num_to_write = write_vio.ntodo(); if (num_to_write > write_len) { @@ -619,7 +604,7 @@ Http2Stream::update_write_request(IOBufferReader *buf_reader, int64_t write_len, ", reader.read_avail=%" PRId64, write_vio.nbytes, write_vio.ndone, write_vio.get_writer()->write_avail(), bytes_avail); - if (bytes_avail <= 0 && !is_done) { + if (bytes_avail <= 0) { return; } @@ -654,17 +639,7 @@ Http2Stream::update_write_request(IOBufferReader *buf_reader, int64_t write_len, h2_proxy_ssn->connection_state.send_headers_frame(this); } - // See if the response is chunked. Set up the dechunking logic if it is - // Make sure to check if the chunk is complete and signal appropriately - this->response_initialize_data_handling(is_done); - - // If there is additional data, send it along in a data frame. Or if this was header only - // make sure to send the end of stream - is_done |= (write_vio.ntodo() + this->response_header.length_get()) == bytes_avail; - if (this->response_is_data_available() || is_done) { - if (is_done) { - this->mark_body_done(); - } + if (this->response_reader->is_read_avail_more_than(0)) { this->_milestones.mark(Http2StreamMilestone::START_TX_DATA_FRAMES); this->send_response_body(call_update); } @@ -677,9 +652,6 @@ Http2Stream::update_write_request(IOBufferReader *buf_reader, int64_t write_len, break; } } else { - if (write_vio.ntodo() == bytes_avail || is_done) { - this->mark_body_done(); - } this->_milestones.mark(Http2StreamMilestone::START_TX_DATA_FRAMES); this->send_response_body(call_update); } @@ -820,7 +792,6 @@ Http2Stream::destroy() if (header_blocks) { ats_free(header_blocks); } - chunked_handler.clear(); clear_timers(); clear_io_events(); http_parser_clear(&http_parser); @@ -829,53 +800,10 @@ Http2Stream::destroy() THREAD_FREE(this, http2StreamAllocator, this_ethread()); } -void -Http2Stream::response_initialize_data_handling(bool &is_done) -{ - is_done = false; - int chunked_index = response_header.value_get_index(TS_MIME_FIELD_TRANSFER_ENCODING, TS_MIME_LEN_TRANSFER_ENCODING, - TS_HTTP_VALUE_CHUNKED, TS_HTTP_LEN_CHUNKED); - // -1 means this value was not found for this field - if (chunked_index >= 0) { - Http2StreamDebug("Response is chunked"); - chunked = true; - this->chunked_handler.init_by_action(this->response_reader, ChunkedHandler::ACTION_DECHUNK); - this->chunked_handler.state = ChunkedHandler::CHUNK_READ_SIZE; - this->chunked_handler.dechunked_reader = this->chunked_handler.dechunked_buffer->alloc_reader(); - this->response_reader->dealloc(); - this->response_reader = nullptr; - // Get things going if there is already data waiting - if (this->chunked_handler.chunked_reader->is_read_avail_more_than(0)) { - response_process_data(is_done); - } - } -} - -void -Http2Stream::response_process_data(bool &done) -{ - done = false; - if (chunked) { - do { - if (chunked_handler.state == ChunkedHandler::CHUNK_FLOW_CONTROL) { - chunked_handler.state = ChunkedHandler::CHUNK_READ_SIZE_START; - } - done = this->chunked_handler.process_chunked_content(); - } while (chunked_handler.state == ChunkedHandler::CHUNK_FLOW_CONTROL); - } -} - -bool -Http2Stream::response_is_data_available() const -{ - IOBufferReader *reader = this->response_get_data_reader(); - return reader ? reader->is_read_avail_more_than(0) : false; -} - IOBufferReader * Http2Stream::response_get_data_reader() const { - return (chunked) ? chunked_handler.dechunked_reader : response_reader; + return this->response_reader; } void @@ -1053,17 +981,6 @@ Http2Stream::_switch_thread_if_not_on_right_thread(int event, void *edata) return true; } -void -Http2Stream::mark_body_done() -{ - body_done = true; - if (response_is_chunked()) { - ink_assert(chunked_handler.state == ChunkedHandler::CHUNK_READ_DONE || - chunked_handler.state == ChunkedHandler::CHUNK_READ_ERROR); - this->write_vio.nbytes = response_header.length_get() + chunked_handler.dechunked_size; - } -} - int Http2Stream::get_transaction_priority_weight() const { diff --git a/proxy/http2/Http2Stream.h b/proxy/http2/Http2Stream.h index 759b0f28171..58baee67281 100644 --- a/proxy/http2/Http2Stream.h +++ b/proxy/http2/Http2Stream.h @@ -24,9 +24,8 @@ #pragma once #include "HTTP2.h" -#include "../ProxyTransaction.h" +#include "ProxyTransaction.h" #include "Http2DebugNames.h" -#include "../http/HttpTunnel.h" // To get ChunkedHandler #include "Http2DependencyTree.h" #include "tscore/History.h" #include "Milestones.h" @@ -107,7 +106,6 @@ class Http2Stream : public ProxyTransaction bool is_client_state_writeable() const; bool is_closed() const; - bool response_is_chunked() const; IOBufferReader *response_get_data_reader() const; void mark_milestone(Http2StreamMilestone type); @@ -115,7 +113,6 @@ class Http2Stream : public ProxyTransaction void increment_data_length(uint64_t length); bool payload_length_is_valid() const; bool is_body_done() const; - void mark_body_done(); void update_sent_count(unsigned num_bytes); Http2StreamId get_id() const; Http2StreamState get_state() const; @@ -146,8 +143,6 @@ class Http2Stream : public ProxyTransaction Http2DependencyTree::Node *priority_node = nullptr; private: - void response_initialize_data_handling(bool &is_done); - void response_process_data(bool &is_done); bool response_is_data_available() const; Event *send_tracked_event(Event *event, int send_event, VIO *vio); void send_response_body(bool call_update); @@ -173,8 +168,6 @@ class Http2Stream : public ProxyTransaction Milestones(Http2StreamMilestone::LAST_ENTRY)> _milestones; bool trailing_header = false; - bool body_done = false; - bool chunked = false; // A brief discussion of similar flags and state variables: _state, closed, terminate_stream // @@ -208,7 +201,6 @@ class Http2Stream : public ProxyTransaction std::vector _recent_rwnd_increment = {SIZE_MAX, SIZE_MAX, SIZE_MAX, SIZE_MAX, SIZE_MAX}; int _recent_rwnd_increment_index = 0; - ChunkedHandler chunked_handler; Event *cross_thread_event = nullptr; Event *buffer_full_write_event = nullptr; @@ -240,7 +232,7 @@ Http2Stream::mark_milestone(Http2StreamMilestone type) inline bool Http2Stream::is_body_done() const { - return body_done; + return this->write_vio.ntodo() == 0; } inline void @@ -300,12 +292,6 @@ Http2Stream::payload_length_is_valid() const return content_length == 0 || content_length == data_length; } -inline bool -Http2Stream::response_is_chunked() const -{ - return chunked; -} - inline bool Http2Stream::allow_half_open() const { From 574bde40db241397307d2c4b391220e593082803 Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Wed, 6 Nov 2019 18:21:13 -0700 Subject: [PATCH 128/718] Updated changelog --- CHANGELOG-9.0.0 | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/CHANGELOG-9.0.0 b/CHANGELOG-9.0.0 index 2d520825fd1..fa2dd5909b6 100644 --- a/CHANGELOG-9.0.0 +++ b/CHANGELOG-9.0.0 @@ -33,7 +33,6 @@ Changes with Apache Traffic Server 9.0.0 #4029 - Replace TSHashTable in server session management with IntrusiveHashMap #4033 - Removes remnants of dprintf support #4039 - Enable ECDH explicitly only if OpenSSL version is v1.0.2 or lower - #4042 - Fixed url_sig error when storing base64ed params in penultimate segment. #4044 - Adjust tests to work with more versions of curl. #4046 - Collapses LogAccess and LogAccessHttp into LogAccess #4047 - Improve log entry for http connect result errors @@ -402,7 +401,6 @@ Changes with Apache Traffic Server 9.0.0 #5228 - Implement prefetched OCSP stapling responses #5239 - Adds basic version feature for traffic_layout info #5240 - Setting the correct directory for test_Cache - #5241 - Changed how current age is determined to age out documents #5247 - Fixed cache test, using updated shutdown #5252 - Make host status persistent across restarts #5255 - Remove unused variable in cache test @@ -521,7 +519,6 @@ Changes with Apache Traffic Server 9.0.0 #5455 - Convert ssl_preaccept plugin to use command-line arguments #5458 - Updates the Docker image with latest dependencies #5460 - Fixed clang-analyzer issue calling schedule_imm with the continuation possibly being a nullptr - #5462 - gcc9: fixed issue with always printing a null char* #5463 - clang-analyzer: Fixed err value being uninitialized #5464 - clang-analyzer: Fix API test logic and fixed clang-analyzer issue #5465 - Separate out common header compression logic to hdrs directory @@ -533,11 +530,9 @@ Changes with Apache Traffic Server 9.0.0 #5477 - Removes proxy.config.http.server_tcp_init_cwnd #5478 - Fixes some cache-tests build issues #5480 - Add HKDF wrapper - #5489 - gcc9: set default value for printing debug message #5490 - clang-analyzer: Fix uninitialized variable in make_to_lower_case. #5492 - clang-analyzer: fix bogus use after free with Ptr in LogFieldInt constructor. #5495 - Correct the clear range when cache restart - #5497 - gcc9: sprintf and strncat fixes in plugins #5500 - Added Docker support for Fedora 29 and Fedora 30 #5507 - AcidPtr: Tweaks tests to be a bit more robust. #5508 - Grab lock before invoke @@ -751,6 +746,7 @@ Changes with Apache Traffic Server 9.0.0 #5964 - Fix a build issue on enabling FIPS #5969 - Change the ready checks for ats to use the actual ats port #5970 - "Plugin (un)used" post reload notification + #5973 - url_sig: fix memory leak with urlParse and pristine flag #5977 - YAML config: output erroneous keyword and line number #5978 - Removed hardcoded logging.yaml filename in logs #5979 - Revert "Optimize: If failed on migrateToCurrentThread, put the server… @@ -760,6 +756,7 @@ Changes with Apache Traffic Server 9.0.0 #5992 - Cache SSL EC explicitly #6000 - Add QUIC draft-23 support #6003 - Cleanup: do not re-define _proxy_ssn variable in local + #6006 - Rewrote remap_stats plugin to use C++ #6008 - Do not schedule stuff during shutdown #6011 - clang-analyzer: Add a null check #6016 - Fix host type in host matcher. @@ -773,8 +770,18 @@ Changes with Apache Traffic Server 9.0.0 #6076 - Issue 4635: Address pipe reuse after configuration reload issues #6078 - Cleanup: Ignore checkprograms of remap #6089 - Make If-Range date compare to be exact match + #6094 - Issue #4294: Handle return value of SSL_write() properly #6095 - For remap_stats, removes configure time dependency on search.h #6096 - Fixing log cleanup candidate selection and adding a test for it. #6099 - doc + unittest TSRemap(Init|NewInstance) failures #6106 - Removes proxy.config.cache.storage_filename + #6116 - Updated to clang-format v9.0.0 #6120 - Fix null pointer dereference reported by clang-analyzer + #6125 - Add Metrics to track SSL Handshake attempts + #6129 - Adding an autest for traffic_dump. + #6131 - Remove never implemented HttpTransact::service_transaction_in_proxy_only_mode + #6134 - Removes the records.config.shadow alternative config file + #6140 - Remove using namespace std + #6141 - Update docs for SSL Handshake stats + #6145 - Remove including sys/sysctl.h for Linux + #6148 - Disable the most expensive "make check" tests by default From 60500919d9c10c6e0d3af2e1734cdc81773ab30a Mon Sep 17 00:00:00 2001 From: Miles Libbey Date: Wed, 6 Nov 2019 17:35:50 -0800 Subject: [PATCH 129/718] Internal link needs _ Without this underscore, the link tries to go to an external file (cherry picked from commit 7ba816fcffe2d40a640b3273af8a0007deba1087) --- doc/admin-guide/plugins/header_rewrite.en.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/admin-guide/plugins/header_rewrite.en.rst b/doc/admin-guide/plugins/header_rewrite.en.rst index 217940acd04..b74e4710e09 100644 --- a/doc/admin-guide/plugins/header_rewrite.en.rst +++ b/doc/admin-guide/plugins/header_rewrite.en.rst @@ -791,7 +791,7 @@ Header Values Setting a header with a value can take the following formats: -- Any `condition `_ which extracts a value from the request. +- Any `condition `_ which extracts a value from the request. - ``$N``, where 0 <= N <= 9, from matching groups in a regular expression. From ce3e12e1be6f1f9f828f928ad1f987ef5991b553 Mon Sep 17 00:00:00 2001 From: David Calavera Date: Wed, 6 Nov 2019 10:24:07 -0800 Subject: [PATCH 130/718] Reverse debug specific check. debug_flag && diags->on() is almost an atomic operation, while is_debug_tag_set requires Diags to run a regular expression. When debug_flag is set to 1, we always want to print the debug log, regardless of whether the tag is set or not, which makes the is_debug_tag_set check useless, and expensive. This change flips the conditional to check if debug_flag is 1 first, skipping the tag check if it is. Signed-off-by: David Calavera (cherry picked from commit 9e91efbb24eafe4150d286e1bab2a52d8bb0823c) --- src/traffic_server/InkAPI.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc index 49ae84326e6..1d9dea39515 100644 --- a/src/traffic_server/InkAPI.cc +++ b/src/traffic_server/InkAPI.cc @@ -7447,7 +7447,7 @@ TSIsDebugTagSet(const char *t) void TSDebugSpecific(int debug_flag, const char *tag, const char *format_str, ...) { - if (is_debug_tag_set(tag) || (debug_flag && diags->on())) { + if ((debug_flag && diags->on()) || is_debug_tag_set(tag)) { va_list ap; va_start(ap, format_str); From 7013affe0f08b20586c8b66e406da572b4ff11f2 Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Fri, 8 Nov 2019 14:16:22 +0900 Subject: [PATCH 131/718] Fix building Catch on macOS (cherry picked from commit 98b0aeaa122ac4c2711e955003c474071c8f2086) --- tests/include/catch.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/include/catch.hpp b/tests/include/catch.hpp index d7bb0377b4f..bc24a4298f1 100644 --- a/tests/include/catch.hpp +++ b/tests/include/catch.hpp @@ -7093,6 +7093,10 @@ namespace Catch { # include # include # include + +// ink_autoconf.h is required to use HAVE_SYS_SYSCTL_H +#include "ink_autoconf.h" + #if defined(darwin) || defined(freebsd) #ifdef HAVE_SYS_SYSCTL_H # include @@ -13051,4 +13055,3 @@ using Catch::Detail::Approx; // end catch_reenable_warnings.h // end catch.hpp #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED - From 469d4d8c05c28291d40e26af8cce2abc01fc03b7 Mon Sep 17 00:00:00 2001 From: David Calavera Date: Tue, 29 Oct 2019 09:30:24 -0700 Subject: [PATCH 132/718] Change API to return a TSReturnCode code. Return a TS_ERROR when we cannot push the url to the promise table. Signed-off-by: David Calavera (cherry picked from commit 4960789e3306dca7968a74ebd4f9eba4d45e1d2a) Conflicts: doc/developer-guide/api/functions/TSHttpTxnServerPush.en.rst include/ts/ts.h --- .../api/functions/TSHttpTxnServerPush.en.rst | 9 ++-- include/ts/ts.h | 9 ++++ proxy/http2/Http2ConnectionState.cc | 11 ++--- proxy/http2/Http2ConnectionState.h | 2 +- proxy/http2/Http2Stream.cc | 4 +- proxy/http2/Http2Stream.h | 2 +- src/traffic_server/InkAPI.cc | 41 ++++++++++++------- 7 files changed, 48 insertions(+), 30 deletions(-) diff --git a/doc/developer-guide/api/functions/TSHttpTxnServerPush.en.rst b/doc/developer-guide/api/functions/TSHttpTxnServerPush.en.rst index 3e43cd26ad3..299172f6479 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnServerPush.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnServerPush.en.rst @@ -28,7 +28,7 @@ Synopsis #include -.. function:: void TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len) +.. function:: TSReturnCode TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len) Description =========== @@ -40,11 +40,8 @@ is not disabled by the client. You can call this API without checking whether Server Push is available on the transaction and it does nothing if Server Push is not available. - -Notes -===== - -This API may be changed in the future version since it is experimental. +This API returns an error if the URL to push is not valid, the client has Server Push disabled, +or there is an error creating the H/2 PUSH_PROMISE frame. See Also ======== diff --git a/include/ts/ts.h b/include/ts/ts.h index 60828f9bc57..79ad5236a0e 100644 --- a/include/ts/ts.h +++ b/include/ts/ts.h @@ -2535,6 +2535,15 @@ tsapi TSReturnCode TSRemapToUrlGet(TSHttpTxn txnp, TSMLoc *urlLocp); */ tsapi TSIOBufferReader TSHttpTxnPostBufferReaderGet(TSHttpTxn txnp); +/** + * Initiate an HTTP/2 Server Push preload request. + * Use this api to register a URL that you want to preload with HTTP/2 Server Push. + * + * @param url the URL string to preload. + * @param url_len the length of the URL string. + */ +tsapi TSReturnCode TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/proxy/http2/Http2ConnectionState.cc b/proxy/http2/Http2ConnectionState.cc index 7fb41ce6f64..b23e0a53e0f 100644 --- a/proxy/http2/Http2ConnectionState.cc +++ b/proxy/http2/Http2ConnectionState.cc @@ -1639,7 +1639,7 @@ Http2ConnectionState::send_headers_frame(Http2Stream *stream) ats_free(buf); } -void +bool Http2ConnectionState::send_push_promise_frame(Http2Stream *stream, URL &url, const MIMEField *accept_encoding) { HTTPHdr h1_hdr, h2_hdr; @@ -1651,7 +1651,7 @@ Http2ConnectionState::send_push_promise_frame(Http2Stream *stream, URL &url, con uint8_t flags = 0x00; if (client_settings.get(HTTP2_SETTINGS_ENABLE_PUSH) == 0) { - return; + return false; } Http2StreamDebug(ua_session, stream->get_id(), "Send PUSH_PROMISE frame"); @@ -1681,14 +1681,14 @@ Http2ConnectionState::send_push_promise_frame(Http2Stream *stream, URL &url, con buf = static_cast(ats_malloc(buf_len)); if (buf == nullptr) { h2_hdr.destroy(); - return; + return false; } Http2ErrorCode result = http2_encode_header_blocks(&h2_hdr, buf, buf_len, &header_blocks_size, *(this->remote_hpack_handle), client_settings.get(HTTP2_SETTINGS_HEADER_TABLE_SIZE)); if (result != Http2ErrorCode::HTTP2_ERROR_NO_ERROR) { h2_hdr.destroy(); ats_free(buf); - return; + return false; } // Send a PUSH_PROMISE frame @@ -1736,7 +1736,7 @@ Http2ConnectionState::send_push_promise_frame(Http2Stream *stream, URL &url, con stream = this->create_stream(id, error); if (!stream) { h2_hdr.destroy(); - return; + return false; } SCOPED_MUTEX_LOCK(stream_lock, stream->mutex, this_ethread()); @@ -1759,6 +1759,7 @@ Http2ConnectionState::send_push_promise_frame(Http2Stream *stream, URL &url, con stream->send_request(*this); h2_hdr.destroy(); + return true; } void diff --git a/proxy/http2/Http2ConnectionState.h b/proxy/http2/Http2ConnectionState.h index 01c80cfa21c..afd438571f3 100644 --- a/proxy/http2/Http2ConnectionState.h +++ b/proxy/http2/Http2ConnectionState.h @@ -247,7 +247,7 @@ class Http2ConnectionState : public Continuation void send_data_frames(Http2Stream *stream); Http2SendDataFrameResult send_a_data_frame(Http2Stream *stream, size_t &payload_length); void send_headers_frame(Http2Stream *stream); - void send_push_promise_frame(Http2Stream *stream, URL &url, const MIMEField *accept_encoding); + bool send_push_promise_frame(Http2Stream *stream, URL &url, const MIMEField *accept_encoding); void send_rst_stream_frame(Http2StreamId id, Http2ErrorCode ec); void send_settings_frame(const Http2ConnectionSettings &new_settings); void send_ping_frame(Http2StreamId id, uint8_t flag, const uint8_t *opaque_data); diff --git a/proxy/http2/Http2Stream.cc b/proxy/http2/Http2Stream.cc index 8d2d5c62a49..eb98c4cbf96 100644 --- a/proxy/http2/Http2Stream.cc +++ b/proxy/http2/Http2Stream.cc @@ -683,12 +683,12 @@ Http2Stream::signal_write_event(bool call_update) } } -void +bool Http2Stream::push_promise(URL &url, const MIMEField *accept_encoding) { Http2ClientSession *h2_proxy_ssn = static_cast(this->_proxy_ssn); SCOPED_MUTEX_LOCK(lock, h2_proxy_ssn->connection_state.mutex, this_ethread()); - h2_proxy_ssn->connection_state.send_push_promise_frame(this, url, accept_encoding); + return h2_proxy_ssn->connection_state.send_push_promise_frame(this, url, accept_encoding); } void diff --git a/proxy/http2/Http2Stream.h b/proxy/http2/Http2Stream.h index 58baee67281..6a522a8cf6f 100644 --- a/proxy/http2/Http2Stream.h +++ b/proxy/http2/Http2Stream.h @@ -75,7 +75,7 @@ class Http2Stream : public ProxyTransaction void update_write_request(IOBufferReader *buf_reader, int64_t write_len, bool send_update); void signal_write_event(bool call_update); void restart_sending(); - void push_promise(URL &url, const MIMEField *accept_encoding); + bool push_promise(URL &url, const MIMEField *accept_encoding); // Stream level window size ssize_t client_rwnd() const; diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc index 1d9dea39515..fb910e0b66d 100644 --- a/src/traffic_server/InkAPI.cc +++ b/src/traffic_server/InkAPI.cc @@ -8026,7 +8026,7 @@ TSHttpTxnIsInternal(TSHttpTxn txnp) return TSHttpSsnIsInternal(TSHttpTxnSsnGet(txnp)); } -void +TSReturnCode TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len) { sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS); @@ -8035,26 +8035,37 @@ TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len) url_obj.create(nullptr); if (url_obj.parse(url, url_len) == PARSE_RESULT_ERROR) { url_obj.destroy(); - return; + return TS_ERROR; } HttpSM *sm = reinterpret_cast(txnp); Http2Stream *stream = dynamic_cast(sm->ua_txn); - if (stream) { - Http2ClientSession *ua_session = static_cast(stream->get_proxy_ssn()); - SCOPED_MUTEX_LOCK(lock, ua_session->mutex, this_ethread()); - if (!ua_session->connection_state.is_state_closed() && !ua_session->is_url_pushed(url, url_len)) { - HTTPHdr *hptr = &(sm->t_state.hdr_info.client_request); - TSMLoc obj = reinterpret_cast(hptr->m_http); - - MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj); - MIMEField *f = mime_hdr_field_find(mh, MIME_FIELD_ACCEPT_ENCODING, MIME_LEN_ACCEPT_ENCODING); - stream->push_promise(url_obj, f); - - ua_session->add_url_to_pushed_table(url, url_len); - } + if (stream == nullptr) { + url_obj.destroy(); + return TS_ERROR; + } + + Http2ClientSession *ua_session = static_cast(stream->get_proxy_ssn()); + SCOPED_MUTEX_LOCK(lock, ua_session->mutex, this_ethread()); + if (ua_session->connection_state.is_state_closed() || ua_session->is_url_pushed(url, url_len)) { + url_obj.destroy(); + return TS_ERROR; } + + HTTPHdr *hptr = &(sm->t_state.hdr_info.client_request); + TSMLoc obj = reinterpret_cast(hptr->m_http); + + MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj); + MIMEField *f = mime_hdr_field_find(mh, MIME_FIELD_ACCEPT_ENCODING, MIME_LEN_ACCEPT_ENCODING); + if (!stream->push_promise(url_obj, f)) { + url_obj.destroy(); + return TS_ERROR; + } + + ua_session->add_url_to_pushed_table(url, url_len); + url_obj.destroy(); + return TS_SUCCESS; } TSReturnCode From ebc3ec1e5d73b3b1e383eea521eda91ec59ffe53 Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Fri, 8 Nov 2019 11:48:25 -0700 Subject: [PATCH 133/718] Revert "Change API to return a TSReturnCode code." This reverts commit 469d4d8c05c28291d40e26af8cce2abc01fc03b7. --- .../api/functions/TSHttpTxnServerPush.en.rst | 9 ++-- include/ts/ts.h | 9 ---- proxy/http2/Http2ConnectionState.cc | 11 +++-- proxy/http2/Http2ConnectionState.h | 2 +- proxy/http2/Http2Stream.cc | 4 +- proxy/http2/Http2Stream.h | 2 +- src/traffic_server/InkAPI.cc | 41 +++++++------------ 7 files changed, 30 insertions(+), 48 deletions(-) diff --git a/doc/developer-guide/api/functions/TSHttpTxnServerPush.en.rst b/doc/developer-guide/api/functions/TSHttpTxnServerPush.en.rst index 299172f6479..3e43cd26ad3 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnServerPush.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnServerPush.en.rst @@ -28,7 +28,7 @@ Synopsis #include -.. function:: TSReturnCode TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len) +.. function:: void TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len) Description =========== @@ -40,8 +40,11 @@ is not disabled by the client. You can call this API without checking whether Server Push is available on the transaction and it does nothing if Server Push is not available. -This API returns an error if the URL to push is not valid, the client has Server Push disabled, -or there is an error creating the H/2 PUSH_PROMISE frame. + +Notes +===== + +This API may be changed in the future version since it is experimental. See Also ======== diff --git a/include/ts/ts.h b/include/ts/ts.h index 79ad5236a0e..60828f9bc57 100644 --- a/include/ts/ts.h +++ b/include/ts/ts.h @@ -2535,15 +2535,6 @@ tsapi TSReturnCode TSRemapToUrlGet(TSHttpTxn txnp, TSMLoc *urlLocp); */ tsapi TSIOBufferReader TSHttpTxnPostBufferReaderGet(TSHttpTxn txnp); -/** - * Initiate an HTTP/2 Server Push preload request. - * Use this api to register a URL that you want to preload with HTTP/2 Server Push. - * - * @param url the URL string to preload. - * @param url_len the length of the URL string. - */ -tsapi TSReturnCode TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len); - #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/proxy/http2/Http2ConnectionState.cc b/proxy/http2/Http2ConnectionState.cc index b23e0a53e0f..7fb41ce6f64 100644 --- a/proxy/http2/Http2ConnectionState.cc +++ b/proxy/http2/Http2ConnectionState.cc @@ -1639,7 +1639,7 @@ Http2ConnectionState::send_headers_frame(Http2Stream *stream) ats_free(buf); } -bool +void Http2ConnectionState::send_push_promise_frame(Http2Stream *stream, URL &url, const MIMEField *accept_encoding) { HTTPHdr h1_hdr, h2_hdr; @@ -1651,7 +1651,7 @@ Http2ConnectionState::send_push_promise_frame(Http2Stream *stream, URL &url, con uint8_t flags = 0x00; if (client_settings.get(HTTP2_SETTINGS_ENABLE_PUSH) == 0) { - return false; + return; } Http2StreamDebug(ua_session, stream->get_id(), "Send PUSH_PROMISE frame"); @@ -1681,14 +1681,14 @@ Http2ConnectionState::send_push_promise_frame(Http2Stream *stream, URL &url, con buf = static_cast(ats_malloc(buf_len)); if (buf == nullptr) { h2_hdr.destroy(); - return false; + return; } Http2ErrorCode result = http2_encode_header_blocks(&h2_hdr, buf, buf_len, &header_blocks_size, *(this->remote_hpack_handle), client_settings.get(HTTP2_SETTINGS_HEADER_TABLE_SIZE)); if (result != Http2ErrorCode::HTTP2_ERROR_NO_ERROR) { h2_hdr.destroy(); ats_free(buf); - return false; + return; } // Send a PUSH_PROMISE frame @@ -1736,7 +1736,7 @@ Http2ConnectionState::send_push_promise_frame(Http2Stream *stream, URL &url, con stream = this->create_stream(id, error); if (!stream) { h2_hdr.destroy(); - return false; + return; } SCOPED_MUTEX_LOCK(stream_lock, stream->mutex, this_ethread()); @@ -1759,7 +1759,6 @@ Http2ConnectionState::send_push_promise_frame(Http2Stream *stream, URL &url, con stream->send_request(*this); h2_hdr.destroy(); - return true; } void diff --git a/proxy/http2/Http2ConnectionState.h b/proxy/http2/Http2ConnectionState.h index afd438571f3..01c80cfa21c 100644 --- a/proxy/http2/Http2ConnectionState.h +++ b/proxy/http2/Http2ConnectionState.h @@ -247,7 +247,7 @@ class Http2ConnectionState : public Continuation void send_data_frames(Http2Stream *stream); Http2SendDataFrameResult send_a_data_frame(Http2Stream *stream, size_t &payload_length); void send_headers_frame(Http2Stream *stream); - bool send_push_promise_frame(Http2Stream *stream, URL &url, const MIMEField *accept_encoding); + void send_push_promise_frame(Http2Stream *stream, URL &url, const MIMEField *accept_encoding); void send_rst_stream_frame(Http2StreamId id, Http2ErrorCode ec); void send_settings_frame(const Http2ConnectionSettings &new_settings); void send_ping_frame(Http2StreamId id, uint8_t flag, const uint8_t *opaque_data); diff --git a/proxy/http2/Http2Stream.cc b/proxy/http2/Http2Stream.cc index eb98c4cbf96..8d2d5c62a49 100644 --- a/proxy/http2/Http2Stream.cc +++ b/proxy/http2/Http2Stream.cc @@ -683,12 +683,12 @@ Http2Stream::signal_write_event(bool call_update) } } -bool +void Http2Stream::push_promise(URL &url, const MIMEField *accept_encoding) { Http2ClientSession *h2_proxy_ssn = static_cast(this->_proxy_ssn); SCOPED_MUTEX_LOCK(lock, h2_proxy_ssn->connection_state.mutex, this_ethread()); - return h2_proxy_ssn->connection_state.send_push_promise_frame(this, url, accept_encoding); + h2_proxy_ssn->connection_state.send_push_promise_frame(this, url, accept_encoding); } void diff --git a/proxy/http2/Http2Stream.h b/proxy/http2/Http2Stream.h index 6a522a8cf6f..58baee67281 100644 --- a/proxy/http2/Http2Stream.h +++ b/proxy/http2/Http2Stream.h @@ -75,7 +75,7 @@ class Http2Stream : public ProxyTransaction void update_write_request(IOBufferReader *buf_reader, int64_t write_len, bool send_update); void signal_write_event(bool call_update); void restart_sending(); - bool push_promise(URL &url, const MIMEField *accept_encoding); + void push_promise(URL &url, const MIMEField *accept_encoding); // Stream level window size ssize_t client_rwnd() const; diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc index fb910e0b66d..1d9dea39515 100644 --- a/src/traffic_server/InkAPI.cc +++ b/src/traffic_server/InkAPI.cc @@ -8026,7 +8026,7 @@ TSHttpTxnIsInternal(TSHttpTxn txnp) return TSHttpSsnIsInternal(TSHttpTxnSsnGet(txnp)); } -TSReturnCode +void TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len) { sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS); @@ -8035,37 +8035,26 @@ TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len) url_obj.create(nullptr); if (url_obj.parse(url, url_len) == PARSE_RESULT_ERROR) { url_obj.destroy(); - return TS_ERROR; + return; } HttpSM *sm = reinterpret_cast(txnp); Http2Stream *stream = dynamic_cast(sm->ua_txn); - if (stream == nullptr) { - url_obj.destroy(); - return TS_ERROR; - } - - Http2ClientSession *ua_session = static_cast(stream->get_proxy_ssn()); - SCOPED_MUTEX_LOCK(lock, ua_session->mutex, this_ethread()); - if (ua_session->connection_state.is_state_closed() || ua_session->is_url_pushed(url, url_len)) { - url_obj.destroy(); - return TS_ERROR; - } - - HTTPHdr *hptr = &(sm->t_state.hdr_info.client_request); - TSMLoc obj = reinterpret_cast(hptr->m_http); - - MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj); - MIMEField *f = mime_hdr_field_find(mh, MIME_FIELD_ACCEPT_ENCODING, MIME_LEN_ACCEPT_ENCODING); - if (!stream->push_promise(url_obj, f)) { - url_obj.destroy(); - return TS_ERROR; + if (stream) { + Http2ClientSession *ua_session = static_cast(stream->get_proxy_ssn()); + SCOPED_MUTEX_LOCK(lock, ua_session->mutex, this_ethread()); + if (!ua_session->connection_state.is_state_closed() && !ua_session->is_url_pushed(url, url_len)) { + HTTPHdr *hptr = &(sm->t_state.hdr_info.client_request); + TSMLoc obj = reinterpret_cast(hptr->m_http); + + MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj); + MIMEField *f = mime_hdr_field_find(mh, MIME_FIELD_ACCEPT_ENCODING, MIME_LEN_ACCEPT_ENCODING); + stream->push_promise(url_obj, f); + + ua_session->add_url_to_pushed_table(url, url_len); + } } - - ua_session->add_url_to_pushed_table(url, url_len); - url_obj.destroy(); - return TS_SUCCESS; } TSReturnCode From 197b3ac58154794445c9909311080a18df4a2ef4 Mon Sep 17 00:00:00 2001 From: David Calavera Date: Wed, 9 Oct 2019 21:55:43 -0700 Subject: [PATCH 134/718] Move TSHttpTxnServerPush to the stable API interface. Signed-off-by: David Calavera (cherry picked from commit b58fcfd326c9a1ecb3f9103da838fbf17eb2afb8) --- .../api/functions/TSHttpTxnServerPush.en.rst | 8 +------- example/plugins/c-api/server_push/server_push.c | 1 - include/ts/experimental.h | 2 -- include/ts/ts.h | 9 +++++++++ 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/developer-guide/api/functions/TSHttpTxnServerPush.en.rst b/doc/developer-guide/api/functions/TSHttpTxnServerPush.en.rst index 3e43cd26ad3..be9ba1d4e38 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnServerPush.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnServerPush.en.rst @@ -26,7 +26,7 @@ Synopsis .. code-block:: cpp - #include + #include .. function:: void TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len) @@ -40,12 +40,6 @@ is not disabled by the client. You can call this API without checking whether Server Push is available on the transaction and it does nothing if Server Push is not available. - -Notes -===== - -This API may be changed in the future version since it is experimental. - See Also ======== diff --git a/example/plugins/c-api/server_push/server_push.c b/example/plugins/c-api/server_push/server_push.c index 41203f532db..c921269aa1b 100644 --- a/example/plugins/c-api/server_push/server_push.c +++ b/example/plugins/c-api/server_push/server_push.c @@ -36,7 +36,6 @@ #include #include "ts/ts.h" -#include "ts/experimental.h" #include "tscore/ink_defs.h" const char *PLUGIN_NAME = "server_push"; diff --git a/include/ts/experimental.h b/include/ts/experimental.h index fa8e7ead89c..88b7a1ddef6 100644 --- a/include/ts/experimental.h +++ b/include/ts/experimental.h @@ -223,8 +223,6 @@ tsapi TSReturnCode TSHttpTxnUpdateCachedObject(TSHttpTxn txnp); ****************************************************************************/ tsapi int TSHttpTxnLookingUpTypeGet(TSHttpTxn txnp); -tsapi void TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len); - /* ip addr parsing */ tsapi TSReturnCode TSIpStringToAddr(const char *str, size_t str_len, struct sockaddr *addr); diff --git a/include/ts/ts.h b/include/ts/ts.h index 60828f9bc57..17748d4b96d 100644 --- a/include/ts/ts.h +++ b/include/ts/ts.h @@ -2535,6 +2535,15 @@ tsapi TSReturnCode TSRemapToUrlGet(TSHttpTxn txnp, TSMLoc *urlLocp); */ tsapi TSIOBufferReader TSHttpTxnPostBufferReaderGet(TSHttpTxn txnp); +/** + * Initiate an HTTP/2 Server Push preload request. + * Use this api to register a URL that you want to preload with HTTP/2 Server Push. + * + * @param url the URL string to preload. + * @param url_len the length of the URL string. + */ +tsapi void TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len); + #ifdef __cplusplus } #endif /* __cplusplus */ From 058ac2f8de3e270c99e03e97c6c209c4f04b6734 Mon Sep 17 00:00:00 2001 From: David Calavera Date: Wed, 9 Oct 2019 21:57:47 -0700 Subject: [PATCH 135/718] Promote server_push_preload plugin. Move this plugin out of experimental at the same time that the API is promoted. Signed-off-by: David Calavera (cherry picked from commit 11a7f1d1333876a3909c578fd12f92be1da1bed9) --- plugins/Makefile.am | 2 +- .../server_push_preload/README.md | 3 -- .../server_push_preload/Makefile.inc | 10 ++-- plugins/server_push_preload/README.md | 17 ++++++ .../server_push_preload.cc | 53 +++++++++++++++---- 5 files changed, 67 insertions(+), 18 deletions(-) delete mode 100644 plugins/experimental/server_push_preload/README.md rename plugins/{experimental => }/server_push_preload/Makefile.inc (71%) create mode 100644 plugins/server_push_preload/README.md rename plugins/{experimental => }/server_push_preload/server_push_preload.cc (74%) diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 5af6494495f..ff92a3d744c 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -50,6 +50,7 @@ include regex_remap/Makefile.inc include regex_revalidate/Makefile.inc include remap_purge/Makefile.inc include s3_auth/Makefile.inc +include server_push_preload/Makefile.inc include stats_over_http/Makefile.inc include tcpinfo/Makefile.inc include xdebug/Makefile.inc @@ -72,7 +73,6 @@ include experimental/metalink/Makefile.inc include experimental/money_trace/Makefile.inc include experimental/mp4/Makefile.inc include experimental/remap_stats/Makefile.inc -include experimental/server_push_preload/Makefile.inc include experimental/slice/Makefile.inc include experimental/sslheaders/Makefile.inc include experimental/stream_editor/Makefile.inc diff --git a/plugins/experimental/server_push_preload/README.md b/plugins/experimental/server_push_preload/README.md deleted file mode 100644 index 296794c8e15..00000000000 --- a/plugins/experimental/server_push_preload/README.md +++ /dev/null @@ -1,3 +0,0 @@ -Parse origin response Link headers and use H2 Server Push to initiate push requests of assets that have the preload keyword. - -https://www.w3.org/TR/preload/ diff --git a/plugins/experimental/server_push_preload/Makefile.inc b/plugins/server_push_preload/Makefile.inc similarity index 71% rename from plugins/experimental/server_push_preload/Makefile.inc rename to plugins/server_push_preload/Makefile.inc index 5a04108ac2e..518d71c7fb3 100644 --- a/plugins/experimental/server_push_preload/Makefile.inc +++ b/plugins/server_push_preload/Makefile.inc @@ -14,14 +14,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -pkglib_LTLIBRARIES += experimental/server_push_preload/server_push_preload.la +pkglib_LTLIBRARIES += server_push_preload/server_push_preload.la -experimental_server_push_preload_server_push_preload_la_SOURCES = \ - experimental/server_push_preload/server_push_preload.cc +server_push_preload_server_push_preload_la_SOURCES = \ + server_push_preload/server_push_preload.cc -experimental_server_push_preload_server_push_preload_la_LDFLAGS = \ +server_push_preload_server_push_preload_la_LDFLAGS = \ $(AM_LDFLAGS) -experimental_server_push_preload_server_push_preload_la_LIBADD = \ +server_push_preload_server_push_preload_la_LIBADD = \ $(top_builddir)/src/tscpp/api/libtscppapi.la diff --git a/plugins/server_push_preload/README.md b/plugins/server_push_preload/README.md new file mode 100644 index 00000000000..4079c895ff4 --- /dev/null +++ b/plugins/server_push_preload/README.md @@ -0,0 +1,17 @@ +Parse origin response Link headers and use H2 Server Push to initiate push requests of assets that have the preload keyword. + +https://www.w3.org/TR/preload/ + +This plugin can be used as a global plugin or a remap plugin. + +To use it as a global plugin for all your remaps, add this line to your `plugins.config` file: + +``` +server_push_preload.so +``` + +To use it as a remap plugin add it to one of your remaps in the `remap.config` file: + +``` +map https://foo.cow.com/ https://bar.cow.com @plugin=server_push_preload.so +``` \ No newline at end of file diff --git a/plugins/experimental/server_push_preload/server_push_preload.cc b/plugins/server_push_preload/server_push_preload.cc similarity index 74% rename from plugins/experimental/server_push_preload/server_push_preload.cc rename to plugins/server_push_preload/server_push_preload.cc index def21cca672..68c44101200 100644 --- a/plugins/experimental/server_push_preload/server_push_preload.cc +++ b/plugins/server_push_preload/server_push_preload.cc @@ -26,9 +26,9 @@ #include #include #include -#include #include "tscpp/api/GlobalPlugin.h" -#include "tscpp/api/utils.h" +#include "tscpp/api/RemapPlugin.h" +#include "tscpp/api/TransactionPlugin.h" #define PLUGIN_NAME "server_push_preload" #define PRELOAD_PARAM "rel=preload" @@ -41,16 +41,16 @@ static regex linkRegexp("<([^>]+)>;(.+)"); namespace { -GlobalPlugin *plugin; -} +GlobalPlugin *globalPlugin; +RemapPlugin *remapPlugin; +} // namespace -class LinkServerPushPlugin : public GlobalPlugin +class ServerPushTransaction : public TransactionPlugin { public: - LinkServerPushPlugin() + explicit ServerPushTransaction(Transaction &transaction) : TransactionPlugin(transaction) { - TSDebug(PLUGIN_NAME, "registering transaction hooks"); - LinkServerPushPlugin::registerHook(HOOK_SEND_RESPONSE_HEADERS); + TransactionPlugin::registerHook(HOOK_SEND_RESPONSE_HEADERS); } void @@ -134,6 +134,32 @@ class LinkServerPushPlugin : public GlobalPlugin } }; +class ServerPushRemap : public RemapPlugin +{ +public: + explicit ServerPushRemap(void **instance_handle) : RemapPlugin(instance_handle) {} + + Result + doRemap(const Url &map_from_url, const Url &map_to_url, Transaction &transaction, bool &redirect) override + { + transaction.addPlugin(new ServerPushTransaction(transaction)); + return RESULT_DID_REMAP; + } +}; + +class ServerPushGlobal : public GlobalPlugin +{ +public: + ServerPushGlobal() { GlobalPlugin::registerHook(HOOK_READ_REQUEST_HEADERS_PRE_REMAP); } + + void + handleReadRequestHeadersPreRemap(Transaction &transaction) override + { + transaction.addPlugin(new ServerPushTransaction(transaction)); + transaction.resume(); + } +}; + void TSPluginInit(int argc ATSCPPAPI_UNUSED, const char *argv[] ATSCPPAPI_UNUSED) { @@ -141,5 +167,14 @@ TSPluginInit(int argc ATSCPPAPI_UNUSED, const char *argv[] ATSCPPAPI_UNUSED) if (!RegisterGlobalPlugin("ServerPushPreloadPlugin", PLUGIN_NAME, "dev@trafficserver.apache.org")) { return; } - plugin = new LinkServerPushPlugin(); + globalPlugin = new ServerPushGlobal(); } + +TSReturnCode +TSRemapNewInstance(int argc ATSCPPAPI_UNUSED, char *argv[] ATSCPPAPI_UNUSED, void **instance_handle, char *errbuf ATSCPPAPI_UNUSED, + int errbuf_size ATSCPPAPI_UNUSED) +{ + TSDebug(PLUGIN_NAME, "New Instance"); + remapPlugin = new ServerPushRemap(instance_handle); + return TS_SUCCESS; +} \ No newline at end of file From db47ab74b62d4efe7f93bc546f08f878f9aaf167 Mon Sep 17 00:00:00 2001 From: David Calavera Date: Tue, 29 Oct 2019 09:30:24 -0700 Subject: [PATCH 136/718] Change API to return a TSReturnCode code. Return a TS_ERROR when we cannot push the url to the promise table. Signed-off-by: David Calavera (cherry picked from commit 4960789e3306dca7968a74ebd4f9eba4d45e1d2a) --- .../api/functions/TSHttpTxnServerPush.en.rst | 5 ++- include/ts/ts.h | 2 +- proxy/http2/Http2ConnectionState.cc | 11 ++--- proxy/http2/Http2ConnectionState.h | 2 +- proxy/http2/Http2Stream.cc | 4 +- proxy/http2/Http2Stream.h | 2 +- src/traffic_server/InkAPI.cc | 41 ++++++++++++------- 7 files changed, 41 insertions(+), 26 deletions(-) diff --git a/doc/developer-guide/api/functions/TSHttpTxnServerPush.en.rst b/doc/developer-guide/api/functions/TSHttpTxnServerPush.en.rst index be9ba1d4e38..0710a07faa9 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnServerPush.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnServerPush.en.rst @@ -28,7 +28,7 @@ Synopsis #include -.. function:: void TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len) +.. function:: TSReturnCode TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len) Description =========== @@ -40,6 +40,9 @@ is not disabled by the client. You can call this API without checking whether Server Push is available on the transaction and it does nothing if Server Push is not available. +This API returns an error if the URL to push is not valid, the client has Server Push disabled, +or there is an error creating the H/2 PUSH_PROMISE frame. + See Also ======== diff --git a/include/ts/ts.h b/include/ts/ts.h index 17748d4b96d..79ad5236a0e 100644 --- a/include/ts/ts.h +++ b/include/ts/ts.h @@ -2542,7 +2542,7 @@ tsapi TSIOBufferReader TSHttpTxnPostBufferReaderGet(TSHttpTxn txnp); * @param url the URL string to preload. * @param url_len the length of the URL string. */ -tsapi void TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len); +tsapi TSReturnCode TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len); #ifdef __cplusplus } diff --git a/proxy/http2/Http2ConnectionState.cc b/proxy/http2/Http2ConnectionState.cc index 7fb41ce6f64..b23e0a53e0f 100644 --- a/proxy/http2/Http2ConnectionState.cc +++ b/proxy/http2/Http2ConnectionState.cc @@ -1639,7 +1639,7 @@ Http2ConnectionState::send_headers_frame(Http2Stream *stream) ats_free(buf); } -void +bool Http2ConnectionState::send_push_promise_frame(Http2Stream *stream, URL &url, const MIMEField *accept_encoding) { HTTPHdr h1_hdr, h2_hdr; @@ -1651,7 +1651,7 @@ Http2ConnectionState::send_push_promise_frame(Http2Stream *stream, URL &url, con uint8_t flags = 0x00; if (client_settings.get(HTTP2_SETTINGS_ENABLE_PUSH) == 0) { - return; + return false; } Http2StreamDebug(ua_session, stream->get_id(), "Send PUSH_PROMISE frame"); @@ -1681,14 +1681,14 @@ Http2ConnectionState::send_push_promise_frame(Http2Stream *stream, URL &url, con buf = static_cast(ats_malloc(buf_len)); if (buf == nullptr) { h2_hdr.destroy(); - return; + return false; } Http2ErrorCode result = http2_encode_header_blocks(&h2_hdr, buf, buf_len, &header_blocks_size, *(this->remote_hpack_handle), client_settings.get(HTTP2_SETTINGS_HEADER_TABLE_SIZE)); if (result != Http2ErrorCode::HTTP2_ERROR_NO_ERROR) { h2_hdr.destroy(); ats_free(buf); - return; + return false; } // Send a PUSH_PROMISE frame @@ -1736,7 +1736,7 @@ Http2ConnectionState::send_push_promise_frame(Http2Stream *stream, URL &url, con stream = this->create_stream(id, error); if (!stream) { h2_hdr.destroy(); - return; + return false; } SCOPED_MUTEX_LOCK(stream_lock, stream->mutex, this_ethread()); @@ -1759,6 +1759,7 @@ Http2ConnectionState::send_push_promise_frame(Http2Stream *stream, URL &url, con stream->send_request(*this); h2_hdr.destroy(); + return true; } void diff --git a/proxy/http2/Http2ConnectionState.h b/proxy/http2/Http2ConnectionState.h index 01c80cfa21c..afd438571f3 100644 --- a/proxy/http2/Http2ConnectionState.h +++ b/proxy/http2/Http2ConnectionState.h @@ -247,7 +247,7 @@ class Http2ConnectionState : public Continuation void send_data_frames(Http2Stream *stream); Http2SendDataFrameResult send_a_data_frame(Http2Stream *stream, size_t &payload_length); void send_headers_frame(Http2Stream *stream); - void send_push_promise_frame(Http2Stream *stream, URL &url, const MIMEField *accept_encoding); + bool send_push_promise_frame(Http2Stream *stream, URL &url, const MIMEField *accept_encoding); void send_rst_stream_frame(Http2StreamId id, Http2ErrorCode ec); void send_settings_frame(const Http2ConnectionSettings &new_settings); void send_ping_frame(Http2StreamId id, uint8_t flag, const uint8_t *opaque_data); diff --git a/proxy/http2/Http2Stream.cc b/proxy/http2/Http2Stream.cc index 8d2d5c62a49..eb98c4cbf96 100644 --- a/proxy/http2/Http2Stream.cc +++ b/proxy/http2/Http2Stream.cc @@ -683,12 +683,12 @@ Http2Stream::signal_write_event(bool call_update) } } -void +bool Http2Stream::push_promise(URL &url, const MIMEField *accept_encoding) { Http2ClientSession *h2_proxy_ssn = static_cast(this->_proxy_ssn); SCOPED_MUTEX_LOCK(lock, h2_proxy_ssn->connection_state.mutex, this_ethread()); - h2_proxy_ssn->connection_state.send_push_promise_frame(this, url, accept_encoding); + return h2_proxy_ssn->connection_state.send_push_promise_frame(this, url, accept_encoding); } void diff --git a/proxy/http2/Http2Stream.h b/proxy/http2/Http2Stream.h index 58baee67281..6a522a8cf6f 100644 --- a/proxy/http2/Http2Stream.h +++ b/proxy/http2/Http2Stream.h @@ -75,7 +75,7 @@ class Http2Stream : public ProxyTransaction void update_write_request(IOBufferReader *buf_reader, int64_t write_len, bool send_update); void signal_write_event(bool call_update); void restart_sending(); - void push_promise(URL &url, const MIMEField *accept_encoding); + bool push_promise(URL &url, const MIMEField *accept_encoding); // Stream level window size ssize_t client_rwnd() const; diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc index 1d9dea39515..fb910e0b66d 100644 --- a/src/traffic_server/InkAPI.cc +++ b/src/traffic_server/InkAPI.cc @@ -8026,7 +8026,7 @@ TSHttpTxnIsInternal(TSHttpTxn txnp) return TSHttpSsnIsInternal(TSHttpTxnSsnGet(txnp)); } -void +TSReturnCode TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len) { sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS); @@ -8035,26 +8035,37 @@ TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len) url_obj.create(nullptr); if (url_obj.parse(url, url_len) == PARSE_RESULT_ERROR) { url_obj.destroy(); - return; + return TS_ERROR; } HttpSM *sm = reinterpret_cast(txnp); Http2Stream *stream = dynamic_cast(sm->ua_txn); - if (stream) { - Http2ClientSession *ua_session = static_cast(stream->get_proxy_ssn()); - SCOPED_MUTEX_LOCK(lock, ua_session->mutex, this_ethread()); - if (!ua_session->connection_state.is_state_closed() && !ua_session->is_url_pushed(url, url_len)) { - HTTPHdr *hptr = &(sm->t_state.hdr_info.client_request); - TSMLoc obj = reinterpret_cast(hptr->m_http); - - MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj); - MIMEField *f = mime_hdr_field_find(mh, MIME_FIELD_ACCEPT_ENCODING, MIME_LEN_ACCEPT_ENCODING); - stream->push_promise(url_obj, f); - - ua_session->add_url_to_pushed_table(url, url_len); - } + if (stream == nullptr) { + url_obj.destroy(); + return TS_ERROR; + } + + Http2ClientSession *ua_session = static_cast(stream->get_proxy_ssn()); + SCOPED_MUTEX_LOCK(lock, ua_session->mutex, this_ethread()); + if (ua_session->connection_state.is_state_closed() || ua_session->is_url_pushed(url, url_len)) { + url_obj.destroy(); + return TS_ERROR; } + + HTTPHdr *hptr = &(sm->t_state.hdr_info.client_request); + TSMLoc obj = reinterpret_cast(hptr->m_http); + + MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj); + MIMEField *f = mime_hdr_field_find(mh, MIME_FIELD_ACCEPT_ENCODING, MIME_LEN_ACCEPT_ENCODING); + if (!stream->push_promise(url_obj, f)) { + url_obj.destroy(); + return TS_ERROR; + } + + ua_session->add_url_to_pushed_table(url, url_len); + url_obj.destroy(); + return TS_SUCCESS; } TSReturnCode From 95fab5ca7f29013a1f4880cdd90d1919af2ea51e Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Fri, 8 Nov 2019 12:19:29 -0700 Subject: [PATCH 137/718] Cleanup, and added TSHttpTxnServerPush changes --- doc/release-notes/upgrading.en.rst | 61 ++++++++++++++++++------------ doc/release-notes/whats-new.en.rst | 34 ++++++++++++----- 2 files changed, 60 insertions(+), 35 deletions(-) diff --git a/doc/release-notes/upgrading.en.rst b/doc/release-notes/upgrading.en.rst index f7a46b8b62d..4f6ab7fb3c5 100644 --- a/doc/release-notes/upgrading.en.rst +++ b/doc/release-notes/upgrading.en.rst @@ -97,50 +97,61 @@ you to avoid using any of these: Deprecated or Removed Features ------------------------------ -The following features, configurations and plugins are either removed or deprecated in this -version of ATS. Deprecated features should be avoided, with the expectation that they will be -removed in the next major release of ATS. +The following features, configurations and plugins are either removed +or deprecated in this version of ATS. Deprecated features should be +avoided, with the expectation that they will be removed in the next major +release of ATS. API Changes ----------- -Our APIs are guaranteed to be compatible within major versions, but we do make changes -for each new major release. +Our APIs are guaranteed to be compatible within major versions, but we do +make changes for each new major release. Removed APIs ~~~~~~~~~~~~ -* `TSHttpTxnRedirectRequest()` +* ``TSHttpTxnRedirectRequest()`` Renamed or modified APIs ~~~~~~~~~~~~~~~~~~~~~~~~ -* `TSVConnSSLConnectionGet` is renamed to be :c:func:`TSVConnSslConnectionGet`. +* ``TSVConnSSLConnectionGet()`` is renamed to be :c:func:`TSVConnSslConnectionGet`. -Cache ------ -The cache in this releases of ATS is compatible with previous versions of ATS. You would not expect -to lose your cache, or have to reinitialize the cache when upgrading. +* ``TSHttpTxnServerPush()`` now returns a :type:`TSReturnCode`. -However, due to changes in how remap plugins are processed, your cache key *might* change. In versions -to v9.0.0, the first plugin in a remap rule would get the pristine URL, and subsequent plugins would -get the remapped URL. As of v9.0.0, **all** plugins now receive the remapped URL. If you are using -a plugin that modifies the cache key, e.g. :ref:`admin-plugins-cachekey`, if it was evaluated first -in a remap rule, the behavior (input) changes, and therefore, cache keys can change! -The old `v23` cache is no longer supported, which means caches created with ATS v2.x will no longer be -possible to load with ATS v9.0.0 or later. We feel that this is an unlikely scenario, but if you do -run into this, clearing the cache is required. +Cache +----- +The cache in this releases of ATS is compatible with previous versions of ATS. +You would not expect to lose your cache, or have to reinitialize the cache when +upgrading. + +However, due to changes in how remap plugins are processed, your cache key +*might* change. In versions to v9.0.0, the first plugin in a remap rule would +get the pristine URL, and subsequent plugins would get the remapped URL. As of +v9.0.0, **all** plugins now receive the remapped URL. If you are using a +plugin that modifies the cache key, e.g. :ref:`admin-plugins-cachekey`, if it +was evaluated first in a remap rule, the behavior (input) changes, and +therefore, cache keys can change! + +The old ``v23`` cache is no longer supported, which means caches created with ATS +v2.x will no longer be possible to load with ATS v9.0.0 or later. We feel that +this is an unlikely scenario, but if you do run into this, clearing the cache +is required. Plugins ------- -The following plugins have changes that might require you to change configurations. +The following plugins have changes that might require you to change +configurations. header_rewrite ~~~~~~~~~~~~~~ -* The `%{PATH}` directive is now removed, and instead you want to use `%{CLIENT-URL:PATH}`. This was - done to unify the behavior of these operators, rather than having this one-off directive. +* The `%{PATH}` directive is now removed, and instead you want to use + `%{CLIENT-URL:PATH}`. This was done to unify the behavior of these + operators, rather than having this one-off directive. Platform specific ----------------- -Solaris is no longer a supported platform, but the code is still there. However, it's unlikely to work, -and unless someone takes on ownership of this Platform, it will be removed from the source in ATS v10.0.0. -For more details, see issue #5553. +Solaris is no longer a supported platform, but the code is still there. +However, it's unlikely to work, and unless someone takes on ownership of this +Platform, it will be removed from the source in ATS v10.0.0. For more details, +see issue #5553. diff --git a/doc/release-notes/whats-new.en.rst b/doc/release-notes/whats-new.en.rst index 53e4841fea9..a87b84c7f6c 100644 --- a/doc/release-notes/whats-new.en.rst +++ b/doc/release-notes/whats-new.en.rst @@ -21,8 +21,8 @@ What's New in ATS v9.x ======================= -This version of ATS includes over commits, from pull requests. A total of contributors -have participated in this development cycle. +This version of ATS includes over commits, from pull requests. A total +of contributors have participated in this development cycle. .. toctree:: :maxdepth: 1 @@ -30,25 +30,28 @@ have participated in this development cycle. New Features ------------ -This version of ATS has a number of new features (details below), but we're particularly excited about -the following features: +This version of ATS has a number of new features (details below), but we're +particularly excited about the following features: * Experimental QUIC support (draft 23). * TLS v1.3 0RTT support. PROXY protocol ~~~~~~~~~~~~~~ -ATS now supports the `PROXY `_ protocol, -on the inbound side. The incoming PROXY data gets transformed into the `Forwarded` header. +ATS now supports the `PROXY +`_ protocol, on +the inbound side. The incoming PROXY data gets transformed into the +``Forwarded`` header. Incompatible records.config settings ------------------------------------ -These are the changes that are most likely to cause problems during an upgrade. Take special care -making sure you have updated your configurations accordingly. +These are the changes that are most likely to cause problems during an upgrade. +Take special care making sure you have updated your configurations accordingly. Connection management ~~~~~~~~~~~~~~~~~~~~~ -The old settings for origin connection management included the following settings: +The old settings for origin connection management included the following +settings: * `proxy.config.http.origin_max_connections` * `proxy.config.http.origin_max_connections_queue` @@ -72,4 +75,15 @@ Plugins xdebug ~~~~~~ -* A new directive, `fwd=` to control the number of hops the header is forwarded for. +* A new directive, `fwd=` to control the number of hops the header is + forwarded for. + +Plugin APIs +----------- + +The API for server push is promoted to stable, and modified to return an error +code, to be consistent with other similar APIs. The new prototype is: + +.. code-block:: c + + TSReturnCode TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len); From 2b47b699bd8cb231b956fef4acc7aa150424451f Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Fri, 8 Nov 2019 12:33:13 -0700 Subject: [PATCH 138/718] Cleanup of release notes --- doc/release-notes/upgrading.en.rst | 4 ++-- doc/release-notes/whats-new.en.rst | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/release-notes/upgrading.en.rst b/doc/release-notes/upgrading.en.rst index 4f6ab7fb3c5..d2d20a15b9f 100644 --- a/doc/release-notes/upgrading.en.rst +++ b/doc/release-notes/upgrading.en.rst @@ -114,9 +114,9 @@ Removed APIs Renamed or modified APIs ~~~~~~~~~~~~~~~~~~~~~~~~ -* ``TSVConnSSLConnectionGet()`` is renamed to be :c:func:`TSVConnSslConnectionGet`. +* ``TSVConnSSLConnectionGet()`` is renamed to be :c:func:`TSVConnSslConnectionGet` -* ``TSHttpTxnServerPush()`` now returns a :type:`TSReturnCode`. +* ``TSHttpTxnServerPush()`` now returns a :type:`TSReturnCode` Cache diff --git a/doc/release-notes/whats-new.en.rst b/doc/release-notes/whats-new.en.rst index a87b84c7f6c..93486a04062 100644 --- a/doc/release-notes/whats-new.en.rst +++ b/doc/release-notes/whats-new.en.rst @@ -86,4 +86,4 @@ code, to be consistent with other similar APIs. The new prototype is: .. code-block:: c - TSReturnCode TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len); + .. c:function:: TSReturnCode TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len); From d6b2266987e1f07665c761c064bbd9f0a04a20db Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Fri, 8 Nov 2019 13:53:35 -0700 Subject: [PATCH 139/718] Explicit c:type: --- doc/release-notes/upgrading.en.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes/upgrading.en.rst b/doc/release-notes/upgrading.en.rst index d2d20a15b9f..67c98e2fe4c 100644 --- a/doc/release-notes/upgrading.en.rst +++ b/doc/release-notes/upgrading.en.rst @@ -116,7 +116,7 @@ Renamed or modified APIs ~~~~~~~~~~~~~~~~~~~~~~~~ * ``TSVConnSSLConnectionGet()`` is renamed to be :c:func:`TSVConnSslConnectionGet` -* ``TSHttpTxnServerPush()`` now returns a :type:`TSReturnCode` +* ``TSHttpTxnServerPush()`` now returns a :c:type:`TSReturnCode` Cache From 7e73a385d3f13ea31faf0c6b5da23e19993f1db5 Mon Sep 17 00:00:00 2001 From: Fei Deng Date: Fri, 8 Nov 2019 13:44:16 -0600 Subject: [PATCH 140/718] detect bogus jemalloc version (cherry picked from commit 02c0e5b4e2b14fc2fab567762e24a1aede3f7e29) --- build/jemalloc.m4 | 13 ++++++++++++- include/tscore/JeAllocator.h | 3 +++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/build/jemalloc.m4 b/build/jemalloc.m4 index 48b2cdc006d..6b707cdfd0a 100644 --- a/build/jemalloc.m4 +++ b/build/jemalloc.m4 @@ -68,7 +68,18 @@ if test "$enable_jemalloc" != "no"; then AC_CHECK_HEADERS(jemalloc/jemalloc.h, [jemalloc_have_headers=1]) fi if test "$jemalloc_have_headers" != "0"; then - jemalloch=1 + AC_RUN_IFELSE([ + AC_LANG_PROGRAM( + [#include ], + [ + #if (JEMALLOC_VERSION_MAJOR == 0) + exit(1); + #endif + ] + )], + [jemalloch=1], + [AC_MSG_ERROR(jemalloc has bogus version)] + ) else CPPFLAGS=$saved_cppflags LDFLAGS=$saved_ldflags diff --git a/include/tscore/JeAllocator.h b/include/tscore/JeAllocator.h index 7d1b678fdcc..24e94d9022e 100644 --- a/include/tscore/JeAllocator.h +++ b/include/tscore/JeAllocator.h @@ -26,6 +26,9 @@ #if TS_HAS_JEMALLOC #include +#if (JEMALLOC_VERSION_MAJOR == 0) +#error jemalloc has bogus version +#endif #if (JEMALLOC_VERSION_MAJOR == 5) && defined(MADV_DONTDUMP) #define JEMALLOC_NODUMP_ALLOCATOR_SUPPORTED 1 #endif /* MADV_DONTDUMP */ From 97b55e78b9fc9741e74230ff356c0c18cea4d4a8 Mon Sep 17 00:00:00 2001 From: bneradt Date: Mon, 28 Oct 2019 22:00:55 +0000 Subject: [PATCH 141/718] Only decrement log_stat_log_files_open_stat when the file is closed. (cherry picked from commit 0db18c7af94e6d81d997a583035f8834aa0c8813) --- include/tscore/BaseLogFile.h | 2 +- proxy/logging/LogFile.cc | 22 +++++++++++++++------- src/tscore/BaseLogFile.cc | 20 ++++++++++++++++---- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/include/tscore/BaseLogFile.h b/include/tscore/BaseLogFile.h index 38f6a496f04..aad473586d1 100644 --- a/include/tscore/BaseLogFile.h +++ b/include/tscore/BaseLogFile.h @@ -177,7 +177,7 @@ class BaseLogFile static bool rolled_logfile(char *path); static bool exists(const char *pathname); int open_file(int perm = -1); - void close_file(); + int close_file(); void change_name(const char *new_name); void display(FILE *fd = stdout); const char * diff --git a/proxy/logging/LogFile.cc b/proxy/logging/LogFile.cc index d0b95dae324..59c6bde2f3d 100644 --- a/proxy/logging/LogFile.cc +++ b/proxy/logging/LogFile.cc @@ -258,18 +258,24 @@ LogFile::close_file() { if (is_open()) { if (m_file_format == LOG_FILE_PIPE) { - ::close(m_fd); - Debug("log-file", "LogFile %s (fd=%d) is closed", m_name, m_fd); + if (::close(m_fd)) { + Error("Error closing LogFile %s: %s.", m_name, strerror(errno)); + } else { + Debug("log-file", "LogFile %s (fd=%d) is closed", m_name, m_fd); + RecIncrRawStat(log_rsb, this_thread()->mutex->thread_holding, log_stat_log_files_open_stat, -1); + } m_fd = -1; } else if (m_log) { - m_log->close_file(); - Debug("log-file", "LogFile %s is closed", m_log->get_name()); + if (m_log->close_file()) { + Error("Error closing LogFile %s: %s.", m_log->get_name(), strerror(errno)); + } else { + Debug("log-file", "LogFile %s is closed", m_log->get_name()); + RecIncrRawStat(log_rsb, this_thread()->mutex->thread_holding, log_stat_log_files_open_stat, -1); + } } else { Warning("LogFile %s is open but was not closed", m_name); } } - - RecIncrRawStat(log_rsb, this_thread()->mutex->thread_holding, log_stat_log_files_open_stat, -1); } struct RolledFile { @@ -369,7 +375,9 @@ LogFile::roll(long interval_start, long interval_end, bool reopen_after_rolling) // Since these two methods of using BaseLogFile are not compatible, we perform the logging log file specific // close file operation here within the containing LogFile object. if (m_log->roll(interval_start, interval_end)) { - m_log->close_file(); + if (m_log->close_file()) { + Error("Error closing LogFile %s: %s.", m_log->get_name(), strerror(errno)); + } if (reopen_after_rolling) { /* If we re-open now log file will be created even if there is nothing being logged */ diff --git a/src/tscore/BaseLogFile.cc b/src/tscore/BaseLogFile.cc index 1dac88fef52..26f567e02ef 100644 --- a/src/tscore/BaseLogFile.cc +++ b/src/tscore/BaseLogFile.cc @@ -339,18 +339,30 @@ BaseLogFile::open_file(int perm) return LOG_FILE_NO_ERROR; } -/* - * Closes actual log file, not metainfo +/** + * @brief Close the managed log file. + * + * @note This closes the actual log file, not its metainfo. + * + * @return The result of calling fclose on the file descriptor or 0 if the file + * was not open. If the result is non-zero, fclose failed and errno is set + * appropriately. */ -void +int BaseLogFile::close_file() { + int ret = 0; if (is_open()) { - fclose(m_fp); log_log_trace("BaseLogFile %s is closed\n", m_name.get()); + + // Both log_log_trace and fclose may set errno. Thus, keep fclose after + // log_log_trace so that by the time this function completes if errno was + // set by fclose it will remain upon function return. + ret = fclose(m_fp); m_fp = nullptr; m_is_init = false; } + return ret; } /* From ab5f56c08ebcf5e17525ceb15611320cda77db61 Mon Sep 17 00:00:00 2001 From: Randall Meyer Date: Fri, 1 Nov 2019 16:46:03 -0700 Subject: [PATCH 142/718] Normalize loopback usage in session_match autest (cherry picked from commit 07e6e2d4243ef218410b6dff22f85cfb314492cd) --- tests/gold_tests/session_sharing/session_match.test.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/gold_tests/session_sharing/session_match.test.py b/tests/gold_tests/session_sharing/session_match.test.py index 2e619e5eff9..20dcd618d83 100644 --- a/tests/gold_tests/session_sharing/session_match.test.py +++ b/tests/gold_tests/session_sharing/session_match.test.py @@ -70,9 +70,9 @@ def setupTS(self): def _runTraffic(self): self._tr.Processes.Default.Command = ( - 'curl -v -H\'Host: www.example.com\' -H\'Connection: close\' http://127.0.1:{port}/one &&' - 'curl -v -H\'Host: www.example.com\' -H\'Connection: close\' http://127.0.1:{port}/two &&' - 'curl -v -H\'Host: www.example.com\' -H\'Connection: close\' http://127.0.1:{port}/three'.format( + 'curl -v -H\'Host: www.example.com\' -H\'Connection: close\' http://127.0.0.1:{port}/one &&' + 'curl -v -H\'Host: www.example.com\' -H\'Connection: close\' http://127.0.0.1:{port}/two &&' + 'curl -v -H\'Host: www.example.com\' -H\'Connection: close\' http://127.0.0.1:{port}/three'.format( port = self._ts.Variables.port)) self._tr.Processes.Default.ReturnCode = 0 self._tr.Processes.Default.StartBefore(self._server) From 3115d02c16286e4180dfca7261b0e65f4ac3039c Mon Sep 17 00:00:00 2001 From: Randall Meyer Date: Mon, 4 Nov 2019 18:08:35 -0800 Subject: [PATCH 143/718] tests: Adds autest for WebSocket mappings (cherry picked from commit 5902d863869e7cc5147866d96bb8efe30b241668) --- .../remap/gold/remap-ws-upgrade-400.gold | 7 ++ .../remap/gold/remap-ws-upgrade.gold | 11 +++ tests/gold_tests/remap/remap_ws.test.py | 77 +++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 tests/gold_tests/remap/gold/remap-ws-upgrade-400.gold create mode 100644 tests/gold_tests/remap/gold/remap-ws-upgrade.gold create mode 100644 tests/gold_tests/remap/remap_ws.test.py diff --git a/tests/gold_tests/remap/gold/remap-ws-upgrade-400.gold b/tests/gold_tests/remap/gold/remap-ws-upgrade-400.gold new file mode 100644 index 00000000000..a46a2490de7 --- /dev/null +++ b/tests/gold_tests/remap/gold/remap-ws-upgrade-400.gold @@ -0,0 +1,7 @@ +`` +> GET /chat HTTP/1.1 +> Host: `` +> User-Agent: curl/`` +`` +< HTTP/1.1 400 Invalid Upgrade Request +`` diff --git a/tests/gold_tests/remap/gold/remap-ws-upgrade.gold b/tests/gold_tests/remap/gold/remap-ws-upgrade.gold new file mode 100644 index 00000000000..317fee1f53c --- /dev/null +++ b/tests/gold_tests/remap/gold/remap-ws-upgrade.gold @@ -0,0 +1,11 @@ +`` +> GET /chat HTTP/1.1 +> Host: `` +> User-Agent: curl/`` +`` +< HTTP/1.1 101 Switching Protocols +< Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= +< Date: `` +< Connection: Upgrade +< Upgrade: websocket +`` diff --git a/tests/gold_tests/remap/remap_ws.test.py b/tests/gold_tests/remap/remap_ws.test.py new file mode 100644 index 00000000000..5379c4d6518 --- /dev/null +++ b/tests/gold_tests/remap/remap_ws.test.py @@ -0,0 +1,77 @@ +''' +''' +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +Test.Summary = ''' +Test a basic remap of a websocket connections +''' + +Test.ContinueOnFail = True + +ts = Test.MakeATSProcess("ts", select_ports=False) +server = Test.MakeOriginServer("server") + +testName = "Test WebSocket Remaps" +request_header = {"headers": "GET /chat HTTP/1.1\r\nHost: www.example.com\r\nUpgrade: websocket\r\nConnection: Upgrade\r\n\r\n", + "body": None} +response_header = {"headers": "HTTP/1.1 101 OK\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n", + "body": None} +server.addResponse("sessionlog.json", request_header, response_header) + +ts.addSSLfile("ssl/server.pem") +ts.addSSLfile("ssl/server.key") + +ts.Disk.records_config.update({ + 'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir), + 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), + 'proxy.config.http.server_ports': '{0} {1}:proto=http2;http:ssl'.format(ts.Variables.port, ts.Variables.ssl_port), +}) + +ts.Disk.remap_config.AddLines([ + 'map ws://www.example.com:{1} ws://127.0.0.1:{0}'.format(server.Variables.Port, ts.Variables.port), + 'map wss://www.example.com:{1} ws://127.0.0.1:{0}'.format(server.Variables.Port, ts.Variables.ssl_port) +]) + +ts.Disk.ssl_multicert_config.AddLine( + 'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key' +) + +# wss mapping +tr = Test.AddTestRun() +tr.Processes.Default.StartBefore(server) +tr.Processes.Default.StartBefore(Test.Processes.ts, ready=1) +tr.Processes.Default.Command = 'curl --max-time 2 -v -s -q -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" -H "Sec-WebSocket-Version: 13" --http1.1 --resolve www.example.com:{0}:127.0.0.1 -k https://www.example.com:{0}/chat'.format(ts.Variables.ssl_port) +tr.Processes.Default.ReturnCode = 28 +tr.Processes.Default.Streams.stderr = "gold/remap-ws-upgrade.gold" +tr.StillRunningAfter = server +tr.StillRunningAfter = ts + +# ws mapping +tr = Test.AddTestRun() +tr.Processes.Default.Command = 'curl --max-time 2 -v -s -q -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" -H "Sec-WebSocket-Version: 13" --http1.1 --resolve www.example.com:{0}:127.0.0.1 -k http://www.example.com:{0}/chat'.format(ts.Variables.port) +tr.Processes.Default.ReturnCode = 28 +tr.Processes.Default.Streams.stderr = "gold/remap-ws-upgrade.gold" +tr.StillRunningAfter = server +tr.StillRunningAfter = ts + +# Missing required headers (should result in 400) +tr = Test.AddTestRun() +tr.Processes.Default.Command = 'curl --max-time 2 -v -s -q -H "Connection: Upgrade" -H "Upgrade: websocket" --http1.1 --resolve www.example.com:{0}:127.0.0.1 -k http://www.example.com:{0}/chat'.format(ts.Variables.port) +tr.Processes.Default.ReturnCode = 0 +tr.Processes.Default.Streams.stderr = "gold/remap-ws-upgrade-400.gold" +tr.StillRunningAfter = server +tr.StillRunningAfter = ts From 25db8be84f4be674fead009f32da63b19112f121 Mon Sep 17 00:00:00 2001 From: Fei Deng Date: Mon, 28 Oct 2019 10:15:26 -0500 Subject: [PATCH 144/718] thread ready check (cherry picked from commit 3ceab9e3d0426000ec1ec3c34decdb375906f073) --- iocore/eventsystem/I_EventProcessor.h | 4 ++++ iocore/eventsystem/UnixEventProcessor.cc | 27 ++++++++++++++++++++---- proxy/http/HttpProxyServerMain.cc | 4 ++-- proxy/http/HttpProxyServerMain.h | 2 +- src/traffic_server/traffic_server.cc | 12 ++++++++--- 5 files changed, 39 insertions(+), 10 deletions(-) diff --git a/iocore/eventsystem/I_EventProcessor.h b/iocore/eventsystem/I_EventProcessor.h index 761f9ca85c7..227ea192f5f 100644 --- a/iocore/eventsystem/I_EventProcessor.h +++ b/iocore/eventsystem/I_EventProcessor.h @@ -325,6 +325,8 @@ class EventProcessor : public Processor */ int n_ethreads = 0; + bool has_tg_started(int etype); + /*------------------------------------------------------*\ | Unix & non NT Interface | \*------------------------------------------------------*/ @@ -410,3 +412,5 @@ class EventProcessor : public Processor }; extern inkcoreapi class EventProcessor eventProcessor; + +void thread_started(EThread *); diff --git a/iocore/eventsystem/UnixEventProcessor.cc b/iocore/eventsystem/UnixEventProcessor.cc index 2182c34841d..2661b678f58 100644 --- a/iocore/eventsystem/UnixEventProcessor.cc +++ b/iocore/eventsystem/UnixEventProcessor.cc @@ -371,6 +371,7 @@ EventProcessor::spawn_event_threads(EventType ev_type, int n_threads, size_t sta } tg->_count = n_threads; n_ethreads += n_threads; + schedule_spawn(&thread_started, ev_type); // Separate loop to avoid race conditions between spawn events and updating the thread table for // the group. Some thread set up depends on knowing the total number of threads but that can't be @@ -394,10 +395,7 @@ EventProcessor::initThreadState(EThread *t) { // Run all thread type initialization continuations that match the event types for this thread. for (int i = 0; i < MAX_EVENT_TYPES; ++i) { - if (t->is_event_type(i)) { // that event type done here, roll thread start events of that type. - if (++thread_group[i]._started == thread_group[i]._count && thread_group[i]._afterStartCallback != nullptr) { - thread_group[i]._afterStartCallback(); - } + if (t->is_event_type(i)) { // To avoid race conditions on the event in the spawn queue, create a local one to actually send. // Use the spawn queue event as a read only model. Event *nev = eventAllocator.alloc(); @@ -491,3 +489,24 @@ EventProcessor::spawn_thread(Continuation *cont, const char *thr_name, size_t st return e; } + +bool +EventProcessor::has_tg_started(int etype) +{ + return thread_group[etype]._started == thread_group[etype]._count; +} + +void +thread_started(EThread *t) +{ + // Find what type of thread this is, and increment the "_started" counter of that thread type. + for (int i = 0; i < MAX_EVENT_TYPES; ++i) { + if (t->is_event_type(i)) { + if (++eventProcessor.thread_group[i]._started == eventProcessor.thread_group[i]._count && + eventProcessor.thread_group[i]._afterStartCallback != nullptr) { + eventProcessor.thread_group[i]._afterStartCallback(); + } + break; + } + } +} diff --git a/proxy/http/HttpProxyServerMain.cc b/proxy/http/HttpProxyServerMain.cc index 48ea161c874..9c80490ef8d 100644 --- a/proxy/http/HttpProxyServerMain.cc +++ b/proxy/http/HttpProxyServerMain.cc @@ -308,9 +308,9 @@ init_accept_HttpProxyServer(int n_accept_threads) * start_HttpProxyServer(). */ void -init_HttpProxyServer(EThread *) +init_HttpProxyServer() { - if (eventProcessor.thread_group[ET_NET]._started == num_of_net_threads) { + if (eventProcessor.has_tg_started(ET_NET)) { std::unique_lock lock(proxyServerMutex); et_net_threads_ready = true; lock.unlock(); diff --git a/proxy/http/HttpProxyServerMain.h b/proxy/http/HttpProxyServerMain.h index 96c461abecc..1de9ced2e98 100644 --- a/proxy/http/HttpProxyServerMain.h +++ b/proxy/http/HttpProxyServerMain.h @@ -38,7 +38,7 @@ void init_accept_HttpProxyServer(int n_accept_threads = 0); /** Checkes whether we can call start_HttpProxyServer(). */ -void init_HttpProxyServer(EThread *); +void init_HttpProxyServer(); /** Start the proxy server. The port data should have been created by @c prep_HttpProxyServer(). diff --git a/src/traffic_server/traffic_server.cc b/src/traffic_server/traffic_server.cc index 07d46ad740a..44e3d249725 100644 --- a/src/traffic_server/traffic_server.cc +++ b/src/traffic_server/traffic_server.cc @@ -1813,10 +1813,10 @@ main(int /* argc ATS_UNUSED */, const char **argv) quic_NetProcessor.init(); #endif - // If num_accept_threads == 0, let the ET_NET threads to set the condition variable, + // If num_accept_threads == 0, let the ET_NET threads set the condition variable, // Else we set it here so when checking the condition variable later it returns immediately. - if (num_accept_threads == 0) { - eventProcessor.schedule_spawn(&init_HttpProxyServer, ET_NET); + if (num_accept_threads == 0 || command_flag) { + eventProcessor.thread_group[ET_NET]._afterStartCallback = init_HttpProxyServer; } else { std::unique_lock lock(proxyServerMutex); et_net_threads_ready = true; @@ -1858,6 +1858,12 @@ main(int /* argc ATS_UNUSED */, const char **argv) int cmd_ret = cmd_mode(); if (cmd_ret != CMD_IN_PROGRESS) { + // Check the condition variable. + { + std::unique_lock lock(proxyServerMutex); + proxyServerCheck.wait(lock, [] { return et_net_threads_ready; }); + } + if (cmd_ret >= 0) { ::exit(0); // everything is OK } else { From 61697bbc96ce3c57048f93bd5c6f6c46d1814ca1 Mon Sep 17 00:00:00 2001 From: Randall Meyer Date: Mon, 4 Nov 2019 18:42:57 -0800 Subject: [PATCH 145/718] tests: Cleans up local variable is assigned to but never used warnings (cherry picked from commit 61cce69983283a9613cafb8867e53b8595465efe) --- tests/gold_tests/h2/h2bigclient.py | 1 - tests/gold_tests/h2/h2chunked.py | 1 - tests/gold_tests/h2/h2client.py | 1 - tests/gold_tests/tls/tls_ticket.test.py | 1 - 4 files changed, 4 deletions(-) diff --git a/tests/gold_tests/h2/h2bigclient.py b/tests/gold_tests/h2/h2bigclient.py index 6e0cec809e7..8bc6a066648 100644 --- a/tests/gold_tests/h2/h2bigclient.py +++ b/tests/gold_tests/h2/h2bigclient.py @@ -43,7 +43,6 @@ def makerequest(port): # Fetch the object twice so we know at least one time comes from cache # Exploring timing options sites = ['/bigfile', '/bigfile'] - responses = [] request_ids = [] for site in sites: request_id = conn.request('GET', url=site) diff --git a/tests/gold_tests/h2/h2chunked.py b/tests/gold_tests/h2/h2chunked.py index 8b1d05196ab..e92945036f7 100644 --- a/tests/gold_tests/h2/h2chunked.py +++ b/tests/gold_tests/h2/h2chunked.py @@ -41,7 +41,6 @@ def makerequest(port, _url): conn = HTTPConnection('localhost:{0}'.format(port), secure=True) sites = {'/'} - responses = [] request_ids = [] for site in sites: request_id = conn.request('GET', url=_url) diff --git a/tests/gold_tests/h2/h2client.py b/tests/gold_tests/h2/h2client.py index df0d19fb627..5042965ce26 100644 --- a/tests/gold_tests/h2/h2client.py +++ b/tests/gold_tests/h2/h2client.py @@ -41,7 +41,6 @@ def makerequest(port): conn = HTTPConnection('localhost:{0}'.format(port), secure=True) sites = {'/'} - responses = [] request_ids = [] for site in sites: request_id = conn.request('GET', url=site) diff --git a/tests/gold_tests/tls/tls_ticket.test.py b/tests/gold_tests/tls/tls_ticket.test.py index 4d34ddb679a..d26e14d810c 100644 --- a/tests/gold_tests/tls/tls_ticket.test.py +++ b/tests/gold_tests/tls/tls_ticket.test.py @@ -95,7 +95,6 @@ def checkSession(ev) : f1Content = f1.read() f2Content = f2.read() - sessRegex = re.compile('Session-ID: ([0-9A-F]+)') match1 = re.findall('Session-ID: ([0-9A-F]+)', f1Content) match2 = re.findall('Session-ID: ([0-9A-F]+)', f2Content) From 27f0af2b57e399cc7c352ffce7e9c42ca66dbccd Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Fri, 14 Jun 2019 11:17:09 +0900 Subject: [PATCH 146/718] Add AUTest using h2spec (cherry picked from commit 097017d7122d7b1ba82bfe5ea92f85ab7a17599b) --- tests/gold_tests/h2/gold/h2spec_stdout.gold | 3 + tests/gold_tests/h2/h2spec.test.py | 83 +++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 tests/gold_tests/h2/gold/h2spec_stdout.gold create mode 100644 tests/gold_tests/h2/h2spec.test.py diff --git a/tests/gold_tests/h2/gold/h2spec_stdout.gold b/tests/gold_tests/h2/gold/h2spec_stdout.gold new file mode 100644 index 00000000000..02732ee469e --- /dev/null +++ b/tests/gold_tests/h2/gold/h2spec_stdout.gold @@ -0,0 +1,3 @@ +`` +Finished in `` seconds +`` tests, `` passed, 0 skipped, 0 failed diff --git a/tests/gold_tests/h2/h2spec.test.py b/tests/gold_tests/h2/h2spec.test.py new file mode 100644 index 00000000000..a188e80a251 --- /dev/null +++ b/tests/gold_tests/h2/h2spec.test.py @@ -0,0 +1,83 @@ +''' +Test HTTP/2 with h2spec +''' +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os + +# ---- +# Setup Test +# ---- +Test.Summary = ''' +Test HTTP/2 with httpspec +''' + +Test.SkipUnless( + Condition.HasProgram("h2spec", "h2spec need to be installed on system for this test to work"), +) +Test.ContinueOnFail = True + +# ---- +# Setup httpbin Origin Server +# ---- +httpbin = Test.MakeHttpBinServer("httpbin") + +# ---- +# Setup ATS +# ---- +ts = Test.MakeATSProcess("ts", select_ports=False) + +# add ssl materials like key, certificates for the server +ts.addSSLfile("ssl/server.pem") +ts.addSSLfile("ssl/server.key") + +ts.Variables.ssl_port = 4443 +ts.Disk.remap_config.AddLine( + 'map / http://127.0.0.1:{0}'.format(httpbin.Variables.Port) +) +ts.Disk.ssl_multicert_config.AddLine( + 'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key' +) +ts.Disk.records_config.update({ + 'proxy.config.http.server_ports': '{0} {1}:ssl'.format(ts.Variables.port, ts.Variables.ssl_port), + 'proxy.config.http.insert_request_via_str': 1, + 'proxy.config.http.insert_response_via_str': 1, + 'proxy.config.http.cache.http': 0, + 'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir), + 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), + 'proxy.config.ssl.client.verify.server': 0, + 'proxy.config.diags.debug.enabled': 1, + 'proxy.config.diags.debug.tags': 'http2', +}) + +# ---- +# Test Cases +# ---- + +# Known broken tests are left out (http2/6.4. and http2/6.9.) +h2spec_targets = "http2/1 http2/2 http2/3 http2/4 http2/5 http2/6.1 http2/6.2 http2/6.3 http2/6.5 http2/6.6 http2/6.7 http2/6.8 http2/7 http2/8 hpack" + +test_run = Test.AddTestRun() +test_run.Processes.Default.Command = 'h2spec {0} -t -k -p {1}'.format(h2spec_targets, ts.Variables.ssl_port) +test_run.Processes.Default.ReturnCode = 0 +test_run.Processes.Default.StartBefore(httpbin, ready=When.PortOpen(httpbin.Variables.Port)) +test_run.Processes.Default.StartBefore(Test.Processes.ts, ready=When.PortOpen(ts.Variables.ssl_port)) +test_run.Processes.Default.Streams.stdout = "gold/h2spec_stdout.gold" +test_run.StillRunningAfter = httpbin + +# Over riding the built in ERROR check since we expect some error cases +ts.Disk.diags_log.Content = Testers.ContainsExpression("ERROR: HTTP/2", "h2spec tests should have error log") From 712e1b9a340380e0aab45b6e7033557e37d85b13 Mon Sep 17 00:00:00 2001 From: Susan Hinrichs Date: Fri, 25 Oct 2019 20:28:33 +0000 Subject: [PATCH 147/718] Allow txn handler to be set from ssn on same hook (cherry picked from commit be2102e4b2874e69823bee5e14f7f644f65cb501) --- proxy/InkAPIInternal.h | 5 +- src/traffic_server/InkAPI.cc | 9 +- .../pluginTest/test_hooks/hook_add.gold | 7 + .../pluginTest/test_hooks/hook_add.test.py | 57 +++++++ tests/tools/plugins/hook_add_plugin.cc | 140 ++++++++++++++++++ 5 files changed, 214 insertions(+), 4 deletions(-) create mode 100644 tests/gold_tests/pluginTest/test_hooks/hook_add.gold create mode 100644 tests/gold_tests/pluginTest/test_hooks/hook_add.test.py create mode 100644 tests/tools/plugins/hook_add_plugin.cc diff --git a/proxy/InkAPIInternal.h b/proxy/InkAPIInternal.h index 25fab38b991..4a90f3518ef 100644 --- a/proxy/InkAPIInternal.h +++ b/proxy/InkAPIInternal.h @@ -357,8 +357,9 @@ class HttpHookState protected: /// Track the state of one scope of hooks. struct Scope { - APIHook const *_c; ///< Current hook (candidate for invocation). - APIHook const *_p; ///< Previous hook (already invoked). + APIHook const *_c; ///< Current hook (candidate for invocation). + APIHook const *_p; ///< Previous hook (already invoked). + APIHooks const *_hooks; ///< Reference to the real hook list /// Initialize the scope. void init(HttpAPIHooks const *scope, TSHttpHookID id); diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc index fb910e0b66d..b508e0306aa 100644 --- a/src/traffic_server/InkAPI.cc +++ b/src/traffic_server/InkAPI.cc @@ -1426,16 +1426,21 @@ HttpHookState::is_enabled() void HttpHookState::Scope::init(HttpAPIHooks const *feature_hooks, TSHttpHookID id) { - APIHooks const *hooks = (*feature_hooks)[id]; + _hooks = (*feature_hooks)[id]; _p = nullptr; - _c = hooks->head(); + _c = _hooks->head(); } APIHook const * HttpHookState::Scope::candidate() { /// Simply returns _c hook for now. Later will do priority checking here + + // Check to see if a hook has been added since this was initialized empty + if (nullptr == _c && nullptr == _p && _hooks != nullptr) { + _c = _hooks->head(); + } return _c; } diff --git a/tests/gold_tests/pluginTest/test_hooks/hook_add.gold b/tests/gold_tests/pluginTest/test_hooks/hook_add.gold new file mode 100644 index 00000000000..9141bacdee6 --- /dev/null +++ b/tests/gold_tests/pluginTest/test_hooks/hook_add.gold @@ -0,0 +1,7 @@ +`` DIAG: (test) -- globalHandler :: TS_EVENT_HTTP_SSN_START +`` DIAG: (test) New session, cont is `` +`` DIAG: (test) -- sessionHandler :: TS_EVENT_HTTP_PRE_REMAP +`` DIAG: (test) -- transactionHandler :: TS_EVENT_HTTP_PRE_REMAP +`` DIAG: (test) -- transactionHandler :: TS_EVENT_HTTP_TXN_CLOSE +`` DIAG: (test) -- sessionHandler :: TS_EVENT_HTTP_SSN_CLOSE +`` diff --git a/tests/gold_tests/pluginTest/test_hooks/hook_add.test.py b/tests/gold_tests/pluginTest/test_hooks/hook_add.test.py new file mode 100644 index 00000000000..3ea96bca230 --- /dev/null +++ b/tests/gold_tests/pluginTest/test_hooks/hook_add.test.py @@ -0,0 +1,57 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +Test.Summary = ''' +Test adding hooks +''' + +Test.ContinueOnFail = True + +server = Test.MakeOriginServer("server") + +request_header = { + "headers": "GET /argh HTTP/1.1\r\nHost: doesnotmatter\r\n\r\n", "timestamp": "1469733493.993", "body": "" } +response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", "timestamp": "1469733493.993", "body": "" } +server.addResponse("sessionlog.json", request_header, response_header) + +ts = Test.MakeATSProcess("ts", select_ports=True, enable_tls=False) + +ts.Disk.records_config.update({ + 'proxy.config.diags.debug.tags': 'test', + 'proxy.config.diags.debug.enabled': 1, + 'proxy.config.http.cache.http': 0, + 'proxy.config.url_remap.remap_required': 0, +}) + +Test.PreparePlugin(Test.Variables.AtsTestToolsDir + '/plugins/hook_add_plugin.cc', ts) + +ts.Disk.remap_config.AddLine( + "map http://one http://127.0.0.1:{0}".format(server.Variables.Port) +) + +tr = Test.AddTestRun() +# Probe server port to check if ready. +tr.Processes.Default.StartBefore(server, ready=When.PortOpen(server.Variables.Port)) +# Probe TS cleartext port to check if ready (probing TLS port causes spurious VCONN hook triggers). +tr.Processes.Default.StartBefore(Test.Processes.ts, ready=When.PortOpen(ts.Variables.port)) +# +tr.Processes.Default.Command = ( + 'curl --verbose --ipv4 --header "Host: one" http://localhost:{0}/argh'.format(ts.Variables.port) +) +tr.Processes.Default.ReturnCode = 0 + +# Look at the debug output from the plugin +ts.Streams.All = "hook_add.gold" diff --git a/tests/tools/plugins/hook_add_plugin.cc b/tests/tools/plugins/hook_add_plugin.cc new file mode 100644 index 00000000000..f8fcfe47af2 --- /dev/null +++ b/tests/tools/plugins/hook_add_plugin.cc @@ -0,0 +1,140 @@ +/** @file + + Test adding continuation from same hook point + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ +#include + +#define PLUGIN_TAG "test" + +int +transactionHandler(TSCont continuation, TSEvent event, void *d) +{ + if (!(event == TS_EVENT_HTTP_PRE_REMAP || event == TS_EVENT_HTTP_TXN_CLOSE)) { + TSError("[" PLUGIN_TAG "] unexpected event on transactionHandler: %i\n", event); + return 0; + } + + TSHttpTxn transaction = static_cast(d); + + switch (event) { + case TS_EVENT_HTTP_PRE_REMAP: { + TSDebug(PLUGIN_TAG, " -- transactionHandler :: TS_EVENT_HTTP_PRE_REMAP"); + } break; + + case TS_EVENT_HTTP_TXN_CLOSE: + TSDebug(PLUGIN_TAG, " -- transactionHandler :: TS_EVENT_HTTP_TXN_CLOSE"); + TSContDataSet(continuation, nullptr); + TSContDestroy(continuation); + break; + + default: + break; + } + + TSHttpTxnReenable(transaction, TS_EVENT_HTTP_CONTINUE); + + return 0; +} + +int +sessionHandler(TSCont continuation, TSEvent event, void *d) +{ + TSHttpTxn txnp = (TSHttpTxn)d; + TSCont txn_contp; + + switch (event) { + case TS_EVENT_HTTP_PRE_REMAP: { + TSDebug(PLUGIN_TAG, " -- sessionHandler :: TS_EVENT_HTTP_PRE_REMAP"); + txn_contp = TSContCreate(transactionHandler, nullptr); + + /* Registers locally to hook PRE_REMAP_HOOK and TXN_CLOSE */ + TSHttpTxnHookAdd(txnp, TS_HTTP_PRE_REMAP_HOOK, txn_contp); + TSHttpTxnHookAdd(txnp, TS_HTTP_TXN_CLOSE_HOOK, txn_contp); + } break; + + case TS_EVENT_HTTP_SSN_CLOSE: { + TSDebug(PLUGIN_TAG, " -- sessionHandler :: TS_EVENT_HTTP_SSN_CLOSE"); + const TSHttpSsn session = static_cast(d); + + TSHttpSsnReenable(session, TS_EVENT_HTTP_CONTINUE); + TSContDestroy(continuation); + return 0; + } break; + + default: + TSAssert(!"Unexpected event"); + break; + } + + TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); + return 0; +} + +int +globalHandler(TSCont continuation, TSEvent event, void *data) +{ + TSHttpSsn session = static_cast(data); + + switch (event) { + case TS_EVENT_HTTP_SSN_START: { + TSDebug(PLUGIN_TAG, " -- globalHandler :: TS_EVENT_HTTP_SSN_START"); + TSCont cont = TSContCreate(sessionHandler, TSMutexCreate()); + + TSHttpSsnHookAdd(session, TS_HTTP_PRE_REMAP_HOOK, cont); + TSHttpSsnHookAdd(session, TS_HTTP_SSN_CLOSE_HOOK, cont); + + TSDebug(PLUGIN_TAG, "New session, cont is %p", cont); + } break; + + default: + return 0; + } + + TSHttpSsnReenable(session, TS_EVENT_HTTP_CONTINUE); + + return 0; +} + +void +TSPluginInit(int argc, const char **argv) +{ + TSPluginRegistrationInfo info; + + info.plugin_name = const_cast(PLUGIN_TAG); + info.support_email = const_cast("shinrich@verizonmedia.com"); + info.vendor_name = const_cast("Verizon Media"); + + TSReturnCode ret; +#if (TS_VERSION_MAJOR >= 7) + ret = TSPluginRegister(&info); +#else + ret = TSPluginRegister(TS_SDK_VERSION_3_0, &info); +#endif + + if (TS_ERROR == ret) { + TSError("[" PLUGIN_TAG "] plugin registration failed\n"); + return; + } + + TSCont continuation = TSContCreate(globalHandler, nullptr); + + TSHttpHookAdd(TS_HTTP_SSN_START_HOOK, continuation); +} From 6088d512aee0e259ba0dba1c8d33484972cdcc80 Mon Sep 17 00:00:00 2001 From: Randall Meyer Date: Mon, 4 Nov 2019 18:39:49 -0800 Subject: [PATCH 148/718] tests: Cleans up imported but unused imports (cherry picked from commit 6b08479ecfe4f677a0b22b8942f6bbaadd687d92) --- tests/gold_tests/autest-site/curl_header.test.ext | 1 - tests/gold_tests/autest-site/init.cli.ext | 5 ++--- tests/gold_tests/autest-site/microDNS.test.ext | 4 +--- tests/gold_tests/autest-site/microserver.test.ext | 11 +++++------ tests/gold_tests/autest-site/traffic_replay.test.ext | 4 ++-- tests/gold_tests/autest-site/trafficserver.test.ext | 5 +---- tests/gold_tests/basic/config.test.py | 1 - tests/gold_tests/basic/copy_config.test.py | 2 +- tests/gold_tests/basic/deny0.test.py | 1 - tests/gold_tests/cache/cache-control.test.py | 3 +-- .../chunked_encoding/chunked_encoding.test.py | 1 - tests/gold_tests/continuations/double.test.py | 4 ++-- tests/gold_tests/continuations/double_h2.test.py | 4 ++-- tests/gold_tests/continuations/openclose.test.py | 4 ++-- tests/gold_tests/h2/h2active_timeout.py | 1 - tests/gold_tests/h2/h2bigclient.py | 1 - tests/gold_tests/h2/h2chunked.py | 1 - tests/gold_tests/h2/h2client.py | 1 - tests/gold_tests/h2/h2disable.test.py | 1 - .../gold_tests/h2/h2disable_no_accept_threads.test.py | 1 - tests/gold_tests/h2/h2enable.test.py | 1 - .../gold_tests/h2/h2enable_no_accept_threads.test.py | 1 - tests/gold_tests/h2/h2spec.test.py | 5 ----- tests/gold_tests/h2/http2_priority.test.py | 6 +----- tests/gold_tests/headers/cache_and_req_body.test.py | 1 - tests/gold_tests/headers/cachedIMSRange.test.py | 2 -- tests/gold_tests/headers/forwarded-observer.py | 1 - tests/gold_tests/headers/forwarded.test.py | 1 - tests/gold_tests/headers/hsts.test.py | 1 - tests/gold_tests/headers/http408.test.py | 1 - tests/gold_tests/headers/normalize_ae.test.py | 1 - tests/gold_tests/headers/syntax.test.py | 1 - tests/gold_tests/headers/via.test.py | 1 - tests/gold_tests/logging/all_headers.test.py | 1 - tests/gold_tests/logging/ccid_ctid.test.py | 1 - tests/gold_tests/logging/log-filter.test.py | 9 ++++----- .../client_context_dump/client_context_dump.test.py | 2 -- tests/gold_tests/pluginTest/compress/compress.test.py | 2 -- .../pluginTest/header_rewrite/header_rewrite.test.py | 1 - .../pluginTest/multiplexer/multiplexer.test.py | 1 - tests/gold_tests/pluginTest/slice/slice.test.py | 2 -- tests/gold_tests/pluginTest/slice/slice_error.test.py | 2 -- .../gold_tests/pluginTest/test_hooks/hook_add.test.py | 2 +- tests/gold_tests/pluginTest/url_sig/url_sig.test.py | 3 +-- tests/gold_tests/redirect/redirect_post.test.py | 1 - tests/gold_tests/remap/remap_http.test.py | 1 - tests/gold_tests/remap/remap_https.test.py | 1 - tests/gold_tests/runroot/runroot_error.test.py | 2 -- tests/gold_tests/runroot/runroot_init.test.py | 2 -- tests/gold_tests/runroot/runroot_manager.test.py | 2 -- tests/gold_tests/runroot/runroot_remove.test.py | 2 -- tests/gold_tests/runroot/runroot_use.test.py | 2 -- tests/gold_tests/runroot/runroot_verify.test.py | 2 -- tests/gold_tests/thread_config/thread_100_0.test.py | 2 -- tests/gold_tests/thread_config/thread_100_1.test.py | 2 -- tests/gold_tests/thread_config/thread_100_10.test.py | 2 -- tests/gold_tests/thread_config/thread_1_0.test.py | 2 -- tests/gold_tests/thread_config/thread_1_1.test.py | 2 -- tests/gold_tests/thread_config/thread_1_10.test.py | 2 -- tests/gold_tests/thread_config/thread_2_0.test.py | 2 -- tests/gold_tests/thread_config/thread_2_1.test.py | 2 -- tests/gold_tests/thread_config/thread_2_10.test.py | 2 -- tests/gold_tests/thread_config/thread_32_0.test.py | 2 -- tests/gold_tests/thread_config/thread_32_1.test.py | 2 -- tests/gold_tests/thread_config/thread_32_10.test.py | 2 -- tests/gold_tests/tls/tls.test.py | 1 - tests/gold_tests/tls/tls_check_cert_selection.test.py | 1 - tests/gold_tests/tls/tls_client_cert.test.py | 2 -- tests/gold_tests/tls/tls_client_cert2.test.py | 3 --- tests/gold_tests/tls/tls_client_cert_override.test.py | 3 --- tests/gold_tests/tls/tls_client_verify.test.py | 3 --- tests/gold_tests/tls/tls_client_verify2.test.py | 3 --- tests/gold_tests/tls/tls_client_versions.test.py | 1 - tests/gold_tests/tls/tls_hooks_client_verify.test.py | 1 - tests/gold_tests/tls/tls_hooks_verify.test.py | 1 - tests/gold_tests/tls/tls_keepalive.test.py | 1 - tests/gold_tests/tls/tls_session_cache.test.py | 1 - tests/gold_tests/tls/tls_ticket.test.py | 1 - tests/gold_tests/tls/tls_tunnel.test.py | 1 - tests/gold_tests/tls/tls_tunnel_forward.test.py | 1 - tests/gold_tests/tls/tls_verify.test.py | 1 - tests/gold_tests/tls/tls_verify2.test.py | 1 - tests/gold_tests/tls/tls_verify3.test.py | 1 - tests/gold_tests/tls/tls_verify_base.test.py | 1 - tests/gold_tests/tls/tls_verify_ca_override.test.py | 1 - tests/gold_tests/tls/tls_verify_not_pristine.test.py | 1 - tests/gold_tests/tls/tls_verify_override.test.py | 1 - tests/gold_tests/tls/tls_verify_override_base.test.py | 1 - tests/gold_tests/tls_hooks/tls_hooks10.test.py | 1 - tests/gold_tests/tls_hooks/tls_hooks12.test.py | 1 - tests/gold_tests/tls_hooks/tls_hooks13.test.py | 1 - tests/gold_tests/tls_hooks/tls_hooks14.test.py | 1 - tests/gold_tests/tls_hooks/tls_hooks15.test.py | 1 - 93 files changed, 26 insertions(+), 155 deletions(-) diff --git a/tests/gold_tests/autest-site/curl_header.test.ext b/tests/gold_tests/autest-site/curl_header.test.ext index b592b45be96..e0ba9925f17 100644 --- a/tests/gold_tests/autest-site/curl_header.test.ext +++ b/tests/gold_tests/autest-site/curl_header.test.ext @@ -140,7 +140,6 @@ class CurlHeader(Tester): p_flag = 0 reason += '\n--------------------------------------------------------------------------------\n' - if p_flag == 1: self.Result = tester.ResultType.Passed self.Reason = "Curl headers and values match" diff --git a/tests/gold_tests/autest-site/init.cli.ext b/tests/gold_tests/autest-site/init.cli.ext index 6d7e89b13e2..defaf8a0365 100644 --- a/tests/gold_tests/autest-site/init.cli.ext +++ b/tests/gold_tests/autest-site/init.cli.ext @@ -16,14 +16,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os - import sys + if sys.version_info < (3, 5, 0): host.WriteError( "You need python 3.5 or later to run these tests\n", show_stack=False) -autest_version ="1.7.2" +autest_version = "1.7.2" if AuTestVersion() < autest_version: host.WriteError( "Tests need AuTest version {ver} or better\n Please update AuTest:\n pip install --upgrade autest\n".format(ver=autest_version), show_stack=False) diff --git a/tests/gold_tests/autest-site/microDNS.test.ext b/tests/gold_tests/autest-site/microDNS.test.ext index fdeffe00088..83fbc7bd2c2 100644 --- a/tests/gold_tests/autest-site/microDNS.test.ext +++ b/tests/gold_tests/autest-site/microDNS.test.ext @@ -18,14 +18,12 @@ import json import os -import sys import trlib.ipconstants as IPConstants from ports import get_port -# AddRecord registers a list of ip address against hostname - +# AddRecord registers a list of ip address against hostname def AddRecord(hostname, list_ip_addr): record = dict() diff --git a/tests/gold_tests/autest-site/microserver.test.ext b/tests/gold_tests/autest-site/microserver.test.ext index bef027f09c7..bde0005c430 100644 --- a/tests/gold_tests/autest-site/microserver.test.ext +++ b/tests/gold_tests/autest-site/microserver.test.ext @@ -19,8 +19,6 @@ import json import socket import ssl -import time -import sys from autest.api import AddWhenFunction from ports import get_port @@ -57,6 +55,7 @@ def getHeaderFieldVal(request_header, field): val = field_v[0].strip() return val + # addResponse adds customized response with respect to request_header. request_header and response_header are both dictionaries def addResponse(self, filename, request_header, response_header): client_request = Request.fromRequestLine(request_header["headers"], request_header["body"], None if "options" not in request_header else request_header["options"]) @@ -69,9 +68,8 @@ def addResponse(self, filename, request_header, response_header): addTransactionToSession(txn, absFilepath) return -# adds transaction in json format to the specified file - +# adds transaction in json format to the specified file def addTransactionToSession(txn, JFile): jsondata = None if not os.path.exists(os.path.dirname(JFile)): @@ -96,6 +94,7 @@ def addTransactionToSession(txn, JFile): with open(JFile, 'w+') as jf: jf.write(json.dumps(jsondata)) + def addSessionFromFiles(self, session_dir): self.Setup.Copy(session_dir, self.Variables.DataDir) @@ -177,8 +176,8 @@ def MakeOriginServer(obj, name, port=None, s_port=None, ip='INADDR_LOOPBACK', de command += " --cert {0}".format(cert) command += " --s_port {0}".format(s_port) - # this might break if user specifies both both and ssl - if not ssl: # in both or HTTP only mode + # this might break if user specifies both both and ssl + if not ssl: # in both or HTTP only mode if not port: port = get_port(p, "Port") diff --git a/tests/gold_tests/autest-site/traffic_replay.test.ext b/tests/gold_tests/autest-site/traffic_replay.test.ext index 340fae93d48..0779dd5d0d3 100644 --- a/tests/gold_tests/autest-site/traffic_replay.test.ext +++ b/tests/gold_tests/autest-site/traffic_replay.test.ext @@ -16,7 +16,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# default 'mixed' for connection type since it doesn't hurt +# default 'mixed' for connection type since it doesn't hurt def Replay(obj, name, replay_dir, key=None, cert=None, conn_type='mixed', options={}): # ATS setup - one line because we leave records and remap config to user ts = obj.MakeATSProcess("ts", select_ports=False) # select ports can be disabled once we add ssl port selection in extension @@ -61,7 +61,7 @@ def Replay(obj, name, replay_dir, key=None, cert=None, conn_type='mixed', option if not cert: cert = os.path.join(obj.Variables["AtsTestToolsDir"], "microserver", "ssl", "server.crt") - + command = 'traffic-replay --log_dir {0} --type {1} --verify --host {2} --port {3} --s_port {4} '.format(data_dir, conn_type, hostIP, ts.Variables.port, ts.Variables.ssl_port) if key: diff --git a/tests/gold_tests/autest-site/trafficserver.test.ext b/tests/gold_tests/autest-site/trafficserver.test.ext index 0ca41eb12a6..34af4fff0fa 100755 --- a/tests/gold_tests/autest-site/trafficserver.test.ext +++ b/tests/gold_tests/autest-site/trafficserver.test.ext @@ -18,9 +18,7 @@ from __future__ import print_function import os -import socket from ports import get_port -from autest.api import AddWhenFunction def make_id(s): @@ -275,7 +273,7 @@ def MakeATSProcess(obj, name, command='traffic_server', select_ports=True, enabl p.Variables.port = 8080 p.Variables.portv6 = 8080 p.Variables.ssl_port = 4443 - + get_port(p, "manager_port") get_port(p, "admin_port") @@ -304,7 +302,6 @@ def MakeATSProcess(obj, name, command='traffic_server', select_ports=True, enabl else: p.ReturnCode = 0 - return p diff --git a/tests/gold_tests/basic/config.test.py b/tests/gold_tests/basic/config.test.py index 4045b86ce1d..bfe048b1854 100644 --- a/tests/gold_tests/basic/config.test.py +++ b/tests/gold_tests/basic/config.test.py @@ -27,4 +27,3 @@ t.Command = "curl 127.0.0.1:{port}".format(port=ts.Variables.port) t.ReturnCode = 0 t.StillRunningAfter = ts - diff --git a/tests/gold_tests/basic/copy_config.test.py b/tests/gold_tests/basic/copy_config.test.py index 8cfea1bbd7d..612f6531440 100644 --- a/tests/gold_tests/basic/copy_config.test.py +++ b/tests/gold_tests/basic/copy_config.test.py @@ -43,4 +43,4 @@ t.Command = "curl 127.0.0.1:{port}".format(port=ts2.Variables.port) t.ReturnCode = 0 t.StillRunningAfter = ts1 -t.StillRunningAfter += ts2 \ No newline at end of file +t.StillRunningAfter += ts2 diff --git a/tests/gold_tests/basic/deny0.test.py b/tests/gold_tests/basic/deny0.test.py index 8b451632d26..54fbe9973ea 100644 --- a/tests/gold_tests/basic/deny0.test.py +++ b/tests/gold_tests/basic/deny0.test.py @@ -18,7 +18,6 @@ # limitations under the License. import os -import socket Test.Summary = ''' Test that Trafficserver rejects requests for host 0 ''' diff --git a/tests/gold_tests/cache/cache-control.test.py b/tests/gold_tests/cache/cache-control.test.py index d66167e156b..cf3caf63b09 100644 --- a/tests/gold_tests/cache/cache-control.test.py +++ b/tests/gold_tests/cache/cache-control.test.py @@ -17,11 +17,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test cached responses and requests with bodies ''' - + Test.ContinueOnFail = True # Define default ATS diff --git a/tests/gold_tests/chunked_encoding/chunked_encoding.test.py b/tests/gold_tests/chunked_encoding/chunked_encoding.test.py index 8f02a1ee637..7219221cb25 100644 --- a/tests/gold_tests/chunked_encoding/chunked_encoding.test.py +++ b/tests/gold_tests/chunked_encoding/chunked_encoding.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test a basic remap of a http connection ''' diff --git a/tests/gold_tests/continuations/double.test.py b/tests/gold_tests/continuations/double.test.py index 400ac9fe060..ab830cde26f 100644 --- a/tests/gold_tests/continuations/double.test.py +++ b/tests/gold_tests/continuations/double.test.py @@ -98,7 +98,7 @@ # Parking this as a ready tester on a meaningless process # To stall the test runs that check for the stats until the # stats have propagated and are ready to read. -def make_done_stat_ready(tsenv): +def make_done_stat_ready(tsenv): def done_stat_ready(process, hasRunFor, **kw): retval = subprocess.run("traffic_ctl metric get continuations_verify.test.done > done 2> /dev/null", shell=True, env=tsenv) if retval.returncode == 0: @@ -106,7 +106,7 @@ def done_stat_ready(process, hasRunFor, **kw): return retval.returncode == 0 return done_stat_ready - + # number of sessions/transactions opened and closed are equal tr = Test.AddTestRun("Check Ssn") server2.StartupTimeout = 60 diff --git a/tests/gold_tests/continuations/double_h2.test.py b/tests/gold_tests/continuations/double_h2.test.py index 9ab8789d543..8cf025add2e 100644 --- a/tests/gold_tests/continuations/double_h2.test.py +++ b/tests/gold_tests/continuations/double_h2.test.py @@ -109,7 +109,7 @@ # Parking this as a ready tester on a meaningless process # To stall the test runs that check for the stats until the # stats have propagated and are ready to read. -def make_done_stat_ready(tsenv): +def make_done_stat_ready(tsenv): def done_stat_ready(process, hasRunFor, **kw): retval = subprocess.run("traffic_ctl metric get continuations_verify.test.done > done 2> /dev/null", shell=True, env=tsenv) if retval.returncode == 0: @@ -117,7 +117,7 @@ def done_stat_ready(process, hasRunFor, **kw): return retval.returncode == 0 return done_stat_ready - + # number of sessions/transactions opened and closed are equal tr = Test.AddTestRun("Check Ssn") server2.StartupTimeout = 60 diff --git a/tests/gold_tests/continuations/openclose.test.py b/tests/gold_tests/continuations/openclose.test.py index 11fd15c24b7..b27b018304d 100644 --- a/tests/gold_tests/continuations/openclose.test.py +++ b/tests/gold_tests/continuations/openclose.test.py @@ -82,7 +82,7 @@ # Parking this as a ready tester on a meaningless process # To stall the test runs that check for the stats until the # stats have propagated and are ready to read. -def make_done_stat_ready(tsenv): +def make_done_stat_ready(tsenv): def done_stat_ready(process, hasRunFor, **kw): retval = subprocess.run("traffic_ctl metric get ssntxnorder_verify.test.done > done 2> /dev/null", shell=True, env=tsenv) if retval.returncode == 0: @@ -90,7 +90,7 @@ def done_stat_ready(process, hasRunFor, **kw): return retval.returncode == 0 return done_stat_ready - + # number of sessions/transactions opened and closed are equal tr = Test.AddTestRun("Check Ssn order errors") server2.StartupTimeout = 60 diff --git a/tests/gold_tests/h2/h2active_timeout.py b/tests/gold_tests/h2/h2active_timeout.py index b71608c3479..0b7d5ac35a7 100644 --- a/tests/gold_tests/h2/h2active_timeout.py +++ b/tests/gold_tests/h2/h2active_timeout.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import json from hyper import HTTPConnection import hyper import argparse diff --git a/tests/gold_tests/h2/h2bigclient.py b/tests/gold_tests/h2/h2bigclient.py index 8bc6a066648..2e1d86d3311 100644 --- a/tests/gold_tests/h2/h2bigclient.py +++ b/tests/gold_tests/h2/h2bigclient.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import json from hyper import HTTPConnection import hyper import argparse diff --git a/tests/gold_tests/h2/h2chunked.py b/tests/gold_tests/h2/h2chunked.py index e92945036f7..97938ec2992 100644 --- a/tests/gold_tests/h2/h2chunked.py +++ b/tests/gold_tests/h2/h2chunked.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import json from hyper import HTTPConnection import hyper import argparse diff --git a/tests/gold_tests/h2/h2client.py b/tests/gold_tests/h2/h2client.py index 5042965ce26..d8f3ce0a101 100644 --- a/tests/gold_tests/h2/h2client.py +++ b/tests/gold_tests/h2/h2client.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import json from hyper import HTTPConnection import hyper import argparse diff --git a/tests/gold_tests/h2/h2disable.test.py b/tests/gold_tests/h2/h2disable.test.py index f9347b669bd..0b0ac8b5ab0 100644 --- a/tests/gold_tests/h2/h2disable.test.py +++ b/tests/gold_tests/h2/h2disable.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test disabling H2 on a per domain basis ''' diff --git a/tests/gold_tests/h2/h2disable_no_accept_threads.test.py b/tests/gold_tests/h2/h2disable_no_accept_threads.test.py index bbf5dd012bc..8d805af0d96 100644 --- a/tests/gold_tests/h2/h2disable_no_accept_threads.test.py +++ b/tests/gold_tests/h2/h2disable_no_accept_threads.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test disabling H2 on a per domain basis ''' diff --git a/tests/gold_tests/h2/h2enable.test.py b/tests/gold_tests/h2/h2enable.test.py index 0357e93168b..a44c27105f2 100644 --- a/tests/gold_tests/h2/h2enable.test.py +++ b/tests/gold_tests/h2/h2enable.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test enabling H2 on a per domain basis ''' diff --git a/tests/gold_tests/h2/h2enable_no_accept_threads.test.py b/tests/gold_tests/h2/h2enable_no_accept_threads.test.py index 0149e54fad5..7f82c4785ec 100644 --- a/tests/gold_tests/h2/h2enable_no_accept_threads.test.py +++ b/tests/gold_tests/h2/h2enable_no_accept_threads.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test enabling H2 on a per domain basis ''' diff --git a/tests/gold_tests/h2/h2spec.test.py b/tests/gold_tests/h2/h2spec.test.py index a188e80a251..7bb7fd45270 100644 --- a/tests/gold_tests/h2/h2spec.test.py +++ b/tests/gold_tests/h2/h2spec.test.py @@ -17,11 +17,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os - -# ---- -# Setup Test -# ---- Test.Summary = ''' Test HTTP/2 with httpspec ''' diff --git a/tests/gold_tests/h2/http2_priority.test.py b/tests/gold_tests/h2/http2_priority.test.py index e0911da8795..6b30c88e55a 100644 --- a/tests/gold_tests/h2/http2_priority.test.py +++ b/tests/gold_tests/h2/http2_priority.test.py @@ -16,14 +16,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os - -# ---- -# Setup Test -# ---- Test.Summary = ''' Test a basic remap of a http connection with Stream Priority Feature ''' + # need Curl Test.SkipUnless( Condition.HasCurlFeature('http2'), diff --git a/tests/gold_tests/headers/cache_and_req_body.test.py b/tests/gold_tests/headers/cache_and_req_body.test.py index a45dc945c6b..f42ec57e42e 100644 --- a/tests/gold_tests/headers/cache_and_req_body.test.py +++ b/tests/gold_tests/headers/cache_and_req_body.test.py @@ -17,7 +17,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test cached responses and requests with bodies using CurlHeader tester ''' diff --git a/tests/gold_tests/headers/cachedIMSRange.test.py b/tests/gold_tests/headers/cachedIMSRange.test.py index 496c945b572..2738aaa3716 100644 --- a/tests/gold_tests/headers/cachedIMSRange.test.py +++ b/tests/gold_tests/headers/cachedIMSRange.test.py @@ -17,8 +17,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os -import time Test.Summary = ''' Test revalidating cached objects ''' diff --git a/tests/gold_tests/headers/forwarded-observer.py b/tests/gold_tests/headers/forwarded-observer.py index f817650775a..7789c4296d1 100644 --- a/tests/gold_tests/headers/forwarded-observer.py +++ b/tests/gold_tests/headers/forwarded-observer.py @@ -18,7 +18,6 @@ # limitations under the License. import re -import subprocess log = open('forwarded.log', 'w') diff --git a/tests/gold_tests/headers/forwarded.test.py b/tests/gold_tests/headers/forwarded.test.py index eb95e382b4b..5fed2056d67 100644 --- a/tests/gold_tests/headers/forwarded.test.py +++ b/tests/gold_tests/headers/forwarded.test.py @@ -18,7 +18,6 @@ # limitations under the License. import os -import subprocess Test.Summary = ''' Test FORWARDED header. diff --git a/tests/gold_tests/headers/hsts.test.py b/tests/gold_tests/headers/hsts.test.py index 434ff4b1d42..67ed89ce656 100644 --- a/tests/gold_tests/headers/hsts.test.py +++ b/tests/gold_tests/headers/hsts.test.py @@ -17,7 +17,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' heck hsts header is set correctly ''' diff --git a/tests/gold_tests/headers/http408.test.py b/tests/gold_tests/headers/http408.test.py index 8e2c37b4303..a56ffa96c0c 100644 --- a/tests/gold_tests/headers/http408.test.py +++ b/tests/gold_tests/headers/http408.test.py @@ -18,7 +18,6 @@ # limitations under the License. import os -import subprocess Test.Summary = ''' Check 408 response header for protocol stack data. diff --git a/tests/gold_tests/headers/normalize_ae.test.py b/tests/gold_tests/headers/normalize_ae.test.py index 23ef42f357a..d9779a2d49a 100644 --- a/tests/gold_tests/headers/normalize_ae.test.py +++ b/tests/gold_tests/headers/normalize_ae.test.py @@ -18,7 +18,6 @@ # limitations under the License. import os -import subprocess Test.Summary = ''' Test normalizations of the Accept-Encoding header field. diff --git a/tests/gold_tests/headers/syntax.test.py b/tests/gold_tests/headers/syntax.test.py index dbaacb984e7..d6a6929deb2 100644 --- a/tests/gold_tests/headers/syntax.test.py +++ b/tests/gold_tests/headers/syntax.test.py @@ -17,7 +17,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test whitespace between field name and colon in the header ''' diff --git a/tests/gold_tests/headers/via.test.py b/tests/gold_tests/headers/via.test.py index 1244b489647..5e275d193df 100644 --- a/tests/gold_tests/headers/via.test.py +++ b/tests/gold_tests/headers/via.test.py @@ -19,7 +19,6 @@ # limitations under the License. import os -import subprocess Test.Summary = ''' Check VIA header for protocol stack data. diff --git a/tests/gold_tests/logging/all_headers.test.py b/tests/gold_tests/logging/all_headers.test.py index 6ae73d7d6ba..b973fa6386a 100644 --- a/tests/gold_tests/logging/all_headers.test.py +++ b/tests/gold_tests/logging/all_headers.test.py @@ -17,7 +17,6 @@ # limitations under the License. import os -import subprocess Test.Summary = ''' Test new "all headers" log fields diff --git a/tests/gold_tests/logging/ccid_ctid.test.py b/tests/gold_tests/logging/ccid_ctid.test.py index 26dc65984b5..34f9d758c51 100644 --- a/tests/gold_tests/logging/ccid_ctid.test.py +++ b/tests/gold_tests/logging/ccid_ctid.test.py @@ -17,7 +17,6 @@ # limitations under the License. import os -import subprocess Test.Summary = ''' Test new ccid and ctid log fields diff --git a/tests/gold_tests/logging/log-filter.test.py b/tests/gold_tests/logging/log-filter.test.py index 784fee27ec8..97dd8eec765 100644 --- a/tests/gold_tests/logging/log-filter.test.py +++ b/tests/gold_tests/logging/log-filter.test.py @@ -18,7 +18,7 @@ import os -Test.Summary = ''' +Test.Summary = ''' Test log filter. ''' # Only on Linux (why??) @@ -31,7 +31,7 @@ # Microserver server = Test.MakeOriginServer("server") -request_header = {'timestamp': 100, "headers": "GET /test-1 HTTP/1.1\r\nHost: test-1\r\n\r\n", "body": ""} +request_header = {'timestamp': 100, "headers": "GET /test-1 HTTP/1.1\r\nHost: test-1\r\n\r\n", "body": ""} response_header = {'timestamp': 100, "headers": "HTTP/1.1 200 OK\r\nTest: 1\r\nContent-Type: application/json\r\nConnection: close\r\nContent-Type: application/json\r\n\r\n", "body": "Test 1"} server.addResponse("sessionlog.json", request_header, response_header) @@ -62,7 +62,7 @@ ) ts.Disk.logging_yaml.AddLines( - ''' + ''' logging: filters: - name: queryparamescaper_cquuc @@ -74,7 +74,7 @@ logs: - filename: filter-test format: custom - filters: + filters: - queryparamescaper_cquuc '''.split("\n") ) @@ -121,4 +121,3 @@ tr.DelayStart = 10 tr.Processes.Default.Command = 'echo "Delay for log flush"' tr.Processes.Default.ReturnCode = 0 - diff --git a/tests/gold_tests/pluginTest/client_context_dump/client_context_dump.test.py b/tests/gold_tests/pluginTest/client_context_dump/client_context_dump.test.py index 9fea371d725..1afd71ee866 100644 --- a/tests/gold_tests/pluginTest/client_context_dump/client_context_dump.test.py +++ b/tests/gold_tests/pluginTest/client_context_dump/client_context_dump.test.py @@ -17,8 +17,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os -import subprocess Test.Summary = ''' Test client_context_dump plugin ''' diff --git a/tests/gold_tests/pluginTest/compress/compress.test.py b/tests/gold_tests/pluginTest/compress/compress.test.py index 65d289010c7..626b74b667c 100644 --- a/tests/gold_tests/pluginTest/compress/compress.test.py +++ b/tests/gold_tests/pluginTest/compress/compress.test.py @@ -16,8 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os -import subprocess Test.Summary = ''' Test compress plugin ''' diff --git a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite.test.py b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite.test.py index 2341cf07764..6e850eb8573 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite.test.py +++ b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test a basic remap of a http connection ''' diff --git a/tests/gold_tests/pluginTest/multiplexer/multiplexer.test.py b/tests/gold_tests/pluginTest/multiplexer/multiplexer.test.py index 028ef769023..69af2bf6e28 100644 --- a/tests/gold_tests/pluginTest/multiplexer/multiplexer.test.py +++ b/tests/gold_tests/pluginTest/multiplexer/multiplexer.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test experimental/multiplexer. ''' diff --git a/tests/gold_tests/pluginTest/slice/slice.test.py b/tests/gold_tests/pluginTest/slice/slice.test.py index cec66ed4ff6..eafaef8b755 100644 --- a/tests/gold_tests/pluginTest/slice/slice.test.py +++ b/tests/gold_tests/pluginTest/slice/slice.test.py @@ -16,8 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os -import time Test.Summary = ''' Basic slice plugin test ''' diff --git a/tests/gold_tests/pluginTest/slice/slice_error.test.py b/tests/gold_tests/pluginTest/slice/slice_error.test.py index 1c42b308609..830ecaad945 100644 --- a/tests/gold_tests/pluginTest/slice/slice_error.test.py +++ b/tests/gold_tests/pluginTest/slice/slice_error.test.py @@ -16,8 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os -import time Test.Summary = ''' Slice plugin error.log test ''' diff --git a/tests/gold_tests/pluginTest/test_hooks/hook_add.test.py b/tests/gold_tests/pluginTest/test_hooks/hook_add.test.py index 3ea96bca230..c5caaceed1e 100644 --- a/tests/gold_tests/pluginTest/test_hooks/hook_add.test.py +++ b/tests/gold_tests/pluginTest/test_hooks/hook_add.test.py @@ -32,7 +32,7 @@ ts.Disk.records_config.update({ 'proxy.config.diags.debug.tags': 'test', 'proxy.config.diags.debug.enabled': 1, - 'proxy.config.http.cache.http': 0, + 'proxy.config.http.cache.http': 0, 'proxy.config.url_remap.remap_required': 0, }) diff --git a/tests/gold_tests/pluginTest/url_sig/url_sig.test.py b/tests/gold_tests/pluginTest/url_sig/url_sig.test.py index 3c96e898035..588f6d6b60a 100644 --- a/tests/gold_tests/pluginTest/url_sig/url_sig.test.py +++ b/tests/gold_tests/pluginTest/url_sig/url_sig.test.py @@ -18,8 +18,7 @@ import hashlib import hmac -import os -import subprocess + Test.Summary = ''' Test url_sig plugin ''' diff --git a/tests/gold_tests/redirect/redirect_post.test.py b/tests/gold_tests/redirect/redirect_post.test.py index 23b7212bff1..ce5f5bfbf85 100644 --- a/tests/gold_tests/redirect/redirect_post.test.py +++ b/tests/gold_tests/redirect/redirect_post.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test basic post redirection ''' diff --git a/tests/gold_tests/remap/remap_http.test.py b/tests/gold_tests/remap/remap_http.test.py index 1417feaf57c..b51ae76d24d 100644 --- a/tests/gold_tests/remap/remap_http.test.py +++ b/tests/gold_tests/remap/remap_http.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test a basic remap of a http connection ''' diff --git a/tests/gold_tests/remap/remap_https.test.py b/tests/gold_tests/remap/remap_https.test.py index f94768d9508..a47dcbf71b2 100644 --- a/tests/gold_tests/remap/remap_https.test.py +++ b/tests/gold_tests/remap/remap_https.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test a basic remap of a http connection ''' diff --git a/tests/gold_tests/runroot/runroot_error.test.py b/tests/gold_tests/runroot/runroot_error.test.py index 1fc7ca75d0a..dc0a26b2cf1 100644 --- a/tests/gold_tests/runroot/runroot_error.test.py +++ b/tests/gold_tests/runroot/runroot_error.test.py @@ -17,8 +17,6 @@ # limitations under the License. import os -import sys -import time Test.Summary = ''' Test for expected error and failure of runroot from traffic_layout. diff --git a/tests/gold_tests/runroot/runroot_init.test.py b/tests/gold_tests/runroot/runroot_init.test.py index 5e8e371a644..9c68b8e7844 100644 --- a/tests/gold_tests/runroot/runroot_init.test.py +++ b/tests/gold_tests/runroot/runroot_init.test.py @@ -17,8 +17,6 @@ # limitations under the License. import os -import sys -import time Test.Summary = ''' Test for init of runroot from traffic_layout. diff --git a/tests/gold_tests/runroot/runroot_manager.test.py b/tests/gold_tests/runroot/runroot_manager.test.py index 0954cdbcfc2..c9ce5f833cf 100644 --- a/tests/gold_tests/runroot/runroot_manager.test.py +++ b/tests/gold_tests/runroot/runroot_manager.test.py @@ -17,8 +17,6 @@ # limitations under the License. import os -import sys -import time Test.Summary = ''' Test for using of runroot of traffic_manager. diff --git a/tests/gold_tests/runroot/runroot_remove.test.py b/tests/gold_tests/runroot/runroot_remove.test.py index c2349eb95c6..987836c8f58 100644 --- a/tests/gold_tests/runroot/runroot_remove.test.py +++ b/tests/gold_tests/runroot/runroot_remove.test.py @@ -17,8 +17,6 @@ # limitations under the License. import os -import sys -import time Test.Summary = ''' Test for remove of runroot from traffic_layout. diff --git a/tests/gold_tests/runroot/runroot_use.test.py b/tests/gold_tests/runroot/runroot_use.test.py index 0ef2aefb210..9e9cbd5c593 100644 --- a/tests/gold_tests/runroot/runroot_use.test.py +++ b/tests/gold_tests/runroot/runroot_use.test.py @@ -17,8 +17,6 @@ # limitations under the License. import os -import sys -import time Test.Summary = ''' Test for using of runroot from traffic_layout. diff --git a/tests/gold_tests/runroot/runroot_verify.test.py b/tests/gold_tests/runroot/runroot_verify.test.py index 961c9706c66..8c316b757b4 100644 --- a/tests/gold_tests/runroot/runroot_verify.test.py +++ b/tests/gold_tests/runroot/runroot_verify.test.py @@ -17,8 +17,6 @@ # limitations under the License. import os -import sys -import time Test.Summary = ''' Test for verify of runroot from traffic_layout. diff --git a/tests/gold_tests/thread_config/thread_100_0.test.py b/tests/gold_tests/thread_config/thread_100_0.test.py index b93f614200d..955dc7e8cb9 100644 --- a/tests/gold_tests/thread_config/thread_100_0.test.py +++ b/tests/gold_tests/thread_config/thread_100_0.test.py @@ -16,8 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import sys - Test.Summary = 'Test that Trafficserver starts with different thread configurations.' Test.ContinueOnFail = True diff --git a/tests/gold_tests/thread_config/thread_100_1.test.py b/tests/gold_tests/thread_config/thread_100_1.test.py index 0230b2ae1cb..d2f962d30e3 100644 --- a/tests/gold_tests/thread_config/thread_100_1.test.py +++ b/tests/gold_tests/thread_config/thread_100_1.test.py @@ -16,8 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import sys - Test.Summary = 'Test that Trafficserver starts with different thread configurations.' Test.ContinueOnFail = True diff --git a/tests/gold_tests/thread_config/thread_100_10.test.py b/tests/gold_tests/thread_config/thread_100_10.test.py index f324b60161b..2ec2204a37e 100644 --- a/tests/gold_tests/thread_config/thread_100_10.test.py +++ b/tests/gold_tests/thread_config/thread_100_10.test.py @@ -16,8 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import sys - Test.Summary = 'Test that Trafficserver starts with different thread configurations.' Test.ContinueOnFail = True diff --git a/tests/gold_tests/thread_config/thread_1_0.test.py b/tests/gold_tests/thread_config/thread_1_0.test.py index a51ca5ef473..e394ab0c7c8 100644 --- a/tests/gold_tests/thread_config/thread_1_0.test.py +++ b/tests/gold_tests/thread_config/thread_1_0.test.py @@ -16,8 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import sys - Test.Summary = 'Test that Trafficserver starts with different thread configurations.' Test.ContinueOnFail = True diff --git a/tests/gold_tests/thread_config/thread_1_1.test.py b/tests/gold_tests/thread_config/thread_1_1.test.py index b0b0db4899f..a3f7608adab 100644 --- a/tests/gold_tests/thread_config/thread_1_1.test.py +++ b/tests/gold_tests/thread_config/thread_1_1.test.py @@ -16,8 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import sys - Test.Summary = 'Test that Trafficserver starts with different thread configurations.' Test.ContinueOnFail = True diff --git a/tests/gold_tests/thread_config/thread_1_10.test.py b/tests/gold_tests/thread_config/thread_1_10.test.py index 1eae1a2a012..07252f3d0d3 100644 --- a/tests/gold_tests/thread_config/thread_1_10.test.py +++ b/tests/gold_tests/thread_config/thread_1_10.test.py @@ -16,8 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import sys - Test.Summary = 'Test that Trafficserver starts with different thread configurations.' Test.ContinueOnFail = True diff --git a/tests/gold_tests/thread_config/thread_2_0.test.py b/tests/gold_tests/thread_config/thread_2_0.test.py index 286b376cc4d..9935e6c7ad2 100644 --- a/tests/gold_tests/thread_config/thread_2_0.test.py +++ b/tests/gold_tests/thread_config/thread_2_0.test.py @@ -16,8 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import sys - Test.Summary = 'Test that Trafficserver starts with different thread configurations.' Test.ContinueOnFail = True diff --git a/tests/gold_tests/thread_config/thread_2_1.test.py b/tests/gold_tests/thread_config/thread_2_1.test.py index 0c3fd6f7cac..641e7e83ae3 100644 --- a/tests/gold_tests/thread_config/thread_2_1.test.py +++ b/tests/gold_tests/thread_config/thread_2_1.test.py @@ -16,8 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import sys - Test.Summary = 'Test that Trafficserver starts with different thread configurations.' Test.ContinueOnFail = True diff --git a/tests/gold_tests/thread_config/thread_2_10.test.py b/tests/gold_tests/thread_config/thread_2_10.test.py index aa674e3a46e..fd725cec2b7 100644 --- a/tests/gold_tests/thread_config/thread_2_10.test.py +++ b/tests/gold_tests/thread_config/thread_2_10.test.py @@ -16,8 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import sys - Test.Summary = 'Test that Trafficserver starts with different thread configurations.' Test.ContinueOnFail = True diff --git a/tests/gold_tests/thread_config/thread_32_0.test.py b/tests/gold_tests/thread_config/thread_32_0.test.py index 7b2c70ca902..2e62129b990 100644 --- a/tests/gold_tests/thread_config/thread_32_0.test.py +++ b/tests/gold_tests/thread_config/thread_32_0.test.py @@ -16,8 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import sys - Test.Summary = 'Test that Trafficserver starts with different thread configurations.' Test.ContinueOnFail = True diff --git a/tests/gold_tests/thread_config/thread_32_1.test.py b/tests/gold_tests/thread_config/thread_32_1.test.py index d6583609d4f..b44fd8e9562 100644 --- a/tests/gold_tests/thread_config/thread_32_1.test.py +++ b/tests/gold_tests/thread_config/thread_32_1.test.py @@ -16,8 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import sys - Test.Summary = 'Test that Trafficserver starts with different thread configurations.' Test.ContinueOnFail = True diff --git a/tests/gold_tests/thread_config/thread_32_10.test.py b/tests/gold_tests/thread_config/thread_32_10.test.py index a794738171f..be20467ca46 100644 --- a/tests/gold_tests/thread_config/thread_32_10.test.py +++ b/tests/gold_tests/thread_config/thread_32_10.test.py @@ -16,8 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import sys - Test.Summary = 'Test that Trafficserver starts with different thread configurations.' Test.ContinueOnFail = True diff --git a/tests/gold_tests/tls/tls.test.py b/tests/gold_tests/tls/tls.test.py index ad3fcb798d8..d204445e6cc 100644 --- a/tests/gold_tests/tls/tls.test.py +++ b/tests/gold_tests/tls/tls.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test tls ''' diff --git a/tests/gold_tests/tls/tls_check_cert_selection.test.py b/tests/gold_tests/tls/tls_check_cert_selection.test.py index 67e76f4d8a5..aa027ac85aa 100644 --- a/tests/gold_tests/tls/tls_check_cert_selection.test.py +++ b/tests/gold_tests/tls/tls_check_cert_selection.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test ATS offering different certificates based on SNI ''' diff --git a/tests/gold_tests/tls/tls_client_cert.test.py b/tests/gold_tests/tls/tls_client_cert.test.py index d21bb6b4c83..6732c45aab6 100644 --- a/tests/gold_tests/tls/tls_client_cert.test.py +++ b/tests/gold_tests/tls/tls_client_cert.test.py @@ -17,9 +17,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os import subprocess -import re Test.Summary = ''' Test different combinations of TLS handshake hooks to ensure they are applied consistently. diff --git a/tests/gold_tests/tls/tls_client_cert2.test.py b/tests/gold_tests/tls/tls_client_cert2.test.py index 5e252ed2bf3..95f2fcede36 100644 --- a/tests/gold_tests/tls/tls_client_cert2.test.py +++ b/tests/gold_tests/tls/tls_client_cert2.test.py @@ -17,9 +17,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os -import re - Test.Summary = ''' Test client certs to origin selected via wildcard names in sni ''' diff --git a/tests/gold_tests/tls/tls_client_cert_override.test.py b/tests/gold_tests/tls/tls_client_cert_override.test.py index 5bb89590eab..5df4f5ad9c4 100644 --- a/tests/gold_tests/tls/tls_client_cert_override.test.py +++ b/tests/gold_tests/tls/tls_client_cert_override.test.py @@ -17,9 +17,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os -import re - Test.Summary = ''' Test conf_remp to specify different client certificates to offer to the origin ''' diff --git a/tests/gold_tests/tls/tls_client_verify.test.py b/tests/gold_tests/tls/tls_client_verify.test.py index aba36829e74..e7480a70cc2 100644 --- a/tests/gold_tests/tls/tls_client_verify.test.py +++ b/tests/gold_tests/tls/tls_client_verify.test.py @@ -17,9 +17,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os -import re - Test.Summary = ''' Test various options for requiring certificate from client for mutual authentication TLS ''' diff --git a/tests/gold_tests/tls/tls_client_verify2.test.py b/tests/gold_tests/tls/tls_client_verify2.test.py index 78dff33768b..0083e9f3e20 100644 --- a/tests/gold_tests/tls/tls_client_verify2.test.py +++ b/tests/gold_tests/tls/tls_client_verify2.test.py @@ -17,9 +17,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os -import re - Test.Summary = ''' Test various options for requiring certificate from client for mutual authentication TLS ''' diff --git a/tests/gold_tests/tls/tls_client_versions.test.py b/tests/gold_tests/tls/tls_client_versions.test.py index 76cb28decd3..f351b981e24 100644 --- a/tests/gold_tests/tls/tls_client_versions.test.py +++ b/tests/gold_tests/tls/tls_client_versions.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test TLS protocol offering based on SNI ''' diff --git a/tests/gold_tests/tls/tls_hooks_client_verify.test.py b/tests/gold_tests/tls/tls_hooks_client_verify.test.py index 36092d4c0f9..becb6a9ace6 100644 --- a/tests/gold_tests/tls/tls_hooks_client_verify.test.py +++ b/tests/gold_tests/tls/tls_hooks_client_verify.test.py @@ -18,7 +18,6 @@ # limitations under the License. import os -import re Test.Summary = ''' Test different combinations of TLS handshake hooks to ensure they are applied consistently. diff --git a/tests/gold_tests/tls/tls_hooks_verify.test.py b/tests/gold_tests/tls/tls_hooks_verify.test.py index dae7e9b9e75..33e1f15814b 100644 --- a/tests/gold_tests/tls/tls_hooks_verify.test.py +++ b/tests/gold_tests/tls/tls_hooks_verify.test.py @@ -18,7 +18,6 @@ # limitations under the License. import os -import re Test.Summary = ''' Test different combinations of TLS handshake hooks to ensure they are applied consistently. diff --git a/tests/gold_tests/tls/tls_keepalive.test.py b/tests/gold_tests/tls/tls_keepalive.test.py index 72c32f008ce..11d39aa1f32 100644 --- a/tests/gold_tests/tls/tls_keepalive.test.py +++ b/tests/gold_tests/tls/tls_keepalive.test.py @@ -18,7 +18,6 @@ # limitations under the License. import os -import re Test.Summary = ''' Verify that the client-side keep alive is honored for TLS and different versions of HTTP diff --git a/tests/gold_tests/tls/tls_session_cache.test.py b/tests/gold_tests/tls/tls_session_cache.test.py index 08d9fd2d9e3..0d4d0a98e9b 100644 --- a/tests/gold_tests/tls/tls_session_cache.test.py +++ b/tests/gold_tests/tls/tls_session_cache.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os import re Test.Summary = ''' Test tls session cache diff --git a/tests/gold_tests/tls/tls_ticket.test.py b/tests/gold_tests/tls/tls_ticket.test.py index d26e14d810c..857217c862e 100644 --- a/tests/gold_tests/tls/tls_ticket.test.py +++ b/tests/gold_tests/tls/tls_ticket.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os import re Test.Summary = ''' Test tls tickets diff --git a/tests/gold_tests/tls/tls_tunnel.test.py b/tests/gold_tests/tls/tls_tunnel.test.py index c168a20bad8..0a7196fb451 100644 --- a/tests/gold_tests/tls/tls_tunnel.test.py +++ b/tests/gold_tests/tls/tls_tunnel.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os import subprocess Test.Summary = ''' Test tunneling based on SNI diff --git a/tests/gold_tests/tls/tls_tunnel_forward.test.py b/tests/gold_tests/tls/tls_tunnel_forward.test.py index 105babfef54..8288f238328 100644 --- a/tests/gold_tests/tls/tls_tunnel_forward.test.py +++ b/tests/gold_tests/tls/tls_tunnel_forward.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test tunneling and forwarding based on SNI ''' diff --git a/tests/gold_tests/tls/tls_verify.test.py b/tests/gold_tests/tls/tls_verify.test.py index b8ac58f52a1..289d1ac8cbf 100644 --- a/tests/gold_tests/tls/tls_verify.test.py +++ b/tests/gold_tests/tls/tls_verify.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test tls server certificate verification options ''' diff --git a/tests/gold_tests/tls/tls_verify2.test.py b/tests/gold_tests/tls/tls_verify2.test.py index e141fd44d06..368f0c8e5b1 100644 --- a/tests/gold_tests/tls/tls_verify2.test.py +++ b/tests/gold_tests/tls/tls_verify2.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test tls server certificate verification options ''' diff --git a/tests/gold_tests/tls/tls_verify3.test.py b/tests/gold_tests/tls/tls_verify3.test.py index 25d806917b3..eb54c295328 100644 --- a/tests/gold_tests/tls/tls_verify3.test.py +++ b/tests/gold_tests/tls/tls_verify3.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test tls server certificate verification options ''' diff --git a/tests/gold_tests/tls/tls_verify_base.test.py b/tests/gold_tests/tls/tls_verify_base.test.py index 7195f868f82..51d41c1fb08 100644 --- a/tests/gold_tests/tls/tls_verify_base.test.py +++ b/tests/gold_tests/tls/tls_verify_base.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test tls server certificate verification options ''' diff --git a/tests/gold_tests/tls/tls_verify_ca_override.test.py b/tests/gold_tests/tls/tls_verify_ca_override.test.py index 6197de7645c..b7208fa94ce 100644 --- a/tests/gold_tests/tls/tls_verify_ca_override.test.py +++ b/tests/gold_tests/tls/tls_verify_ca_override.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test tls server certificate verification options. Exercise conf_remap for ca bundle ''' diff --git a/tests/gold_tests/tls/tls_verify_not_pristine.test.py b/tests/gold_tests/tls/tls_verify_not_pristine.test.py index b04cd68a877..60183589f54 100644 --- a/tests/gold_tests/tls/tls_verify_not_pristine.test.py +++ b/tests/gold_tests/tls/tls_verify_not_pristine.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test tls server certificate verification without a pristine host header ''' diff --git a/tests/gold_tests/tls/tls_verify_override.test.py b/tests/gold_tests/tls/tls_verify_override.test.py index 0e6a7c51cea..68104f69c22 100644 --- a/tests/gold_tests/tls/tls_verify_override.test.py +++ b/tests/gold_tests/tls/tls_verify_override.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test tls server certificate verification options. Exercise conf_remap ''' diff --git a/tests/gold_tests/tls/tls_verify_override_base.test.py b/tests/gold_tests/tls/tls_verify_override_base.test.py index b84a7cbc8d8..ccaaab4b66d 100644 --- a/tests/gold_tests/tls/tls_verify_override_base.test.py +++ b/tests/gold_tests/tls/tls_verify_override_base.test.py @@ -16,7 +16,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os Test.Summary = ''' Test tls server certificate verification options. Exercise conf_remap ''' diff --git a/tests/gold_tests/tls_hooks/tls_hooks10.test.py b/tests/gold_tests/tls_hooks/tls_hooks10.test.py index b16fa6c4fe2..111280c4e0b 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks10.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks10.test.py @@ -18,7 +18,6 @@ # limitations under the License. import os -import re Test.Summary = ''' Test different combinations of TLS handshake hooks to ensure they are applied consistently. diff --git a/tests/gold_tests/tls_hooks/tls_hooks12.test.py b/tests/gold_tests/tls_hooks/tls_hooks12.test.py index dbc76367d5b..4cb12d2e74a 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks12.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks12.test.py @@ -18,7 +18,6 @@ # limitations under the License. import os -import re Test.Summary = ''' Test different combinations of TLS handshake hooks to ensure they are applied consistently. diff --git a/tests/gold_tests/tls_hooks/tls_hooks13.test.py b/tests/gold_tests/tls_hooks/tls_hooks13.test.py index 256d8e93d9b..aebe3fd46a6 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks13.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks13.test.py @@ -18,7 +18,6 @@ # limitations under the License. import os -import re Test.Summary = ''' Test different combinations of TLS handshake hooks to ensure they are applied consistently. diff --git a/tests/gold_tests/tls_hooks/tls_hooks14.test.py b/tests/gold_tests/tls_hooks/tls_hooks14.test.py index 1c78e8b2d34..180f2a1645b 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks14.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks14.test.py @@ -18,7 +18,6 @@ # limitations under the License. import os -import re Test.Summary = ''' Test different combinations of TLS handshake hooks to ensure they are applied consistently. diff --git a/tests/gold_tests/tls_hooks/tls_hooks15.test.py b/tests/gold_tests/tls_hooks/tls_hooks15.test.py index c844dfd52fe..6220f4cff00 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks15.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks15.test.py @@ -18,7 +18,6 @@ # limitations under the License. import os -import re Test.Summary = ''' Test different combinations of TLS handshake hooks to ensure they are applied consistently. From aec8f5d496acc8b40756d962ebec3570a161ca50 Mon Sep 17 00:00:00 2001 From: scw00 Date: Mon, 29 Apr 2019 06:29:18 +0000 Subject: [PATCH 149/718] Remove Cache v23 support (cherry picked from commit d000f0cc0cb30d40755da408962a81c2745fbdf5) --- iocore/cache/Cache.cc | 230 +------------------------------------ iocore/cache/I_CacheDefs.h | 10 +- iocore/cache/P_CacheBC.h | 137 ---------------------- 3 files changed, 11 insertions(+), 366 deletions(-) delete mode 100644 iocore/cache/P_CacheBC.h diff --git a/iocore/cache/Cache.cc b/iocore/cache/Cache.cc index 83b33b54de7..35291d21975 100644 --- a/iocore/cache/Cache.cc +++ b/iocore/cache/Cache.cc @@ -34,7 +34,6 @@ #include "HttpSM.h" #include "HttpCacheSM.h" #include "InkAPIInternal.h" -#include "P_CacheBC.h" #include "tscore/hugepages.h" @@ -2152,92 +2151,6 @@ unmarshal_helper(Doc *doc, Ptr &buf, int &okay) } } -/** Upgrade a marshalled fragment buffer to the current version. - - @internal I looked at doing this in place (rather than a copy & modify) but - - The in place logic would be even worse than this mess - - It wouldn't save you that much, since you end up doing inserts early in the buffer. - Without extreme care in the logic it could end up doing more copying than - the simpler copy & modify. - - @internal This logic presumes the existence of some slack at the end of the buffer, which - is usually the case (because lots of rounding is done). If there isn't enough slack then - this fails and we have a cache miss. The assumption that this is sufficiently rare that - code simplicity takes precedence should be checked at some point. - */ -static bool -upgrade_doc_version(Ptr &buf) -{ - // Type definition is close enough to use for initial checking. - cache_bc::Doc_v23 *doc = reinterpret_cast(buf->data()); - bool zret = true; - - if (DOC_MAGIC == doc->magic) { - if (0 == doc->hlen) { - Debug("cache_bc", "Doc %p without header, no upgrade needed.", doc); - } else if (CACHE_FRAG_TYPE_HTTP_V23 == doc->doc_type) { - cache_bc::HTTPCacheAlt_v21 *alt = reinterpret_cast(doc->hdr()); - if (alt && alt->is_unmarshalled_format()) { - Ptr d_buf(ioDataAllocator.alloc()); - Doc *d_doc; - char *src; - char *dst; - char *hdr_limit = doc->data(); - HTTPInfo::FragOffset *frags = - reinterpret_cast(static_cast(buf->data()) + sizeof(cache_bc::Doc_v23)); - int frag_count = doc->_flen / sizeof(HTTPInfo::FragOffset); - size_t n = 0; - size_t content_size = doc->data_len(); - - Debug("cache_bc", "Doc %p is 3.2", doc); - - // Use the same buffer size, fail if no fit. - d_buf->alloc(buf->_size_index, buf->_mem_type); // Duplicate. - d_doc = reinterpret_cast(d_buf->data()); - n = d_buf->block_size(); - - src = buf->data(); - dst = d_buf->data(); - memcpy(dst, src, sizeof(Doc)); - src += sizeof(Doc) + doc->_flen; - dst += sizeof(Doc); - n -= sizeof(Doc); - - // We copy the fragment table iff there is a fragment table and there is only one alternate. - if (frag_count > 0 && cache_bc::HTTPInfo_v21::marshalled_length(src) > doc->hlen) { - frag_count = 0; // inhibit fragment table insertion. - } - - while (zret && src < hdr_limit) { - zret = cache_bc::HTTPInfo_v21::copy_and_upgrade_unmarshalled_to_v23(dst, src, n, frag_count, frags); - } - if (zret && content_size <= n) { - memcpy(dst, src, content_size); // content - // Must update new Doc::len and Doc::hlen - // dst points at the first byte of the content, or one past the last byte of the alt header. - d_doc->len = (dst - reinterpret_cast(d_doc)) + content_size; - d_doc->hlen = (dst - reinterpret_cast(d_doc)) - sizeof(Doc); - buf = d_buf; // replace original buffer with new buffer. - } else { - zret = false; - } - } - Doc *n_doc = reinterpret_cast(buf->data()); // access as current version. - // For now the base header size is the same. If that changes we'll need to handle the v22/23 case here - // as with the v21 and shift the content down to accommodate the bigger header. - ink_assert(sizeof(*n_doc) == sizeof(*doc)); - - n_doc->doc_type = CACHE_FRAG_TYPE_HTTP; // We converted so adjust doc_type. - // Set these to zero for debugging - they'll be updated to the current values if/when this is - // put in the aggregation buffer. - n_doc->v_major = 0; - n_doc->v_minor = 0; - n_doc->unused = 0; // force to zero to make future use easier. - } - } - return zret; -} - // [amc] I think this is where all disk reads from cache funnel through here. int CacheVC::handleReadDone(int event, Event *e) @@ -2270,37 +2183,12 @@ CacheVC::handleReadDone(int event, Event *e) ink_assert(vol->mutex->nthread_holding < 1000); ink_assert(doc->magic == DOC_MAGIC); - /* We've read the raw data from disk, time to deserialize it. We have to account for a variety of formats that - may be present. - - As of cache version 24 we changed the @a doc_type to indicate a format change in the header which includes - version data inside the header. Prior to that we must use heuristics to deduce the actual format. For this reason - we send that header type off for special processing. Otherwise we can use the in object version to determine - the format. - - All of this processing must produce a serialized header that is compliant with the current version. This includes - updating the doc_type. - */ - - if (doc->doc_type == CACHE_FRAG_TYPE_HTTP_V23) { - if (upgrade_doc_version(buf)) { - doc = reinterpret_cast(buf->data()); // buf may be a new copy - } else { - Debug("cache_bc", "Upgrade of fragment failed - disk %s - doc id = %" PRIx64 ":%" PRIx64 "", vol->hash_text.get(), - read_key->slice64(0), read_key->slice64(1)); - doc->magic = DOC_CORRUPT; - // Should really trash the directory entry for this, as it's never going to work in the future. - // Or does that happen later anyway? - goto Ldone; - } - } else if (doc->doc_type == CACHE_FRAG_TYPE_HTTP) { // handle any version updates based on the object version - if (ts::VersionNumber(doc->v_major, doc->v_minor) > CACHE_DB_VERSION) { - // future version, count as corrupted - doc->magic = DOC_CORRUPT; - Debug("cache_bc", "Object is future version %d:%d - disk %s - doc id = %" PRIx64 ":%" PRIx64 "", doc->v_major, doc->v_minor, - vol->hash_text.get(), read_key->slice64(0), read_key->slice64(1)); - goto Ldone; - } + if (ts::VersionNumber(doc->v_major, doc->v_minor) > CACHE_DB_VERSION) { + // future version, count as corrupted + doc->magic = DOC_CORRUPT; + Debug("cache_bc", "Object is future version %d:%d - disk %s - doc id = %" PRIx64 ":%" PRIx64 "", doc->v_major, doc->v_minor, + vol->hash_text.get(), read_key->slice64(0), read_key->slice64(1)); + goto Ldone; } #ifdef VERIFY_JTEST_DATA @@ -3300,109 +3188,3 @@ CacheProcessor::find_by_path(const char *path, int len) return nullptr; } - -// ---------------------------- - -namespace cache_bc -{ -static size_t const HTTP_ALT_MARSHAL_SIZE = HdrHeapMarshalBlocks{ts::round_up(sizeof(HTTPCacheAlt))}; // current size. -size_t -HTTPInfo_v21::marshalled_length(void *data) -{ - size_t zret = HdrHeapMarshalBlocks{ts::round_up(sizeof(HTTPCacheAlt_v21))}; - HTTPCacheAlt_v21 *alt = static_cast(data); - HdrHeap *hdr; - - hdr = reinterpret_cast(reinterpret_cast(alt) + reinterpret_cast(alt->m_request_hdr.m_heap)); - zret += HdrHeapMarshalBlocks{ts::round_up(hdr->unmarshal_size())}; - hdr = reinterpret_cast(reinterpret_cast(alt) + reinterpret_cast(alt->m_response_hdr.m_heap)); - zret += HdrHeapMarshalBlocks{ts::round_up(hdr->unmarshal_size())}; - return zret; -} - -// Copy an unmarshalled instance from @a src to @a dst. -// @a src is presumed to be Cache version 21 and the result -// is Cache version 23. @a length is the buffer available in @a dst. -// @return @c false if something went wrong (e.g., data overrun). -bool -HTTPInfo_v21::copy_and_upgrade_unmarshalled_to_v23(char *&dst, char *&src, size_t &length, int n_frags, FragOffset *frag_offsets) -{ - // Offsets of the data after the new stuff. - static const size_t OLD_OFFSET = offsetof(HTTPCacheAlt_v21, m_ext_buffer); - static const size_t NEW_OFFSET = offsetof(HTTPCacheAlt_v23, m_ext_buffer); - - HTTPCacheAlt_v21 *s_alt = reinterpret_cast(src); - HTTPCacheAlt_v23 *d_alt = reinterpret_cast(dst); - HdrHeap_v23 *s_hdr; - HdrHeap_v23 *d_hdr; - size_t hdr_size; - - if (length < HTTP_ALT_MARSHAL_SIZE) { - return false; // Absolutely no hope in this case. - } - - memcpy(dst, src, OLD_OFFSET); // initially same data - // Now data that's now after extra - memcpy(static_cast(dst) + NEW_OFFSET, static_cast(src) + OLD_OFFSET, sizeof(HTTPCacheAlt_v21) - OLD_OFFSET); - dst += HTTP_ALT_MARSHAL_SIZE; // move past fixed data. - length -= HTTP_ALT_MARSHAL_SIZE; - - // Extra data is fragment table - set that if we have it. - if (n_frags) { - static size_t const IFT_SIZE = HTTPCacheAlt_v23::N_INTEGRAL_FRAG_OFFSETS * sizeof(FragOffset); - size_t ift_actual = std::min(n_frags, HTTPCacheAlt_v23::N_INTEGRAL_FRAG_OFFSETS) * sizeof(FragOffset); - - if (length < (HTTP_ALT_MARSHAL_SIZE + n_frags * sizeof(FragOffset) - IFT_SIZE)) { - return false; // can't place fragment table. - } - - d_alt->m_frag_offset_count = n_frags; - d_alt->m_frag_offsets = reinterpret_cast(dst - reinterpret_cast(d_alt)); - - memcpy(d_alt->m_integral_frag_offsets, frag_offsets, ift_actual); - n_frags -= HTTPCacheAlt_v23::N_INTEGRAL_FRAG_OFFSETS; - if (n_frags > 0) { - size_t k = sizeof(FragOffset) * n_frags; - memcpy(dst, frag_offsets + IFT_SIZE, k); - dst += k; - length -= k; - } else if (n_frags < 0) { - memset(dst + ift_actual, 0, IFT_SIZE - ift_actual); - } - } else { - d_alt->m_frag_offset_count = 0; - d_alt->m_frag_offsets = nullptr; - ink_zero(d_alt->m_integral_frag_offsets); - } - - // Copy over the headers, tweaking the swizzled pointers. - s_hdr = - reinterpret_cast(reinterpret_cast(s_alt) + reinterpret_cast(s_alt->m_request_hdr.m_heap)); - d_hdr = reinterpret_cast(dst); - hdr_size = HdrHeapMarshalBlocks{ts::round_up(s_hdr->unmarshal_size())}; - if (hdr_size > length) { - return false; - } - memcpy(static_cast(d_hdr), s_hdr, hdr_size); - d_alt->m_request_hdr.m_heap = reinterpret_cast(reinterpret_cast(d_hdr) - reinterpret_cast(d_alt)); - dst += hdr_size; - length -= hdr_size; - - s_hdr = - reinterpret_cast(reinterpret_cast(s_alt) + reinterpret_cast(s_alt->m_response_hdr.m_heap)); - d_hdr = reinterpret_cast(dst); - hdr_size = HdrHeapMarshalBlocks{ts::round_up(s_hdr->unmarshal_size())}; - if (hdr_size > length) { - return false; - } - memcpy(static_cast(d_hdr), s_hdr, hdr_size); - d_alt->m_response_hdr.m_heap = reinterpret_cast(reinterpret_cast(d_hdr) - reinterpret_cast(d_alt)); - dst += hdr_size; - length -= hdr_size; - - src = reinterpret_cast(s_hdr) + hdr_size; - - return true; -} - -} // namespace cache_bc diff --git a/iocore/cache/I_CacheDefs.h b/iocore/cache/I_CacheDefs.h index cdd39bb2199..b8dfd5c3bd6 100644 --- a/iocore/cache/I_CacheDefs.h +++ b/iocore/cache/I_CacheDefs.h @@ -113,11 +113,11 @@ enum CacheDataType { }; enum CacheFragType { - CACHE_FRAG_TYPE_NONE, - CACHE_FRAG_TYPE_HTTP_V23, ///< DB version 23 or prior. - CACHE_FRAG_TYPE_RTSP, ///< Should be removed once Cache Toolkit is implemented. - CACHE_FRAG_TYPE_HTTP, - NUM_CACHE_FRAG_TYPES + CACHE_FRAG_TYPE_NONE = 0, + CACHE_FRAG_TYPE_UNUSED_1 = 1, //. Because of the history we need to occupy a space + CACHE_FRAG_TYPE_RTSP = 2, ///< Should be removed once Cache Toolkit is implemented. + CACHE_FRAG_TYPE_HTTP = 3, + NUM_CACHE_FRAG_TYPES = 4 }; typedef CryptoHash CacheKey; diff --git a/iocore/cache/P_CacheBC.h b/iocore/cache/P_CacheBC.h deleted file mode 100644 index ac4d9255826..00000000000 --- a/iocore/cache/P_CacheBC.h +++ /dev/null @@ -1,137 +0,0 @@ -/** @file - - Backwards compatibility support for the cache. - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#pragma once - -namespace cache_bc -{ -/* This looks kind of dumb, but I think it's useful. We import external structure - dependencies in to this namespace so we can at least (1) notice them and - (2) change them if the current structure changes. -*/ - -typedef HTTPHdr HTTPHdr_v21; -typedef HdrHeap HdrHeap_v23; -typedef CryptoHash CryptoHash_v23; -typedef HTTPCacheAlt HTTPCacheAlt_v23; - -/** Cache backwards compatibility structure - the fragment table. - This is copied from @c HTTPCacheAlt in @c HTTP.h. -*/ -struct HTTPCacheFragmentTable { - /// # of fragment offsets in this alternate. - /// @note This is one less than the number of fragments. - int m_frag_offset_count; - /// Type of offset for a fragment. - typedef uint64_t FragOffset; - /// Table of fragment offsets. - /// @note The offsets are forward looking so that frag[0] is the - /// first byte past the end of fragment 0 which is also the first - /// byte of fragment 1. For this reason there is no fragment offset - /// for the last fragment. - FragOffset *m_frag_offsets; - /// # of fragment offsets built in to object. - static int const N_INTEGRAL_FRAG_OFFSETS = 4; - /// Integral fragment offset table. - FragOffset m_integral_frag_offsets[N_INTEGRAL_FRAG_OFFSETS]; -}; - -// From before moving the fragment table to the alternate. -struct HTTPCacheAlt_v21 { - uint32_t m_magic; - - int32_t m_writeable; - int32_t m_unmarshal_len; - - int32_t m_id; - int32_t m_rid; - - int32_t m_object_key[4]; - int32_t m_object_size[2]; - - HTTPHdr_v21 m_request_hdr; - HTTPHdr_v21 m_response_hdr; - - time_t m_request_sent_time; - time_t m_response_received_time; - - RefCountObj *m_ext_buffer; - - // The following methods were added for BC support. - // Checks itself to verify that it is unmarshalled and v21 format. - bool - is_unmarshalled_format() const - { - return CACHE_ALT_MAGIC_MARSHALED == m_magic && reinterpret_cast(m_request_hdr.m_heap) == sizeof(*this); - } -}; - -/// Really just a namespace, doesn't depend on any of the members. -struct HTTPInfo_v21 { - typedef uint64_t FragOffset; - /// Version upgrade methods - /// @a src , @a dst , and @a n are updated upon return. - /// @a n is the space in @a dst remaining. - /// @return @c false if something went wrong. - static bool copy_and_upgrade_unmarshalled_to_v23(char *&dst, char *&src, size_t &length, int n_frags, FragOffset *frag_offsets); - /// The size of the marshalled data of a marshalled alternate header. - static size_t marshalled_length(void *data); -}; - -/// Pre version 24. -struct Doc_v23 { - uint32_t magic; // DOC_MAGIC - uint32_t len; // length of this segment (including hlen, flen & sizeof(Doc), unrounded) - uint64_t total_len; // total length of document - CryptoHash_v23 first_key; ///< first key in object. - CryptoHash_v23 key; ///< Key for this doc. - uint32_t hlen; ///< Length of this header. - uint32_t doc_type : 8; ///< Doc type - indicates the format of this structure and its content. - uint32_t _flen : 24; ///< Fragment table length. - uint32_t sync_serial; - uint32_t write_serial; - uint32_t pinned; // pinned until - uint32_t checksum; - - char *hdr(); - char *data(); - size_t data_len(); -}; - -char * -Doc_v23::data() -{ - return reinterpret_cast(this) + sizeof(Doc_v23) + _flen + hlen; -} -size_t -Doc_v23::data_len() -{ - return len - sizeof(Doc_v23) - hlen; -} -char * -Doc_v23::hdr() -{ - return reinterpret_cast(this) + sizeof(Doc_v23); -} - -} // namespace cache_bc From fc4fab65bd3301cd6c0544c6b9de6eb66b66b970 Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Sat, 9 Nov 2019 19:57:17 -0700 Subject: [PATCH 150/718] Cleans up some of the filenames mess (#6144) * Cleans up some of the filenames mess However, I did not finish eliminating all configurations. I've marked some of them deprecated, the changes to refactor all of this is too big to be safe for a v9.0.0 PR. We will revisit their removals for v10.0.0, but I'll also add a deprecation note for all of these for v9.0.0. * Replaced with constexpr, and namespace. DON'T MERGE THIS!! * Mark a few more configurations deprecated * Remove one superfluous const (cherry picked from commit afa69e7018b5fd0faa89b1efe0938d7deacf64a5) --- doc/admin-guide/files/records.config.en.rst | 5 +++ include/tscore/Filenames.h | 35 ++++++++++++++++----- iocore/cache/Cache.cc | 2 +- iocore/cache/CacheHosting.cc | 11 ++++--- iocore/cache/Store.cc | 12 +++---- iocore/dns/SplitDNS.cc | 11 ++++--- iocore/net/QUICMultiCertConfigLoader.cc | 5 +-- iocore/net/SSLClientUtils.cc | 7 +++-- iocore/net/SSLUtils.cc | 13 ++++---- lib/records/RecCore.cc | 6 ++-- mgmt/LocalManager.cc | 4 +-- mgmt/RecordsConfig.cc | 23 +++++++------- proxy/CacheControl.cc | 15 ++++----- proxy/IPAllow.cc | 5 +-- proxy/ParentSelection.cc | 13 ++++---- proxy/Plugin.cc | 13 ++++---- proxy/ReverseProxy.cc | 21 +++++++------ proxy/http/HttpBodyFactory.cc | 3 +- proxy/http/HttpConfig.cc | 9 +++--- proxy/http/HttpTransact.cc | 5 +-- proxy/http/remap/UrlRewrite.cc | 5 +-- proxy/logging/LogConfig.cc | 3 +- proxy/shared/DiagsConfig.cc | 3 +- src/traffic_layout/info.cc | 16 +++++----- src/traffic_manager/AddConfigFilesHere.cc | 28 ++++++++--------- src/traffic_manager/traffic_manager.cc | 2 +- src/traffic_server/InkAPITest.cc | 9 +++--- src/traffic_server/traffic_server.cc | 22 +++++++------ src/tscore/Filenames.cc | 29 ----------------- src/tscore/Makefile.am | 1 - src/tscore/unit_tests/test_layout.cc | 4 +-- 31 files changed, 176 insertions(+), 164 deletions(-) delete mode 100644 src/tscore/Filenames.cc diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst index 5c482439f4d..c11ce440de9 100644 --- a/doc/admin-guide/files/records.config.en.rst +++ b/doc/admin-guide/files/records.config.en.rst @@ -2901,6 +2901,7 @@ Logging Configuration .. ts:cv:: CONFIG proxy.config.log.config.filename STRING logging.yaml :reloadable: + :deprecated: This configuration value specifies the path to the :file:`logging.yaml` configuration file. If this is a relative @@ -3052,6 +3053,7 @@ URL Remap Rules =============== .. ts:cv:: CONFIG proxy.config.url_remap.filename STRING remap.config + :deprecated: Sets the name of the :file:`remap.config` file. @@ -3182,6 +3184,7 @@ SSL Termination .. ts:cv:: CONFIG proxy.config.ssl.server.multicert.filename STRING ssl_multicert.config + :deprecated: The location of the :file:`ssl_multicert.config` file, relative to the |TS| configuration directory. In the following @@ -3250,6 +3253,7 @@ SSL Termination file is changed with new tickets, use :option:`traffic_ctl config reload` to begin using them. .. ts:cv:: CONFIG proxy.config.ssl.servername.filename STRING sni.yaml + :deprecated: The filename of the :file:`sni.yaml` configuration file. If relative, it is relative to the configuration directory. @@ -3956,6 +3960,7 @@ SOCKS Processor Specifies the SOCKS version (``4``) or (``5``) .. ts:cv:: CONFIG proxy.config.socks.socks_config_file STRING socks.config + :deprecated: The socks.config file allows you to specify ranges of IP addresses that will not be relayed to the SOCKS server. It can also be used diff --git a/include/tscore/Filenames.h b/include/tscore/Filenames.h index 6c880e02d52..6fe0eb8f460 100644 --- a/include/tscore/Filenames.h +++ b/include/tscore/Filenames.h @@ -21,11 +21,30 @@ #pragma once -/////////////////////////////////////////////////////////////////// -// Configuration file names -extern const char *STORAGE_CONF_FILENAME; -extern const char *RECORDS_CONF_FILENAME; - -/////////////////////////////////////////////////////////////////// -// Various other file names -extern const char *RECORDS_STATS_FILE; +namespace ts +{ +namespace filename +{ + constexpr const char *STORAGE = "storage.config"; + constexpr const char *RECORDS = "records.config"; + constexpr const char *VOLUME = "volume.config"; + constexpr const char *PLUGIN = "plugin.config"; + + // These still need to have their corrensponding records.config settings remove + constexpr const char *LOGGING = "logging.yaml"; + constexpr const char *CACHE = "cache.config"; + constexpr const char *IP_ALLOW = "ip_allow.yaml"; + constexpr const char *HOSTING = "hosting.config"; + constexpr const char *SOCKS = "socks.config"; + constexpr const char *PARENT = "parent.config"; + constexpr const char *REMAP = "remap.config"; + constexpr const char *SSL_MULTICERT = "ssl_multicert.config"; + constexpr const char *SPLITDNS = "splitdns.config"; + constexpr const char *SNI = "sni.yaml"; + + /////////////////////////////////////////////////////////////////// + // Various other file names + constexpr const char *RECORDS_STATS = "records.snap"; + +} // namespace filename +} // namespace ts diff --git a/iocore/cache/Cache.cc b/iocore/cache/Cache.cc index 35291d21975..5fbd2fc3def 100644 --- a/iocore/cache/Cache.cc +++ b/iocore/cache/Cache.cc @@ -3141,7 +3141,7 @@ ink_cache_init(ts::ModuleVersion v) Result result = theCacheStore.read_config(); if (result.failed()) { - Fatal("Failed to read cache configuration %s: %s", STORAGE_CONF_FILENAME, result.message()); + Fatal("Failed to read cache configuration %s: %s", ts::filename::STORAGE, result.message()); } } diff --git a/iocore/cache/CacheHosting.cc b/iocore/cache/CacheHosting.cc index 98e75073611..24930c73ef2 100644 --- a/iocore/cache/CacheHosting.cc +++ b/iocore/cache/CacheHosting.cc @@ -26,6 +26,7 @@ #include "tscore/HostLookup.h" #include "tscore/Tokenizer.h" #include "tscore/Regression.h" +#include "tscore/Filenames.h" extern int gndisks; @@ -244,7 +245,7 @@ int fstat_wrapper(int fd, struct stat *s); int CacheHostTable::BuildTableFromString(const char *config_file_path, char *file_buf) { - Note("hosting.config loading ..."); + Note("%s loading ...", ts::filename::HOSTING); // Table build locals Tokenizer bufTok("\n"); @@ -325,7 +326,7 @@ CacheHostTable::BuildTableFromString(const char *config_file_path, char *file_bu if (gen_host_rec.Init(type)) { Warning("Problems encountered while initializing the Generic Volume"); } - Note("hosting.config finished loading"); + Note("%s finished loading", ts::filename::HOSTING); return 0; } @@ -374,7 +375,7 @@ CacheHostTable::BuildTableFromString(const char *config_file_path, char *file_bu current = current->next; ats_free(last); - Note("hosting.config finished loading"); + Note("%s finished loading", ts::filename::HOSTING); } if (!generic_rec_initd) { @@ -596,11 +597,11 @@ ConfigVolumes::read_config_file() config_path = RecConfigReadConfigPath("proxy.config.cache.volume_filename"); ink_release_assert(config_path); - Note("volume.config loading ..."); + Note("%s loading ...", ts::filename::VOLUME); file_buf = readIntoBuffer(config_path, "[CacheVolition]", nullptr); if (file_buf == nullptr) { - Error("volume.config failed to load"); + Error("%s failed to load", ts::filename::VOLUME); Warning("Cannot read the config file: %s", (const char *)config_path); return; } diff --git a/iocore/cache/Store.cc b/iocore/cache/Store.cc index 119206f91ad..22592fdb726 100644 --- a/iocore/cache/Store.cc +++ b/iocore/cache/Store.cc @@ -325,13 +325,13 @@ Store::read_config() Span *sd = nullptr, *cur = nullptr; Span *ns; ats_scoped_fd fd; - ats_scoped_str storage_path(RecConfigReadConfigPath(nullptr, STORAGE_CONF_FILENAME)); + ats_scoped_str storage_path(RecConfigReadConfigPath(nullptr, ts::filename::STORAGE)); - Note("%s loading ...", STORAGE_CONF_FILENAME); + Note("%s loading ...", ts::filename::STORAGE); Debug("cache_init", "Store::read_config, fd = -1, \"%s\"", (const char *)storage_path); fd = ::open(storage_path, O_RDONLY); if (fd < 0) { - Error("%s failed to load", STORAGE_CONF_FILENAME); + Error("%s failed to load", ts::filename::STORAGE); return Result::failure("open %s: %s", (const char *)storage_path, strerror(errno)); } @@ -372,7 +372,7 @@ Store::read_config() const char *end; if ((size = ink_atoi64(e, &end)) <= 0 || *end != '\0') { delete sd; - Error("%s failed to load", STORAGE_CONF_FILENAME); + Error("%s failed to load", ts::filename::STORAGE); return Result::failure("failed to parse size '%s'", e); } } else if (0 == strncasecmp(HASH_BASE_STRING_KEY, e, sizeof(HASH_BASE_STRING_KEY) - 1)) { @@ -390,7 +390,7 @@ Store::read_config() } if (!*e || !ParseRules::is_digit(*e) || 0 >= (volume_num = ink_atoi(e))) { delete sd; - Error("%s failed to load", STORAGE_CONF_FILENAME); + Error("%s failed to load", ts::filename::STORAGE); return Result::failure("failed to parse volume number '%s'", e); } } @@ -442,7 +442,7 @@ Store::read_config() sd = nullptr; // these are all used. sort(); - Note("%s finished loading", STORAGE_CONF_FILENAME); + Note("%s finished loading", ts::filename::STORAGE); return Result::ok(); } diff --git a/iocore/dns/SplitDNS.cc b/iocore/dns/SplitDNS.cc index 827204b7e32..2ad8c245507 100644 --- a/iocore/dns/SplitDNS.cc +++ b/iocore/dns/SplitDNS.cc @@ -30,6 +30,7 @@ #include "tscore/ink_platform.h" #include "tscore/Tokenizer.h" +#include "tscore/Filenames.h" #ifdef SPLIT_DNS #include @@ -130,7 +131,7 @@ SplitDNSConfig::reconfigure() return; } - Note("splitdns.config loading ..."); + Note("%s loading ...", ts::filename::SPLITDNS); SplitDNS *params = new SplitDNS; @@ -138,7 +139,7 @@ SplitDNSConfig::reconfigure() params->m_DNSSrvrTable = new DNS_table("proxy.config.dns.splitdns.filename", modulePrefix, &sdns_dest_tags); if (nullptr == params->m_DNSSrvrTable || (0 == params->m_DNSSrvrTable->getEntryCount())) { - Error("splitdns.config failed to load"); + Error("%s failed to load", ts::filename::SPLITDNS); Warning("No NAMEDs provided! Disabling SplitDNS"); gsplit_dns_enabled = 0; delete params; @@ -159,7 +160,7 @@ SplitDNSConfig::reconfigure() SplitDNSConfig::print(); } - Note("splitdns.config finished loading"); + Note("%s finished loading", ts::filename::SPLITDNS); } /* -------------------------------------------------------------- @@ -476,7 +477,7 @@ SplitDNSRecord::Init(matcher_line *line_info) } if (!ats_is_ip(&m_servers.x_server_ip[0].sa)) { - return Result::failure("%s No server specified in splitdns.config at line %d", modulePrefix, line_num); + return Result::failure("%s No server specified in %s at line %d", modulePrefix, ts::filename::SPLITDNS, line_num); } DNSHandler *dnsH = new DNSHandler; @@ -505,7 +506,7 @@ SplitDNSRecord::Init(matcher_line *line_info) if (line_info->num_el > 0) { const char *tmp = ProcessModifiers(line_info); if (tmp != nullptr) { - return Result::failure("%s %s at line %d in splitdns.config", modulePrefix, tmp, line_num); + return Result::failure("%s %s at line %d in %s", modulePrefix, tmp, line_num, ts::filename::SPLITDNS); } } diff --git a/iocore/net/QUICMultiCertConfigLoader.cc b/iocore/net/QUICMultiCertConfigLoader.cc index 7e37f3427dc..2b1aecf594d 100644 --- a/iocore/net/QUICMultiCertConfigLoader.cc +++ b/iocore/net/QUICMultiCertConfigLoader.cc @@ -29,6 +29,7 @@ #include "QUICConfig.h" #include "QUICConnection.h" #include "QUICTypes.h" +#include "tscore/Filenames.h" // #include "QUICGlobals.h" #define QUICConfDebug(fmt, ...) Debug("quic_conf", fmt, ##__VA_ARGS__) @@ -128,7 +129,7 @@ QUICMultiCertConfigLoader::init_server_ssl_ctx(std::vector &cert_list, c #if TS_USE_TLS_SET_CIPHERSUITES if (params->server_tls13_cipher_suites != nullptr) { if (!SSL_CTX_set_ciphersuites(ctx, params->server_tls13_cipher_suites)) { - Error("invalid tls server cipher suites in records.config"); + Error("invalid tls server cipher suites in %s", ts::filename::RECORDS); goto fail; } } @@ -141,7 +142,7 @@ QUICMultiCertConfigLoader::init_server_ssl_ctx(std::vector &cert_list, c #else if (!SSL_CTX_set1_curves_list(ctx, params->server_groups_list)) { #endif - Error("invalid groups list for server in records.config"); + Error("invalid groups list for server in %s", ts::filename::RECORDS); goto fail; } } diff --git a/iocore/net/SSLClientUtils.cc b/iocore/net/SSLClientUtils.cc index 59f2bce646d..70f36d1740f 100644 --- a/iocore/net/SSLClientUtils.cc +++ b/iocore/net/SSLClientUtils.cc @@ -22,6 +22,7 @@ #include "tscore/ink_config.h" #include "records/I_RecHttp.h" #include "tscore/ink_platform.h" +#include "tscore/Filenames.h" #include "tscore/X509HostnameValidator.h" #include "P_Net.h" @@ -158,7 +159,7 @@ SSLInitClientContext(const SSLConfigParams *params) SSL_CTX_set_options(client_ctx, params->ssl_client_ctx_options); if (params->client_cipherSuite != nullptr) { if (!SSL_CTX_set_cipher_list(client_ctx, params->client_cipherSuite)) { - SSLError("invalid client cipher suite in records.config"); + SSLError("invalid client cipher suite in %s", ts::filename::RECORDS); goto fail; } } @@ -166,7 +167,7 @@ SSLInitClientContext(const SSLConfigParams *params) #if TS_USE_TLS_SET_CIPHERSUITES if (params->client_tls13_cipher_suites != nullptr) { if (!SSL_CTX_set_ciphersuites(client_ctx, params->client_tls13_cipher_suites)) { - SSLError("invalid tls client cipher suites in records.config"); + SSLError("invalid tls client cipher suites in %s", ts::filename::RECORDS); goto fail; } } @@ -179,7 +180,7 @@ SSLInitClientContext(const SSLConfigParams *params) #else if (!SSL_CTX_set1_curves_list(client_ctx, params->client_groups_list)) { #endif - SSLError("invalid groups list for client in records.config"); + SSLError("invalid groups list for client in %s", ts::filename::RECORDS); goto fail; } } diff --git a/iocore/net/SSLUtils.cc b/iocore/net/SSLUtils.cc index 9e8b352abbc..b1994c1b920 100644 --- a/iocore/net/SSLUtils.cc +++ b/iocore/net/SSLUtils.cc @@ -27,6 +27,7 @@ #include "tscore/I_Layout.h" #include "tscore/ink_cap.h" #include "tscore/ink_mutex.h" +#include "tscore/Filenames.h" #include "records/I_RecHttp.h" #include "P_Net.h" @@ -962,7 +963,7 @@ SSLPrivateKeyHandler(SSL_CTX *ctx, const SSLConfigParams *params, const std::str SSLConfigParams::load_ssl_file_cb(completeServerKeyPath); } } else { - SSLError("empty SSL private key path in records.config"); + SSLError("empty SSL private key path in %s", ts::filename::RECORDS); return false; } @@ -1328,7 +1329,7 @@ SSLMultiCertConfigLoader::init_server_ssl_ctx(std::vector &cert_list, co } else { // disable client cert support server_verify_client = SSL_VERIFY_NONE; - Error("illegal client certification level %d in records.config", server_verify_client); + Error("illegal client certification level %d in %s", server_verify_client, ts::filename::RECORDS); } SSL_CTX_set_verify(ctx, server_verify_client, ssl_verify_client_callback); SSL_CTX_set_verify_depth(ctx, params->verify_depth); // might want to make configurable at some point. @@ -1340,7 +1341,7 @@ SSLMultiCertConfigLoader::init_server_ssl_ctx(std::vector &cert_list, co if (params->cipherSuite != nullptr) { if (!SSL_CTX_set_cipher_list(ctx, params->cipherSuite)) { - SSLError("invalid cipher suite in records.config"); + SSLError("invalid cipher suite in %s", ts::filename::RECORDS); goto fail; } } @@ -1348,7 +1349,7 @@ SSLMultiCertConfigLoader::init_server_ssl_ctx(std::vector &cert_list, co #if TS_USE_TLS_SET_CIPHERSUITES if (params->server_tls13_cipher_suites != nullptr) { if (!SSL_CTX_set_ciphersuites(ctx, params->server_tls13_cipher_suites)) { - SSLError("invalid tls server cipher suites in records.config"); + SSLError("invalid tls server cipher suites in %s", ts::filename::RECORDS); goto fail; } } @@ -1361,7 +1362,7 @@ SSLMultiCertConfigLoader::init_server_ssl_ctx(std::vector &cert_list, co #else if (!SSL_CTX_set1_curves_list(ctx, params->server_groups_list)) { #endif - SSLError("invalid groups list for server in records.config"); + SSLError("invalid groups list for server in %s", ts::filename::RECORDS); goto fail; } } @@ -1590,7 +1591,7 @@ SSLMultiCertConfigLoader::load(SSLCertLookup *lookup) const matcher_tags sslCertTags = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, false}; - Note("ssl_multicert.config loading ..."); + Note("%s loading ...", ts::filename::SSL_MULTICERT); if (params->configFilePath) { file_buf = readIntoBuffer(params->configFilePath, __func__, nullptr); diff --git a/lib/records/RecCore.cc b/lib/records/RecCore.cc index 01430b7253e..75b481df963 100644 --- a/lib/records/RecCore.cc +++ b/lib/records/RecCore.cc @@ -219,9 +219,9 @@ RecCoreInit(RecModeT mode_type, Diags *_diags) ink_mutex_init(&g_rec_config_lock); - g_rec_config_fpath = ats_stringdup(RecConfigReadConfigPath(nullptr, RECORDS_CONF_FILENAME)); + g_rec_config_fpath = ats_stringdup(RecConfigReadConfigPath(nullptr, ts::filename::RECORDS)); if (RecFileExists(g_rec_config_fpath) == REC_ERR_FAIL) { - RecLog(DL_Warning, "Could not find '%s', system will run with defaults\n", RECORDS_CONF_FILENAME); + RecLog(DL_Warning, "Could not find '%s', system will run with defaults\n", ts::filename::RECORDS); file_exists = false; } @@ -1257,7 +1257,7 @@ std::string RecConfigReadPersistentStatsPath() { std::string rundir(RecConfigReadRuntimeDir()); - return Layout::relative_to(rundir, RECORDS_STATS_FILE); + return Layout::relative_to(rundir, ts::filename::RECORDS_STATS); } void diff --git a/mgmt/LocalManager.cc b/mgmt/LocalManager.cc index 369cfd66e3e..09c9c1ce030 100644 --- a/mgmt/LocalManager.cc +++ b/mgmt/LocalManager.cc @@ -750,9 +750,9 @@ LocalManager::processEventQueue() // check if we have a local file update if (mh->msg_id == MGMT_EVENT_CONFIG_FILE_UPDATE) { // records.config - if (!(strcmp(payload.begin(), RECORDS_CONF_FILENAME))) { + if (!(strcmp(payload.begin(), ts::filename::RECORDS))) { if (RecReadConfigFile() != REC_ERR_OKAY) { - mgmt_elog(errno, "[fileUpdated] Config update failed for records.config\n"); + mgmt_elog(errno, "[fileUpdated] Config update failed for %s\n", ts::filename::RECORDS); } else { RecConfigWarnIfUnregistered(); } diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc index 8e7ec9ddfbf..6fa1c63b4fe 100644 --- a/mgmt/RecordsConfig.cc +++ b/mgmt/RecordsConfig.cc @@ -22,6 +22,7 @@ */ #include "tscore/ink_config.h" +#include "tscore/Filenames.h" #include "RecordsConfig.h" #if TS_USE_REMOTE_UNWINDING @@ -420,7 +421,7 @@ static const RecordElement RecordsConfig[] = // ############################## {RECT_CONFIG, "proxy.config.http.parent_proxies", RECD_STRING, nullptr, RECU_DYNAMIC, RR_NULL, RECC_STR, ".*", RECA_NULL} , - {RECT_CONFIG, "proxy.config.http.parent_proxy.file", RECD_STRING, "parent.config", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} + {RECT_CONFIG, "proxy.config.http.parent_proxy.file", RECD_STRING, ts::filename::PARENT, RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , {RECT_CONFIG, "proxy.config.http.parent_proxy.retry_time", RECD_INT, "300", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , @@ -687,7 +688,7 @@ static const RecordElement RecordsConfig[] = , {RECT_CONFIG, "proxy.config.socks.socks_version", RECD_INT, "4", RECU_RESTART_TS, RR_NULL, RECC_INT, "[4-5]", RECA_NULL} , - {RECT_CONFIG, "proxy.config.socks.socks_config_file", RECD_STRING, "socks.config", RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} + {RECT_CONFIG, "proxy.config.socks.socks_config_file", RECD_STRING, ts::filename::SOCKS, RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , {RECT_CONFIG, "proxy.config.socks.socks_timeout", RECD_INT, "100", RECU_RESTART_TS, RR_NULL, RECC_STR, "^[0-9]+$", RECA_NULL} , @@ -796,13 +797,13 @@ static const RecordElement RecordsConfig[] = //# Cache //# //############################################################################## - {RECT_CONFIG, "proxy.config.cache.control.filename", RECD_STRING, "cache.config", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} + {RECT_CONFIG, "proxy.config.cache.control.filename", RECD_STRING, ts::filename::CACHE, RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , - {RECT_CONFIG, "proxy.config.cache.ip_allow.filename", RECD_STRING, "ip_allow.yaml", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} + {RECT_CONFIG, "proxy.config.cache.ip_allow.filename", RECD_STRING, ts::filename::IP_ALLOW, RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , - {RECT_CONFIG, "proxy.config.cache.hosting_filename", RECD_STRING, "hosting.config", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} + {RECT_CONFIG, "proxy.config.cache.hosting_filename", RECD_STRING, ts::filename::HOSTING, RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , - {RECT_CONFIG, "proxy.config.cache.volume_filename", RECD_STRING, "volume.config", RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} + {RECT_CONFIG, "proxy.config.cache.volume_filename", RECD_STRING, ts::filename::VOLUME, RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , {RECT_CONFIG, "proxy.config.cache.permit.pinning", RECD_INT, "0", RECU_DYNAMIC, RR_NULL, RECC_INT, "[0-1]", RECA_NULL} , @@ -879,7 +880,7 @@ static const RecordElement RecordsConfig[] = , {RECT_CONFIG, "proxy.config.dns.splitDNS.enabled", RECD_INT, "0", RECU_DYNAMIC, RR_NULL, RECC_INT, "[0-1]", RECA_NULL} , - {RECT_CONFIG, "proxy.config.dns.splitdns.filename", RECD_STRING, "splitdns.config", RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL} + {RECT_CONFIG, "proxy.config.dns.splitdns.filename", RECD_STRING, ts::filename::SPLITDNS, RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , {RECT_CONFIG, "proxy.config.dns.nameservers", RECD_STRING, nullptr, RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , @@ -1000,7 +1001,7 @@ static const RecordElement RecordsConfig[] = , {RECT_CONFIG, "proxy.config.log.logfile_perm", RECD_STRING, "rw-r--r--", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , - {RECT_CONFIG, "proxy.config.log.config.filename", RECD_STRING, "logging.yaml", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} + {RECT_CONFIG, "proxy.config.log.config.filename", RECD_STRING, ts::filename::LOGGING, RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , {RECT_CONFIG, "proxy.config.log.preproc_threads", RECD_INT, "1", RECU_DYNAMIC, RR_REQUIRED, RECC_INT, "[1-128]", RECA_NULL} , @@ -1041,7 +1042,7 @@ static const RecordElement RecordsConfig[] = //############################################################################## {RECT_CONFIG, "proxy.config.reverse_proxy.enabled", RECD_INT, "1", RECU_DYNAMIC, RR_REQUIRED, RECC_INT, "[0-1]", RECA_NULL} , - {RECT_CONFIG, "proxy.config.url_remap.filename", RECD_STRING, "remap.config", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} + {RECT_CONFIG, "proxy.config.url_remap.filename", RECD_STRING, ts::filename::REMAP, RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , {RECT_CONFIG, "proxy.config.url_remap.remap_required", RECD_INT, "1", RECU_DYNAMIC, RR_NULL, RECC_INT, "[0-1]", RECA_NULL} , @@ -1085,11 +1086,11 @@ static const RecordElement RecordsConfig[] = , {RECT_CONFIG, "proxy.config.ssl.server.cert_chain.filename", RECD_STRING, nullptr, RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , - {RECT_CONFIG, "proxy.config.ssl.server.multicert.filename", RECD_STRING, "ssl_multicert.config", RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} + {RECT_CONFIG, "proxy.config.ssl.server.multicert.filename", RECD_STRING, ts::filename::SSL_MULTICERT, RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , {RECT_CONFIG, "proxy.config.ssl.server.multicert.exit_on_load_fail", RECD_INT, "1", RECU_RESTART_TS, RR_NULL, RECC_NULL, "[0-1]", RECA_NULL} , - {RECT_CONFIG, "proxy.config.ssl.servername.filename", RECD_STRING, "sni.yaml", RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} + {RECT_CONFIG, "proxy.config.ssl.servername.filename", RECD_STRING, ts::filename::SNI, RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , {RECT_CONFIG, "proxy.config.ssl.server.ticket_key.filename", RECD_STRING, nullptr, RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , diff --git a/proxy/CacheControl.cc b/proxy/CacheControl.cc index 072c4709e99..bf1608e33db 100644 --- a/proxy/CacheControl.cc +++ b/proxy/CacheControl.cc @@ -31,6 +31,7 @@ #include #include "tscore/ink_config.h" +#include "tscore/Filenames.h" #include "CacheControl.h" #include "ControlMatcher.h" #include "Main.h" @@ -143,16 +144,16 @@ initCacheControl() void reloadCacheControl() { - Note("cache.config loading ..."); + Note("%s loading ...", ts::filename::CACHE); CC_table *newTable; - Debug("cache_control", "cache.config updated, reloading"); + Debug("cache_control", "%s updated, reloading", ts::filename::CACHE); eventProcessor.schedule_in(new CC_FreerContinuation(CacheControlTable), CACHE_CONTROL_TIMEOUT, ET_CACHE); newTable = new CC_table("proxy.config.cache.control.filename", modulePrefix, &http_dest_tags); ink_atomic_swap(&CacheControlTable, newTable); - Note("cache.config finished loading"); + Note("%s finished loading", ts::filename::CACHE); } void @@ -297,7 +298,7 @@ CacheControlRecord::Init(matcher_line *line_info) directive = CC_IGNORE_SERVER_NO_CACHE; d_found = true; } else { - return Result::failure("%s Invalid action at line %d in cache.config", modulePrefix, line_num); + return Result::failure("%s Invalid action at line %d in %s", modulePrefix, line_num, ts::filename::CACHE); } } else { if (strcasecmp(label, "revalidate") == 0) { @@ -317,7 +318,7 @@ CacheControlRecord::Init(matcher_line *line_info) this->time_arg = time_in; } else { - return Result::failure("%s %s at line %d in cache.config", modulePrefix, tmp, line_num); + return Result::failure("%s %s at line %d in %s", modulePrefix, tmp, line_num, ts::filename::CACHE); } } } @@ -331,14 +332,14 @@ CacheControlRecord::Init(matcher_line *line_info) } if (d_found == false) { - return Result::failure("%s No directive in cache.config at line %d", modulePrefix, line_num); + return Result::failure("%s No directive in %s at line %d", modulePrefix, ts::filename::CACHE, line_num); } // Process any modifiers to the directive, if they exist if (line_info->num_el > 0) { tmp = ProcessModifiers(line_info); if (tmp != nullptr) { - return Result::failure("%s %s at line %d in cache.config", modulePrefix, tmp, line_num); + return Result::failure("%s %s at line %d in %s", modulePrefix, tmp, line_num, ts::filename::CACHE); } } diff --git a/proxy/IPAllow.cc b/proxy/IPAllow.cc index 1761a0c7e54..776c8b5fd34 100644 --- a/proxy/IPAllow.cc +++ b/proxy/IPAllow.cc @@ -29,6 +29,7 @@ #include "tscore/BufferWriter.h" #include "tscore/ts_file.h" #include "tscore/ink_memory.h" +#include "tscore/Filenames.h" #include "yaml-cpp/yaml.h" @@ -136,14 +137,14 @@ IpAllow::reconfigure() { self_type *new_table; - Note("ip_allow.yaml loading ..."); + Note("%s loading ...", ts::filename::IP_ALLOW); new_table = new self_type("proxy.config.cache.ip_allow.filename"); new_table->BuildTable(); configid = configProcessor.set(configid, new_table); - Note("ip_allow.yaml finished loading"); + Note("%s finished loading", ts::filename::IP_ALLOW); } IpAllow * diff --git a/proxy/ParentSelection.cc b/proxy/ParentSelection.cc index e8a787798d0..27c52c9c531 100644 --- a/proxy/ParentSelection.cc +++ b/proxy/ParentSelection.cc @@ -30,6 +30,7 @@ #include "HTTP.h" #include "HttpTransact.h" #include "I_Machine.h" +#include "tscore/Filenames.h" #define MAX_SIMPLE_RETRIES 5 #define MAX_UNAVAILABLE_SERVER_RETRIES 5 @@ -264,7 +265,7 @@ ParentConfig::startup() void ParentConfig::reconfigure() { - Note("parent.config loading ..."); + Note("%s loading ...", ts::filename::PARENT); ParentConfigParams *params = nullptr; @@ -280,7 +281,7 @@ ParentConfig::reconfigure() ParentConfig::print(); } - Note("parent.config finished loading"); + Note("%s finished loading", ts::filename::PARENT); } // void ParentConfig::print @@ -743,14 +744,14 @@ ParentRecord::Init(matcher_line *line_info) } if (this->parents == nullptr && go_direct == false) { - return Result::failure("%s No parent specified in parent.config at line %d", modulePrefix, line_num); + return Result::failure("%s No parent specified in %s at line %d", modulePrefix, ts::filename::PARENT, line_num); } // Process any modifiers to the directive, if they exist if (line_info->num_el > 0) { tmp = ProcessModifiers(line_info); if (tmp != nullptr) { - return Result::failure("%s %s at line %d in parent.config", modulePrefix, tmp, line_num); + return Result::failure("%s %s at line %d in %s", modulePrefix, tmp, line_num, ts::filename::PARENT); } // record SCHEME modifier if present. // NULL if not present @@ -895,7 +896,7 @@ setup_socks_servers(ParentRecord *rec_arr, int len) void SocksServerConfig::reconfigure() { - Note("socks.config loading ..."); + Note("%s loading ...", ts::filename::SOCKS); char *default_val = nullptr; int retry_time = 30; @@ -935,7 +936,7 @@ SocksServerConfig::reconfigure() SocksServerConfig::print(); } - Note("socks.config finished loading"); + Note("%s finished loading", ts::filename::SOCKS); } void diff --git a/proxy/Plugin.cc b/proxy/Plugin.cc index 4687ddb5528..b658e31c811 100644 --- a/proxy/Plugin.cc +++ b/proxy/Plugin.cc @@ -30,6 +30,7 @@ #include "InkAPIInternal.h" #include "Plugin.h" #include "tscore/ink_cap.h" +#include "tscore/Filenames.h" #define MAX_PLUGIN_ARGS 64 @@ -208,7 +209,7 @@ plugin_expand(char *arg) } not_found: - Warning("plugin.config: unable to find parameter %s", arg); + Warning("%s: unable to find parameter %s", ts::filename::PLUGIN, arg); return nullptr; } @@ -231,11 +232,11 @@ plugin_init(bool validateOnly) INIT_ONCE = false; } - Note("plugin.config loading ..."); - path = RecConfigReadConfigPath(nullptr, "plugin.config"); + Note("%s loading ...", ts::filename::PLUGIN); + path = RecConfigReadConfigPath(nullptr, ts::filename::PLUGIN); fd = open(path, O_RDONLY); if (fd < 0) { - Warning("plugin.config failed to load: %d, %s", errno, strerror(errno)); + Warning("%s failed to load: %d, %s", ts::filename::PLUGIN, errno, strerror(errno)); return false; } @@ -311,9 +312,9 @@ plugin_init(bool validateOnly) close(fd); if (retVal) { - Note("plugin.config finished loading"); + Note("%s finished loading", ts::filename::PLUGIN); } else { - Error("plugin.config failed to load"); + Error("%s failed to load", ts::filename::PLUGIN); } return retVal; } diff --git a/proxy/ReverseProxy.cc b/proxy/ReverseProxy.cc index 2f5de1a917b..0d68c8beb2a 100644 --- a/proxy/ReverseProxy.cc +++ b/proxy/ReverseProxy.cc @@ -28,6 +28,7 @@ */ #include "tscore/ink_platform.h" +#include "tscore/Filenames.h" #include #include "P_EventSystem.h" #include "P_Cache.h" @@ -64,11 +65,11 @@ init_reverse_proxy() reconfig_mutex = new_ProxyMutex(); rewrite_table = new UrlRewrite(); - Note("remap.config loading ..."); + Note("%s loading ...", ts::filename::REMAP); if (!rewrite_table->load()) { - Fatal("remap.config failed to load"); + Fatal("%s failed to load", ts::filename::REMAP); } - Note("remap.config finished loading"); + Note("%s finished loading", ts::filename::REMAP); REC_RegisterConfigUpdateFunc("proxy.config.url_remap.filename", url_rewrite_CB, (void *)FILE_CHANGED); REC_RegisterConfigUpdateFunc("proxy.config.proxy_name", url_rewrite_CB, (void *)TSNAME_CHANGED); @@ -136,11 +137,11 @@ reloadUrlRewrite() { UrlRewrite *newTable, *oldTable; - Note("remap.config loading ..."); - Debug("url_rewrite", "remap.config updated, reloading..."); + Note("%s loading ...", ts::filename::REMAP); + Debug("url_rewrite", "%s updated, reloading...", ts::filename::REMAP); newTable = new UrlRewrite(); if (newTable->load()) { - static const char *msg = "remap.config finished loading"; + static const char *msg = "%s finished loading"; // Hold at least one lease, until we reload the configuration newTable->acquire(); @@ -154,15 +155,15 @@ reloadUrlRewrite() oldTable->pluginFactory.deactivate(); oldTable->release(); - Debug("url_rewrite", "%s", msg); + Debug("url_rewrite", msg, ts::filename::REMAP); Note("%s", msg); return true; } else { - static const char *msg = "remap.config failed to load"; + static const char *msg = "%s failed to load"; delete newTable; - Debug("url_rewrite", "%s", msg); - Error("%s", msg); + Debug("url_rewrite", msg, ts::filename::REMAP); + Error(msg, ts::filename::REMAP); return false; } } diff --git a/proxy/http/HttpBodyFactory.cc b/proxy/http/HttpBodyFactory.cc index 65b44c2d287..a13d06daf57 100644 --- a/proxy/http/HttpBodyFactory.cc +++ b/proxy/http/HttpBodyFactory.cc @@ -31,6 +31,7 @@ #include "tscore/ink_platform.h" #include "tscore/ink_sprintf.h" #include "tscore/ink_file.h" +#include "tscore/Filenames.h" #include "HttpBodyFactory.h" #include #include @@ -334,7 +335,7 @@ HttpBodyFactory::HttpBodyFactory() for (i = 0; config_record_names[i] != nullptr; i++) { status = REC_RegisterConfigUpdateFunc(config_record_names[i], config_callback, (void *)this); if (status != REC_ERR_OKAY) { - Warning("couldn't register variable '%s', is records.config up to date?", config_record_names[i]); + Warning("couldn't register variable '%s', is %s up to date?", config_record_names[i], ts::filename::RECORDS); } no_registrations_failed = no_registrations_failed && (status == REC_ERR_OKAY); } diff --git a/proxy/http/HttpConfig.cc b/proxy/http/HttpConfig.cc index 0d247f5866b..1aa62b3b8dd 100644 --- a/proxy/http/HttpConfig.cc +++ b/proxy/http/HttpConfig.cc @@ -22,6 +22,7 @@ */ #include "tscore/ink_config.h" +#include "tscore/Filenames.h" #include #include #include "HttpConfig.h" @@ -1266,9 +1267,9 @@ HttpConfig::reconfigure() if (params->outbound_conntrack.queue_size > 0 && !(params->oride.outbound_conntrack.max > 0 || params->oride.outbound_conntrack.min > 0)) { Warning("'%s' is set, but neither '%s' nor '%s' are " - "set, please correct your records.config", + "set, please correct your %s", OutboundConnTrack::CONFIG_VAR_QUEUE_SIZE.data(), OutboundConnTrack::CONFIG_VAR_MAX.data(), - OutboundConnTrack::CONFIG_VAR_MIN.data()); + OutboundConnTrack::CONFIG_VAR_MIN.data(), ts::filename::RECORDS); } params->oride.attach_server_session_to_client = m_master.oride.attach_server_session_to_client; @@ -1276,8 +1277,8 @@ HttpConfig::reconfigure() params->http_hdr_field_max_size = m_master.http_hdr_field_max_size; if (params->oride.outbound_conntrack.max > 0 && params->oride.outbound_conntrack.max < params->oride.outbound_conntrack.min) { - Warning("'%s' < per_server.min_keep_alive_connections, setting min=max , please correct your records.config", - OutboundConnTrack::CONFIG_VAR_MAX.data()); + Warning("'%s' < per_server.min_keep_alive_connections, setting min=max , please correct your %s", + OutboundConnTrack::CONFIG_VAR_MAX.data(), ts::filename::RECORDS); params->oride.outbound_conntrack.min = params->oride.outbound_conntrack.max; } diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc index 918a4b0b0c5..6c673fcae63 100644 --- a/proxy/http/HttpTransact.cc +++ b/proxy/http/HttpTransact.cc @@ -33,6 +33,7 @@ #include "HttpDebugNames.h" #include #include "tscore/ParseRules.h" +#include "tscore/Filenames.h" #include "HTTP.h" #include "HdrUtils.h" #include "logging/Log.h" @@ -6056,8 +6057,8 @@ HttpTransact::is_response_cacheable(State *s, HTTPHdr *request, HTTPHdr *respons // If a ttl is set, allow caching even if response contains // Cache-Control headers to prevent caching if (s->cache_control.ttl_in_cache > 0) { - TxnDebug("http_trans", - "[is_response_cacheable] Cache-control header directives in response overridden by ttl in cache.config"); + TxnDebug("http_trans", "[is_response_cacheable] Cache-control header directives in response overridden by ttl in %s", + ts::filename::CACHE); } else { TxnDebug("http_trans", "[is_response_cacheable] NO by response cache control"); return false; diff --git a/proxy/http/remap/UrlRewrite.cc b/proxy/http/remap/UrlRewrite.cc index 39052138174..c0dc69b5da5 100644 --- a/proxy/http/remap/UrlRewrite.cc +++ b/proxy/http/remap/UrlRewrite.cc @@ -27,6 +27,7 @@ #include "ReverseProxy.h" #include "RemapConfig.h" #include "tscore/I_Layout.h" +#include "tscore/Filenames.h" #include "HttpSM.h" #define modulePrefix "[ReverseProxy]" @@ -55,10 +56,10 @@ UrlRewrite::load() { ats_scoped_str config_file_path; - config_file_path = RecConfigReadConfigPath("proxy.config.url_remap.filename", "remap.config"); + config_file_path = RecConfigReadConfigPath("proxy.config.url_remap.filename", ts::filename::REMAP); if (!config_file_path) { pmgmt->signalManager(MGMT_SIGNAL_CONFIG_ERROR, "Unable to find proxy.config.url_remap.filename"); - Warning("%s Unable to locate remap.config. No remappings in effect", modulePrefix); + Warning("%s Unable to locate %s. No remappings in effect", modulePrefix, ts::filename::REMAP); return false; } diff --git a/proxy/logging/LogConfig.cc b/proxy/logging/LogConfig.cc index 77d517147da..6500bc1dc69 100644 --- a/proxy/logging/LogConfig.cc +++ b/proxy/logging/LogConfig.cc @@ -34,6 +34,7 @@ #include "tscore/ink_file.h" #include "tscore/List.h" +#include "tscore/Filenames.h" #include "Log.h" #include "LogField.h" @@ -806,7 +807,7 @@ LogConfig::update_space_used() bool LogConfig::evaluate_config() { - ats_scoped_str path(RecConfigReadConfigPath("proxy.config.log.config.filename", "logging.yaml")); + ats_scoped_str path(RecConfigReadConfigPath("proxy.config.log.config.filename", ts::filename::LOGGING)); struct stat sbuf; if (stat(path.get(), &sbuf) == -1 && errno == ENOENT) { Warning("logging configuration '%s' doesn't exist", path.get()); diff --git a/proxy/shared/DiagsConfig.cc b/proxy/shared/DiagsConfig.cc index b1ce1fe33cb..2246dc89631 100644 --- a/proxy/shared/DiagsConfig.cc +++ b/proxy/shared/DiagsConfig.cc @@ -25,6 +25,7 @@ #include "tscore/ink_memory.h" #include "tscore/ink_file.h" #include "tscore/I_Layout.h" +#include "tscore/Filenames.h" #include "DiagsConfig.h" #include "records/P_RecCore.h" @@ -337,7 +338,7 @@ DiagsConfig::register_diags_callbacks() for (i = 0; config_record_names[i] != nullptr; i++) { status = (REC_RegisterConfigUpdateFunc(config_record_names[i], diags_config_callback, o) == REC_ERR_OKAY); if (!status) { - Warning("couldn't register variable '%s', is records.config up to date?", config_record_names[i]); + Warning("couldn't register variable '%s', is %s up to date?", config_record_names[i], ts::filename::RECORDS); } total_status = total_status && status; } diff --git a/src/traffic_layout/info.cc b/src/traffic_layout/info.cc index 64afb6110db..736e2879c0b 100644 --- a/src/traffic_layout/info.cc +++ b/src/traffic_layout/info.cc @@ -155,14 +155,14 @@ produce_layout(bool json) print_var("PLUGINDIR", RecConfigReadPluginDir(), json); print_var("INCLUDEDIR", Layout::get()->includedir, json); - print_var(RECORDS_CONF_FILENAME, RecConfigReadConfigPath(nullptr, RECORDS_CONF_FILENAME), json); - print_var("remap.config", RecConfigReadConfigPath("proxy.config.url_remap.filename"), json); - print_var("plugin.config", RecConfigReadConfigPath(nullptr, "plugin.config"), json); - print_var("ssl_multicert.config", RecConfigReadConfigPath("proxy.config.ssl.server.multicert.filename"), json); - print_var(STORAGE_CONF_FILENAME, RecConfigReadConfigPath(nullptr, STORAGE_CONF_FILENAME), json); - print_var("hosting.config", RecConfigReadConfigPath("proxy.config.cache.hosting_filename"), json); - print_var("volume.config", RecConfigReadConfigPath("proxy.config.cache.volume_filename"), json); - print_var("ip_allow.yaml", RecConfigReadConfigPath("proxy.config.cache.ip_allow.filename"), json, true); + print_var(ts::filename::RECORDS, RecConfigReadConfigPath(nullptr, ts::filename::RECORDS), json); + print_var(ts::filename::REMAP, RecConfigReadConfigPath("proxy.config.url_remap.filename"), json); + print_var(ts::filename::PLUGIN, RecConfigReadConfigPath(nullptr, ts::filename::PLUGIN), json); + print_var(ts::filename::SSL_MULTICERT, RecConfigReadConfigPath("proxy.config.ssl.server.multicert.filename"), json); + print_var(ts::filename::STORAGE, RecConfigReadConfigPath(nullptr, ts::filename::STORAGE), json); + print_var(ts::filename::HOSTING, RecConfigReadConfigPath("proxy.config.cache.hosting_filename"), json); + print_var(ts::filename::VOLUME, RecConfigReadConfigPath("proxy.config.cache.volume_filename"), json); + print_var(ts::filename::IP_ALLOW, RecConfigReadConfigPath("proxy.config.cache.ip_allow.filename"), json, true); if (json) { printf("}\n"); } diff --git a/src/traffic_manager/AddConfigFilesHere.cc b/src/traffic_manager/AddConfigFilesHere.cc index 553c050d00c..be91a826603 100644 --- a/src/traffic_manager/AddConfigFilesHere.cc +++ b/src/traffic_manager/AddConfigFilesHere.cc @@ -73,20 +73,20 @@ initializeRegistry() ink_assert(!"Configuration Object Registry Initialized More than Once"); } - registerFile("proxy.config.log.config.filename", "logging.yaml"); - registerFile("", STORAGE_CONF_FILENAME); - registerFile("proxy.config.socks.socks_config_file", "socks.config"); - registerFile(RECORDS_CONF_FILENAME, RECORDS_CONF_FILENAME); - registerFile("proxy.config.cache.control.filename", "cache.config"); - registerFile("proxy.config.cache.ip_allow.filename", "ip_allow.yaml"); - registerFile("proxy.config.http.parent_proxy.file", "parent.config"); - registerFile("proxy.config.url_remap.filename", "remap.config"); - registerFile("", "volume.config"); - registerFile("proxy.config.cache.hosting_filename", "hosting.config"); - registerFile("", "plugin.config"); - registerFile("proxy.config.dns.splitdns.filename", "splitdns.config"); - registerFile("proxy.config.ssl.server.multicert.filename", "ssl_multicert.config"); - registerFile("proxy.config.ssl.servername.filename", "sni.config"); + registerFile("proxy.config.log.config.filename", ts::filename::LOGGING); + registerFile("", ts::filename::STORAGE); + registerFile("proxy.config.socks.socks_config_file", ts::filename::SOCKS); + registerFile(ts::filename::RECORDS, ts::filename::RECORDS); + registerFile("proxy.config.cache.control.filename", ts::filename::CACHE); + registerFile("proxy.config.cache.ip_allow.filename", ts::filename::IP_ALLOW); + registerFile("proxy.config.http.parent_proxy.file", ts::filename::PARENT); + registerFile("proxy.config.url_remap.filename", ts::filename::REMAP); + registerFile("", ts::filename::VOLUME); + registerFile("proxy.config.cache.hosting_filename", ts::filename::HOSTING); + registerFile("", ts::filename::PLUGIN); + registerFile("proxy.config.dns.splitdns.filename", ts::filename::SPLITDNS); + registerFile("proxy.config.ssl.server.multicert.filename", ts::filename::SSL_MULTICERT); + registerFile("proxy.config.ssl.servername.filename", ts::filename::SNI); configFiles->registerCallback(testcall); } diff --git a/src/traffic_manager/traffic_manager.cc b/src/traffic_manager/traffic_manager.cc index ccbf1626267..152ab78280c 100644 --- a/src/traffic_manager/traffic_manager.cc +++ b/src/traffic_manager/traffic_manager.cc @@ -91,7 +91,7 @@ static char bind_stderr[512] = ""; static const char *mgmt_path = nullptr; // By default, set the current directory as base -static const char *recs_conf = RECORDS_CONF_FILENAME; +static const char *recs_conf = ts::filename::RECORDS; static int fds_limit; diff --git a/src/traffic_server/InkAPITest.cc b/src/traffic_server/InkAPITest.cc index d6713a8180b..685da749bb1 100644 --- a/src/traffic_server/InkAPITest.cc +++ b/src/traffic_server/InkAPITest.cc @@ -40,6 +40,7 @@ #include "tscore/ink_sprintf.h" #include "tscore/ink_file.h" #include "tscore/Regression.h" +#include "tscore/Filenames.h" #include "ts/ts.h" #include "ts/experimental.h" #include "records/I_RecCore.h" @@ -1995,7 +1996,6 @@ REGRESSION_TEST(SDK_API_TSCache)(RegressionTest *test, int /* atype ATS_UNUSED * // TSfread // TSfwrite ////////////////////////////////////////////// -#define PFX "plugin.config" // Note that for each test, if it fails, we set the error status and return. REGRESSION_TEST(SDK_API_TSfopen)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus) @@ -2013,8 +2013,7 @@ REGRESSION_TEST(SDK_API_TSfopen)(RegressionTest *test, int /* atype ATS_UNUSED * struct stat stat_buffer_pre, stat_buffer_post, stat_buffer_input; char *ret_val; int read = 0, wrote = 0; - int64_t read_amount = 0; - char INPUT_TEXT_FILE[] = "plugin.config"; + int64_t read_amount = 0; char input_file_full_path[BUFSIZ]; // Set full path to file at run time. @@ -2027,7 +2026,7 @@ REGRESSION_TEST(SDK_API_TSfopen)(RegressionTest *test, int /* atype ATS_UNUSED * return; } // Add "etc/trafficserver" to point to config directory - ink_filepath_make(input_file_full_path, sizeof(input_file_full_path), TSConfigDirGet(), INPUT_TEXT_FILE); + ink_filepath_make(input_file_full_path, sizeof(input_file_full_path), TSConfigDirGet(), ts::filename::PLUGIN); // open existing file for reading if (!(source_read_file = TSfopen(input_file_full_path, "r"))) { @@ -2041,7 +2040,7 @@ REGRESSION_TEST(SDK_API_TSfopen)(RegressionTest *test, int /* atype ATS_UNUSED * } // Create unique tmp _file_name_, do not use any TS file_name - snprintf(write_file_name, PATH_NAME_MAX, "/tmp/%sXXXXXX", PFX); + snprintf(write_file_name, PATH_NAME_MAX, "/tmp/%sXXXXXX", ts::filename::PLUGIN); int write_file_fd; // this file will be reopened below if ((write_file_fd = mkstemp(write_file_name)) <= 0) { SDK_RPRINT(test, "mkstemp", "std func", TC_FAIL, "can't create file for writing"); diff --git a/src/traffic_server/traffic_server.cc b/src/traffic_server/traffic_server.cc index 44e3d249725..d57e1a3fe22 100644 --- a/src/traffic_server/traffic_server.cc +++ b/src/traffic_server/traffic_server.cc @@ -38,6 +38,7 @@ #include "tscore/ink_syslog.h" #include "tscore/hugepages.h" #include "tscore/runroot.h" +#include "tscore/Filenames.h" #include "ts/ts.h" // This is sadly needed because of us using TSThreadInit() for some reason. @@ -857,23 +858,23 @@ cmd_verify(char * /* cmd ATS_UNUSED */) if (!urlRewriteVerify()) { exitStatus |= (1 << 0); - fprintf(stderr, "ERROR: Failed to load remap.config, exitStatus %d\n\n", exitStatus); + fprintf(stderr, "ERROR: Failed to load %s, exitStatus %d\n\n", ts::filename::REMAP, exitStatus); } else { - fprintf(stderr, "INFO: Successfully loaded remap.config\n\n"); + fprintf(stderr, "INFO: Successfully loaded %s\n\n", ts::filename::REMAP); } if (RecReadConfigFile() != REC_ERR_OKAY) { exitStatus |= (1 << 1); - fprintf(stderr, "ERROR: Failed to load records.config, exitStatus %d\n\n", exitStatus); + fprintf(stderr, "ERROR: Failed to load %s, exitStatus %d\n\n", ts::filename::RECORDS, exitStatus); } else { - fprintf(stderr, "INFO: Successfully loaded records.config\n\n"); + fprintf(stderr, "INFO: Successfully loaded %s\n\n", ts::filename::RECORDS); } if (!plugin_init(true)) { exitStatus |= (1 << 2); - fprintf(stderr, "ERROR: Failed to load plugin.config, exitStatus %d\n\n", exitStatus); + fprintf(stderr, "ERROR: Failed to load %s, exitStatus %d\n\n", ts::filename::PLUGIN, exitStatus); } else { - fprintf(stderr, "INFO: Successfully loaded plugin.config\n\n"); + fprintf(stderr, "INFO: Successfully loaded %s\n\n", ts::filename::PLUGIN); } SSLInitializeLibrary(); @@ -1304,7 +1305,7 @@ syslog_log_configure() ats_free(facility_str); if (facility < 0) { - syslog(LOG_WARNING, "Bad syslog facility in records.config. Keeping syslog at LOG_DAEMON"); + syslog(LOG_WARNING, "Bad syslog facility in %s. Keeping syslog at LOG_DAEMON", ts::filename::RECORDS); } else { Debug("server", "Setting syslog facility to %d", facility); closelog(); @@ -1474,7 +1475,8 @@ change_uid_gid(const char *user) "\tand then rebuild the server.\n" "\tIt is strongly suggested that you instead modify the\n" "\tproxy.config.admin.user_id directive in your\n" - "\trecords.config file to list a non-root user.\n"); + "\t%s file to list a non-root user.\n", + ts::filename::RECORDS); } #endif } @@ -2104,13 +2106,13 @@ init_ssl_ctx_callback(void *ctx, bool server) static void load_ssl_file_callback(const char *ssl_file) { - pmgmt->signalConfigFileChild("ssl_multicert.config", ssl_file); + pmgmt->signalConfigFileChild(ts::filename::SSL_MULTICERT, ssl_file); } static void load_remap_file_callback(const char *remap_file) { - pmgmt->signalConfigFileChild("remap.config", remap_file); + pmgmt->signalConfigFileChild(ts::filename::REMAP, remap_file); } static void diff --git a/src/tscore/Filenames.cc b/src/tscore/Filenames.cc deleted file mode 100644 index 018804c7ffe..00000000000 --- a/src/tscore/Filenames.cc +++ /dev/null @@ -1,29 +0,0 @@ -/** @file - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -/////////////////////////////////////////////////////////////////// -// Configuration file names -const char *STORAGE_CONF_FILENAME = "storage.config"; -const char *RECORDS_CONF_FILENAME = "records.config"; - -/////////////////////////////////////////////////////////////////// -// Various other file names -const char *RECORDS_STATS_FILE = "records.snap"; diff --git a/src/tscore/Makefile.am b/src/tscore/Makefile.am index faa2fc02ca3..c342179c890 100644 --- a/src/tscore/Makefile.am +++ b/src/tscore/Makefile.am @@ -64,7 +64,6 @@ libtscore_la_SOURCES = \ EventNotify.cc \ Extendible.cc \ fastlz.c \ - Filenames.cc \ Hash.cc \ HashFNV.cc \ HashMD5.cc \ diff --git a/src/tscore/unit_tests/test_layout.cc b/src/tscore/unit_tests/test_layout.cc index bd25517b798..736393bd847 100644 --- a/src/tscore/unit_tests/test_layout.cc +++ b/src/tscore/unit_tests/test_layout.cc @@ -80,8 +80,8 @@ TEST_CASE("relative to test", "[relative_to]") // relative to (4 parameters) char config_file[PATH_NAME_MAX]; - Layout::relative_to(config_file, sizeof(config_file), Layout::get()->sysconfdir, RECORDS_CONF_FILENAME); - std::string a = Layout::relative_to(Layout::get()->sysconfdir, RECORDS_CONF_FILENAME); + Layout::relative_to(config_file, sizeof(config_file), Layout::get()->sysconfdir, ts::filename::RECORDS); + std::string a = Layout::relative_to(Layout::get()->sysconfdir, ts::filename::RECORDS); std::string b = config_file; REQUIRE(a == b); } From e67db9b68e40edb8436f221f4834bc79bb566760 Mon Sep 17 00:00:00 2001 From: "Alan M. Carroll" Date: Sat, 19 Oct 2019 17:32:14 -0500 Subject: [PATCH 151/718] Doc: clean up build errors. (cherry picked from commit ee5a7a411e3397cf362ef58b9071543021fd577b) --- doc/admin-guide/files/logging.yaml.en.rst | 4 ++-- doc/admin-guide/logging/examples.en.rst | 2 +- doc/admin-guide/logging/understanding.en.rst | 2 +- doc/admin-guide/plugins/lua.en.rst | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/admin-guide/files/logging.yaml.en.rst b/doc/admin-guide/files/logging.yaml.en.rst index f4d69373f2f..d7e076add49 100644 --- a/doc/admin-guide/files/logging.yaml.en.rst +++ b/doc/admin-guide/files/logging.yaml.en.rst @@ -325,7 +325,7 @@ common fields: formats: - name: minimalfmt - format: '% : % : %' + format: '% , % , %' The following is an example of a format that uses aggregate operators to produce a summary log: @@ -334,7 +334,7 @@ produce a summary log: formats: - name: summaryfmt - format: '% : % : %' + format: '%:%:%' interval: 10 The following is an example of a filter that will cause only REFRESH_HIT events diff --git a/doc/admin-guide/logging/examples.en.rst b/doc/admin-guide/logging/examples.en.rst index a4895cfea33..84b919c84de 100644 --- a/doc/admin-guide/logging/examples.en.rst +++ b/doc/admin-guide/logging/examples.en.rst @@ -247,7 +247,7 @@ to clients: formats: - name: mysummary - format: '% : % : %' + format: '%:%:%' interval: 10 Dual Output to Compact Binary Logs and ASCII Pipes diff --git a/doc/admin-guide/logging/understanding.en.rst b/doc/admin-guide/logging/understanding.en.rst index 6cad223de5e..b789315068a 100644 --- a/doc/admin-guide/logging/understanding.en.rst +++ b/doc/admin-guide/logging/understanding.en.rst @@ -151,7 +151,7 @@ aforementioned aggregate functions and the specification of an interval, as so: formats: - name: mysummary - format: '% : %' + format: '% , %' interval: n The interval itself is given with *n* as the number of seconds for each period diff --git a/doc/admin-guide/plugins/lua.en.rst b/doc/admin-guide/plugins/lua.en.rst index 5686b289342..dd0d1979b80 100644 --- a/doc/admin-guide/plugins/lua.en.rst +++ b/doc/admin-guide/plugins/lua.en.rst @@ -977,7 +977,7 @@ Here is an example: end -`TOP <#lua-plugin>`_ +:ref:`TOP ` ts.client_request.get_ssl_protocol ----------------------------------------------- @@ -997,7 +997,7 @@ Here is an example: end -`TOP <#lua-plugin>`_ +:ref:`TOP ` ts.client_request.get_ssl_cipher ----------------------------------------------- @@ -1017,7 +1017,7 @@ Here is an example: end -`TOP <#lua-plugin>`_ +:ref:`TOP ` ts.client_request.get_ssl_curve ----------------------------------------------- @@ -1037,7 +1037,7 @@ Here is an example: end -`TOP <#lua-plugin>`_ +:ref:`TOP ` ts.http.set_cache_url --------------------- From 8f373b4d11aa1f716c18c609be499e69c71ad15e Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Sat, 9 Nov 2019 20:06:35 -0700 Subject: [PATCH 152/718] Fix build warnings, since some configs do not have docs --- doc/release-notes/upgrading.en.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/release-notes/upgrading.en.rst b/doc/release-notes/upgrading.en.rst index 67c98e2fe4c..6ad85ab4c47 100644 --- a/doc/release-notes/upgrading.en.rst +++ b/doc/release-notes/upgrading.en.rst @@ -83,17 +83,17 @@ The following configurations still exist, and functions, but are considered deprecated and will be removed in a future release. We **strongly** encourage you to avoid using any of these: - * :ts:cv:`proxy.config.http.parent_proxy.file` * :ts:cv:`proxy.config.socks.socks_config_file` - * :ts:cv:`proxy.config.cache.control.filename` - * :ts:cv:`proxy.config.cache.ip_allow.filename` - * :ts:cv:`proxy.config.cache.hosting_filename` - * :ts:cv:`proxy.config.cache.volume_filename` - * :ts:cv:`proxy.config.dns.splitdns.filename` * :ts:cv:`proxy.config.log.config.filename` * :ts:cv:`proxy.config.url_remap.filename` * :ts:cv:`proxy.config.ssl.server.multicert.filename` * :ts:cv:`proxy.config.ssl.servername.filename` + * ``proxy.config.http.parent_proxy.file`` + * ``proxy.config.cache.control.filename`` + * ``proxy.config.cache.ip_allow.filename`` + * ``proxy.config.cache.hosting_filename`` + * ``proxy.config.cache.volume_filename`` + * ``proxy.config.dns.splitdns.filename`` Deprecated or Removed Features ------------------------------ From 23d6b2f2e4ae13f6562f1c28c0290de54b1ab5a3 Mon Sep 17 00:00:00 2001 From: Randall Meyer Date: Thu, 7 Nov 2019 16:06:39 -0800 Subject: [PATCH 153/718] tslua: Exposes set/get method for server request objects (cherry picked from commit 97692a552c8ad72a1cc8a890cdf11e53d3a6a1bc) --- doc/admin-guide/plugins/lua.en.rst | 42 ++++++++++++++++++++++ plugins/lua/ts_lua_server_request.c | 55 ++++++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/doc/admin-guide/plugins/lua.en.rst b/doc/admin-guide/plugins/lua.en.rst index dd0d1979b80..53624350cd0 100644 --- a/doc/admin-guide/plugins/lua.en.rst +++ b/doc/admin-guide/plugins/lua.en.rst @@ -1903,6 +1903,48 @@ ts.server_request.set_url_scheme :ref:`TOP ` +ts.server_request.get_method +---------------------------- +**syntax:** *ts.server_request.get_method()* + +**context:** function @ TS_LUA_HOOK_SEND_REQUEST_HDR hook point or later + +**description:** This function can be used to retrieve the current server request's method name. String like "GET" or "POST" is returned. + +Here is an example: + +:: + + function send_request() + local method = ts.server_request.get_method() + ts.debug(method) + end + + function do_remap() + ts.hook(TS_LUA_HOOK_SEND_REQUEST_HDR, send_request) + return 0 + end + +Then ``HEAD /`` will yield the output: + +``HEAD`` + +:ref:`TOP ` + +ts.server_request.set_method +---------------------------- +**syntax:** *ts.server_request.set_method()* + +**context:** function @ TS_LUA_HOOK_SEND_REQUEST_HDR hook point or later + +**description:** This function can be used to override the current server request's method with METHOD_NAME. + +:: + + ts.server_request.set_method('HEAD') + +:ref:`TOP ` + ts.server_response.get_status ----------------------------- **syntax:** *status = ts.server_response.get_status()* diff --git a/plugins/lua/ts_lua_server_request.c b/plugins/lua/ts_lua_server_request.c index c9272176efc..2aa7e459358 100644 --- a/plugins/lua/ts_lua_server_request.c +++ b/plugins/lua/ts_lua_server_request.c @@ -51,6 +51,7 @@ static void ts_lua_inject_server_request_uri_api(lua_State *L); static void ts_lua_inject_server_request_uri_args_api(lua_State *L); static void ts_lua_inject_server_request_uri_params_api(lua_State *L); static void ts_lua_inject_server_request_url_api(lua_State *L); +static void ts_lua_inject_server_request_method_api(lua_State *L); static int ts_lua_server_request_header_get(lua_State *L); static int ts_lua_server_request_header_set(lua_State *L); @@ -63,6 +64,8 @@ static int ts_lua_server_request_set_uri_args(lua_State *L); static int ts_lua_server_request_get_uri_args(lua_State *L); static int ts_lua_server_request_set_uri_params(lua_State *L); static int ts_lua_server_request_get_uri_params(lua_State *L); +static int ts_lua_server_request_get_method(lua_State *L); +static int ts_lua_server_request_set_method(lua_State *L); static int ts_lua_server_request_get_url_host(lua_State *L); static int ts_lua_server_request_set_url_host(lua_State *L); static int ts_lua_server_request_get_url_scheme(lua_State *L); @@ -87,7 +90,7 @@ ts_lua_inject_server_request_api(lua_State *L) ts_lua_inject_server_request_headers_api(L); ts_lua_inject_server_request_get_header_size_api(L); ts_lua_inject_server_request_get_body_size_api(L); - + ts_lua_inject_server_request_method_api(L); ts_lua_inject_server_request_uri_api(L); ts_lua_inject_server_request_uri_args_api(L); ts_lua_inject_server_request_uri_params_api(L); @@ -924,3 +927,53 @@ ts_lua_server_request_server_addr_set_outgoing_addr(lua_State *L) return 0; } + +static void +ts_lua_inject_server_request_method_api(lua_State *L) +{ + lua_pushcfunction(L, ts_lua_server_request_get_method); + lua_setfield(L, -2, "get_method"); + + lua_pushcfunction(L, ts_lua_server_request_set_method); + lua_setfield(L, -2, "set_method"); +} + +static int +ts_lua_server_request_get_method(lua_State *L) +{ + const char *method; + int method_len; + + ts_lua_http_ctx *http_ctx; + + GET_HTTP_CONTEXT(http_ctx, L); + + method = TSHttpHdrMethodGet(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, &method_len); + + if (method && method_len) { + lua_pushlstring(L, method, method_len); + } else { + lua_pushnil(L); + } + + return 1; +} + +static int +ts_lua_server_request_set_method(lua_State *L) +{ + const char *method; + size_t method_len; + + ts_lua_http_ctx *http_ctx; + + GET_HTTP_CONTEXT(http_ctx, L); + + method = luaL_checklstring(L, 1, &method_len); + + if (method) { + TSHttpHdrMethodSet(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, method, method_len); + } + + return 0; +} From 8978e64d26b0fcc92192444c6adb502a95c3a58c Mon Sep 17 00:00:00 2001 From: Miles Libbey Date: Tue, 12 Nov 2019 11:38:19 -0800 Subject: [PATCH 154/718] Re-order READ_REQUEST_ HDR_HOOK and PRE_REMAP_HOOK #5795 notes that READ_REQUEST_HDR_HOOK and READ_REQUEST_PRE_REMAP_HOOK in the diagram are reversed from actual. The state diagram in https://docs.trafficserver.apache.org/en/8.0.x/developer-guide/plugins/hooks-and-transactions/index.en.html#http-transaction-state-diagram show that READ_REQUEST is before PRE_REMAP. (cherry picked from commit fe0d476ec04678ae5bda6ae2a24cd5985a9dd882) --- doc/admin-guide/plugins/header_rewrite.en.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/admin-guide/plugins/header_rewrite.en.rst b/doc/admin-guide/plugins/header_rewrite.en.rst index b74e4710e09..84ce216a9ce 100644 --- a/doc/admin-guide/plugins/header_rewrite.en.rst +++ b/doc/admin-guide/plugins/header_rewrite.en.rst @@ -880,7 +880,7 @@ one forces the beginning of a new ruleset. node[shape=record]; Client[height=4, label="{ Client|{|} }"]; - ATS[height=4, fontsize=10,label="{ {{Global:\nREAD_REQUEST_PRE_REMAP_HOOK|Global:\nREAD_REQUEST_HDR_HOOK\nRemap rule:\nREMAP_PSEUDO_HOOK}|SEND_RESPONSE_HDR_HOOK}|ATS |{SEND_REQUEST_HDR_HOOK|READ_RESPONSE_HDR_HOOK} }",xlabel="ATS"]; + ATS[height=4, fontsize=10,label="{ {{Global:\nREAD_REQUEST_HDR_HOOK\nREAD_REQUEST_PRE_REMAP_HOOK|Remap rule:\nREMAP_PSEUDO_HOOK}|SEND_RESPONSE_HDR_HOOK}|ATS |{SEND_REQUEST_HDR_HOOK|READ_RESPONSE_HDR_HOOK} }",xlabel="ATS"]; Origin[height=4, label="{ {|}|Origin }"]; Client:p1 -> ATS:clientside0 [ label = "Request" ]; From cece5e5e88dc1bf7c1ed49bbf1a6f885d9537c22 Mon Sep 17 00:00:00 2001 From: Randall Meyer Date: Tue, 12 Nov 2019 09:48:19 +0800 Subject: [PATCH 155/718] Updates yaml-cpp to 0.6.3 (cherry picked from commit 14aadf430d04ec8435df7f891443194921d35d05) --- lib/yamlcpp/.gitignore | 1 + lib/yamlcpp/CMakeLists.txt | 134 +- lib/yamlcpp/README.md | 4 +- lib/yamlcpp/include/yaml-cpp/binary.h | 12 +- .../include/yaml-cpp/contrib/anchordict.h | 3 +- lib/yamlcpp/include/yaml-cpp/emitter.h | 33 +- lib/yamlcpp/include/yaml-cpp/eventhandler.h | 7 +- lib/yamlcpp/include/yaml-cpp/exceptions.h | 44 +- lib/yamlcpp/include/yaml-cpp/node/convert.h | 11 +- .../include/yaml-cpp/node/detail/impl.h | 81 +- .../include/yaml-cpp/node/detail/iterator.h | 16 +- .../include/yaml-cpp/node/detail/memory.h | 5 +- .../include/yaml-cpp/node/detail/node.h | 12 +- .../include/yaml-cpp/node/detail/node_data.h | 2 +- .../yaml-cpp/node/detail/node_iterator.h | 4 +- lib/yamlcpp/include/yaml-cpp/node/impl.h | 115 +- lib/yamlcpp/include/yaml-cpp/node/node.h | 4 + lib/yamlcpp/include/yaml-cpp/noncopyable.h | 25 - .../include/yaml-cpp/ostream_wrapper.h | 10 +- lib/yamlcpp/include/yaml-cpp/parser.h | 10 +- lib/yamlcpp/include/yaml-cpp/traits.h | 32 + lib/yamlcpp/src/binary.cpp | 11 +- lib/yamlcpp/src/collectionstack.h | 6 +- lib/yamlcpp/src/contrib/graphbuilder.cpp | 2 +- .../src/contrib/graphbuilderadapter.cpp | 6 +- lib/yamlcpp/src/contrib/graphbuilderadapter.h | 16 +- lib/yamlcpp/src/contrib/yaml-cpp.natvis | 32 + lib/yamlcpp/src/contrib/yaml-cpp.natvis.md | 9 + lib/yamlcpp/src/directives.cpp | 9 +- lib/yamlcpp/src/emitfromevents.cpp | 7 +- lib/yamlcpp/src/emitter.cpp | 10 +- lib/yamlcpp/src/emitterstate.cpp | 44 +- lib/yamlcpp/src/emitterstate.h | 9 +- lib/yamlcpp/src/emitterutils.cpp | 28 +- lib/yamlcpp/src/exceptions.cpp | 2 +- lib/yamlcpp/src/exp.h | 60 +- lib/yamlcpp/src/node_data.cpp | 32 +- lib/yamlcpp/src/nodebuilder.cpp | 11 +- lib/yamlcpp/src/nodebuilder.h | 6 +- lib/yamlcpp/src/nodeevents.cpp | 4 +- lib/yamlcpp/src/nodeevents.h | 8 +- lib/yamlcpp/src/ostream_wrapper.cpp | 11 +- lib/yamlcpp/src/parser.cpp | 6 +- lib/yamlcpp/src/ptr_vector.h | 12 +- lib/yamlcpp/src/regex_yaml.cpp | 20 +- lib/yamlcpp/src/regex_yaml.h | 13 +- lib/yamlcpp/src/scanner.cpp | 13 +- lib/yamlcpp/src/scanner.h | 2 +- lib/yamlcpp/src/scanscalar.cpp | 2 +- lib/yamlcpp/src/scantoken.cpp | 4 +- lib/yamlcpp/src/setting.h | 24 +- lib/yamlcpp/src/simplekey.cpp | 2 +- lib/yamlcpp/src/singledocparser.cpp | 26 +- lib/yamlcpp/src/singledocparser.h | 14 +- lib/yamlcpp/src/stream.cpp | 32 +- lib/yamlcpp/src/stream.h | 9 +- lib/yamlcpp/src/streamcharsource.h | 8 +- lib/yamlcpp/src/tag.cpp | 5 +- lib/yamlcpp/src/token.h | 13 +- lib/yamlcpp/test/CMakeLists.txt | 73 +- lib/yamlcpp/test/create-emitter-tests.py | 28 +- lib/yamlcpp/test/integration/emitter_test.cpp | 67 +- .../test/integration/error_messages_test.cpp | 61 + .../test/integration/gen_emitter_test.cpp | 1177 ++++++++++------- .../test/integration/handler_spec_test.cpp | 14 +- .../test/integration/load_node_test.cpp | 22 +- lib/yamlcpp/test/mock_event_handler.h | 3 +- lib/yamlcpp/test/node/node_test.cpp | 130 +- lib/yamlcpp/test/regex_test.cpp | 18 +- lib/yamlcpp/util/CMakeLists.txt | 18 +- 70 files changed, 1687 insertions(+), 1017 deletions(-) delete mode 100644 lib/yamlcpp/include/yaml-cpp/noncopyable.h create mode 100644 lib/yamlcpp/src/contrib/yaml-cpp.natvis create mode 100644 lib/yamlcpp/src/contrib/yaml-cpp.natvis.md create mode 100644 lib/yamlcpp/test/integration/error_messages_test.cpp diff --git a/lib/yamlcpp/.gitignore b/lib/yamlcpp/.gitignore index 567609b1234..0e29154b528 100644 --- a/lib/yamlcpp/.gitignore +++ b/lib/yamlcpp/.gitignore @@ -1 +1,2 @@ build/ +/tags diff --git a/lib/yamlcpp/CMakeLists.txt b/lib/yamlcpp/CMakeLists.txt index d2d88102880..4732a453f10 100644 --- a/lib/yamlcpp/CMakeLists.txt +++ b/lib/yamlcpp/CMakeLists.txt @@ -1,38 +1,15 @@ ### ### CMake settings ### -## Due to Mac OSX we need to keep compatibility with CMake 2.6 # see http://www.cmake.org/Wiki/CMake_Policies -cmake_minimum_required(VERSION 2.6) -# see http://www.cmake.org/cmake/help/cmake-2-8-docs.html#policy:CMP0012 -if(POLICY CMP0012) - cmake_policy(SET CMP0012 OLD) -endif() -# see http://www.cmake.org/cmake/help/cmake-2-8-docs.html#policy:CMP0015 -if(POLICY CMP0015) - cmake_policy(SET CMP0015 OLD) -endif() -# see https://cmake.org/cmake/help/latest/policy/CMP0042.html -if(POLICY CMP0042) - # Enable MACOSX_RPATH by default. - cmake_policy(SET CMP0042 NEW) -endif() +cmake_minimum_required(VERSION 3.1) include(CheckCXXCompilerFlag) - ### ### Project settings ### -project(YAML_CPP) - -set(YAML_CPP_VERSION_MAJOR "0") -set(YAML_CPP_VERSION_MINOR "6") -set(YAML_CPP_VERSION_PATCH "2") -set(YAML_CPP_VERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}.${YAML_CPP_VERSION_PATCH}") - -enable_testing() - +project(YAML_CPP VERSION 0.6.3) ### ### Project options @@ -41,21 +18,26 @@ enable_testing() option(YAML_CPP_BUILD_TESTS "Enable testing" ON) option(YAML_CPP_BUILD_TOOLS "Enable parse tools" ON) option(YAML_CPP_BUILD_CONTRIB "Enable contrib stuff in library" ON) +option(YAML_CPP_INSTALL "Enable generation of install target" ON) ## Build options # --> General # see http://www.cmake.org/cmake/help/cmake2.6docs.html#variable:BUILD_SHARED_LIBS # http://www.cmake.org/cmake/help/cmake2.6docs.html#command:add_library -option(BUILD_SHARED_LIBS "Build Shared Libraries" OFF) +option(YAML_BUILD_SHARED_LIBS "Build Shared Libraries" OFF) # --> Apple -option(APPLE_UNIVERSAL_BIN "Apple: Build universal binary" OFF) +if(APPLE) + option(YAML_APPLE_UNIVERSAL_BIN "Apple: Build universal binary" OFF) +endif() # --> Microsoft Visual C++ # see http://msdn.microsoft.com/en-us/library/aa278396(v=VS.60).aspx # http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=VS.71).aspx -option(MSVC_SHARED_RT "MSVC: Build with shared runtime libs (/MD)" ON) -option(MSVC_STHREADED_RT "MSVC: Build with single-threaded static runtime libs (/ML until VS .NET 2003)" OFF) +if(MSVC) + option(YAML_MSVC_SHARED_RT "MSVC: Build with shared runtime libs (/MD)" ON) + option(YAML_MSVC_STHREADED_RT "MSVC: Build with single-threaded static runtime libs (/ML until VS .NET 2003)" OFF) +endif() ### ### Sources, headers, directories and libs @@ -116,9 +98,10 @@ if(VERBOSE) message(STATUS "contrib_private_headers: ${contrib_private_headers}") endif() -include_directories(${YAML_CPP_SOURCE_DIR}/src) -include_directories(${YAML_CPP_SOURCE_DIR}/include) - +if (CMAKE_VERSION VERSION_LESS 2.8.12) + include_directories(${YAML_CPP_SOURCE_DIR}/src) + include_directories(${YAML_CPP_SOURCE_DIR}/include) +endif() ### @@ -127,14 +110,14 @@ include_directories(${YAML_CPP_SOURCE_DIR}/include) set(yaml_c_flags ${CMAKE_C_FLAGS}) set(yaml_cxx_flags ${CMAKE_CXX_FLAGS}) -if(BUILD_SHARED_LIBS) +if(YAML_BUILD_SHARED_LIBS) set(LABEL_SUFFIX "shared") else() set(LABEL_SUFFIX "static") endif() if(APPLE) - if(APPLE_UNIVERSAL_BIN) + if(YAML_APPLE_UNIVERSAL_BIN) set(CMAKE_OSX_ARCHITECTURES ppc;i386) endif() endif() @@ -145,7 +128,7 @@ if(IPHONE) endif() if(WIN32) - if(BUILD_SHARED_LIBS) + if(YAML_BUILD_SHARED_LIBS) add_definitions(-D${PROJECT_NAME}_DLL) # use or build Windows DLL endif() if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) @@ -155,7 +138,7 @@ endif() # GCC or Clang or Intel Compiler specialities if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR - CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR + (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") OR CMAKE_CXX_COMPILER_ID MATCHES "Intel") ### General stuff @@ -170,32 +153,27 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR set(CMAKE_BUILD_TYPE Release) endif() # - set(CMAKE_CXX_FLAGS_RELEASE "-O2") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g") - set(CMAKE_CXX_FLAGS_DEBUG "-g") - set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os") - # set(GCC_EXTRA_OPTIONS "") # - if(BUILD_SHARED_LIBS) + if(YAML_BUILD_SHARED_LIBS) set(GCC_EXTRA_OPTIONS "${GCC_EXTRA_OPTIONS} -fPIC") endif() # - set(FLAG_TESTED "-Wextra") + set(FLAG_TESTED "-Wextra -Wshadow -Weffc++ -pedantic -pedantic-errors") check_cxx_compiler_flag(${FLAG_TESTED} FLAG_WEXTRA) if(FLAG_WEXTRA) set(GCC_EXTRA_OPTIONS "${GCC_EXTRA_OPTIONS} ${FLAG_TESTED}") endif() # - set(yaml_cxx_flags "-Wall ${GCC_EXTRA_OPTIONS} -pedantic -Wno-long-long -std=c++11 ${yaml_cxx_flags}") + set(yaml_cxx_flags "-Wall ${GCC_EXTRA_OPTIONS} -pedantic -Wno-long-long ${yaml_cxx_flags}") ### Make specific if(${CMAKE_BUILD_TOOL} MATCHES make OR ${CMAKE_BUILD_TOOL} MATCHES gmake) - add_custom_target(debuggable $(MAKE) clean + add_custom_target(debuggable ${CMAKE_MAKE_PROGRAM} clean COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${CMAKE_SOURCE_DIR} COMMENT "Adjusting settings for debug compilation" VERBATIM) - add_custom_target(releasable $(MAKE) clean + add_custom_target(releasable ${CMAKE_MAKE_PROGRAM} clean COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Release ${CMAKE_SOURCE_DIR} COMMENT "Adjusting settings for release compilation" VERBATIM) @@ -212,8 +190,8 @@ if(MSVC) set(LIB_RT_SUFFIX "md") # CMake defaults to /MD for MSVC set(LIB_RT_OPTION "/MD") # - if(NOT MSVC_SHARED_RT) # User wants to have static runtime libraries (/MT, /ML) - if(MSVC_STHREADED_RT) # User wants to have old single-threaded static runtime libraries + if(NOT YAML_MSVC_SHARED_RT) # User wants to have static runtime libraries (/MT, /ML) + if(YAML_MSVC_STHREADED_RT) # User wants to have old single-threaded static runtime libraries set(LIB_RT_SUFFIX "ml") set(LIB_RT_OPTION "/ML") if(NOT ${MSVC_VERSION} LESS 1400) @@ -243,7 +221,7 @@ if(MSVC) set(CMAKE_STATIC_LIBRARY_PREFIX "lib") # to distinguish static libraries from DLL import libs # c) Correct suffixes for static libraries - if(NOT BUILD_SHARED_LIBS) + if(NOT YAML_BUILD_SHARED_LIBS) ### General stuff set(LIB_TARGET_SUFFIX "${LIB_SUFFIX}${LIB_RT_SUFFIX}") endif() @@ -274,7 +252,24 @@ set(_INSTALL_DESTINATIONS ### ### Library ### -add_library(yaml-cpp ${library_sources}) +if(YAML_BUILD_SHARED_LIBS) + add_library(yaml-cpp SHARED ${library_sources}) +else() + add_library(yaml-cpp STATIC ${library_sources}) +endif() + +if (NOT CMAKE_VERSION VERSION_LESS 2.8.12) + target_include_directories(yaml-cpp + PUBLIC $ + $ + PRIVATE $) +endif() + +set_target_properties(yaml-cpp PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED ON +) + set_target_properties(yaml-cpp PROPERTIES COMPILE_FLAGS "${yaml_c_flags} ${yaml_cxx_flags}" ) @@ -292,7 +287,7 @@ if(IPHONE) endif() if(MSVC) - if(NOT BUILD_SHARED_LIBS) + if(NOT YAML_BUILD_SHARED_LIBS) # correct library names set_target_properties(yaml-cpp PROPERTIES DEBUG_POSTFIX "${LIB_TARGET_SUFFIX}d" @@ -303,12 +298,14 @@ if(MSVC) endif() endif() -install(TARGETS yaml-cpp EXPORT yaml-cpp-targets ${_INSTALL_DESTINATIONS}) -install( - DIRECTORY ${header_directory} - DESTINATION ${INCLUDE_INSTALL_DIR} - FILES_MATCHING PATTERN "*.h" -) +if (YAML_CPP_INSTALL) + install(TARGETS yaml-cpp EXPORT yaml-cpp-targets ${_INSTALL_DESTINATIONS}) + install( + DIRECTORY ${header_directory} + DESTINATION ${INCLUDE_INSTALL_DIR} + FILES_MATCHING PATTERN "*.h" + ) +endif() export( TARGETS yaml-cpp @@ -326,6 +323,7 @@ else() set(INSTALL_CMAKE_DIR ${LIB_INSTALL_DIR}/cmake/yaml-cpp) endif() + file(RELATIVE_PATH REL_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_CMAKE_DIR}" "${CMAKE_INSTALL_PREFIX}/${INCLUDE_INSTALL_ROOT_DIR}") set(CONFIG_INCLUDE_DIRS "\${YAML_CPP_CMAKE_DIR}/${REL_INCLUDE_DIR}") configure_file(${CMAKE_CURRENT_SOURCE_DIR}/yaml-cpp-config.cmake.in @@ -334,16 +332,19 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/yaml-cpp-config.cmake.in configure_file(${CMAKE_CURRENT_SOURCE_DIR}/yaml-cpp-config-version.cmake.in "${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake" @ONLY) -install(FILES - "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/yaml-cpp-config.cmake" - "${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake" - DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev) -install(EXPORT yaml-cpp-targets DESTINATION ${INSTALL_CMAKE_DIR}) +if (YAML_CPP_INSTALL) + install(FILES + "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/yaml-cpp-config.cmake" + "${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake" + DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev) + install(EXPORT yaml-cpp-targets DESTINATION ${INSTALL_CMAKE_DIR}) + + if(UNIX) + set(PC_FILE ${CMAKE_BINARY_DIR}/yaml-cpp.pc) + configure_file("yaml-cpp.pc.cmake" ${PC_FILE} @ONLY) + install(FILES ${PC_FILE} DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) + endif() -if(UNIX) - set(PC_FILE ${CMAKE_BINARY_DIR}/yaml-cpp.pc) - configure_file("yaml-cpp.pc.cmake" ${PC_FILE} @ONLY) - install(FILES ${PC_FILE} DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) endif() @@ -351,6 +352,7 @@ endif() ### Extras ### if(YAML_CPP_BUILD_TESTS) + enable_testing() add_subdirectory(test) endif() if(YAML_CPP_BUILD_TOOLS) diff --git a/lib/yamlcpp/README.md b/lib/yamlcpp/README.md index f33d3503a15..e793143af92 100644 --- a/lib/yamlcpp/README.md +++ b/lib/yamlcpp/README.md @@ -26,7 +26,7 @@ cd build 3. Run CMake. The basic syntax is: ``` -cmake [-G generator] [-DBUILD_SHARED_LIBS=ON|OFF] .. +cmake [-G generator] [-DYAML_BUILD_SHARED_LIBS=ON|OFF] .. ``` * The `generator` is whatever type of build system you'd like to use. To see a full list of generators on your platform, just run `cmake` (with no arguments). For example: @@ -34,7 +34,7 @@ cmake [-G generator] [-DBUILD_SHARED_LIBS=ON|OFF] .. * On OS X, you might use "Xcode" to generate an Xcode project * On a UNIX-y system, simply omit the option to generate a makefile - * yaml-cpp defaults to building a static library, but you may build a shared library by specifying `-DBUILD_SHARED_LIBS=ON`. + * yaml-cpp defaults to building a static library, but you may build a shared library by specifying `-DYAML_BUILD_SHARED_LIBS=ON`. * For more options on customizing the build, see the [CMakeLists.txt](https://github.com/jbeder/yaml-cpp/blob/master/CMakeLists.txt) file. diff --git a/lib/yamlcpp/include/yaml-cpp/binary.h b/lib/yamlcpp/include/yaml-cpp/binary.h index 29d5dbd027a..1050dae98c3 100644 --- a/lib/yamlcpp/include/yaml-cpp/binary.h +++ b/lib/yamlcpp/include/yaml-cpp/binary.h @@ -19,9 +19,13 @@ YAML_CPP_API std::vector DecodeBase64(const std::string &input); class YAML_CPP_API Binary { public: - Binary() : m_unownedData(0), m_unownedSize(0) {} Binary(const unsigned char *data_, std::size_t size_) - : m_unownedData(data_), m_unownedSize(size_) {} + : m_data{}, m_unownedData(data_), m_unownedSize(size_) {} + Binary() : Binary(nullptr, 0) {} + Binary(const Binary &) = default; + Binary(Binary &&) = default; + Binary &operator=(const Binary &) = default; + Binary &operator=(Binary &&) = default; bool owned() const { return !m_unownedData; } std::size_t size() const { return owned() ? m_data.size() : m_unownedSize; } @@ -35,7 +39,7 @@ class YAML_CPP_API Binary { rhs.clear(); rhs.resize(m_unownedSize); std::copy(m_unownedData, m_unownedData + m_unownedSize, rhs.begin()); - m_unownedData = 0; + m_unownedData = nullptr; m_unownedSize = 0; } else { m_data.swap(rhs); @@ -62,6 +66,6 @@ class YAML_CPP_API Binary { const unsigned char *m_unownedData; std::size_t m_unownedSize; }; -} +} // namespace YAML #endif // BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/lib/yamlcpp/include/yaml-cpp/contrib/anchordict.h b/lib/yamlcpp/include/yaml-cpp/contrib/anchordict.h index 78db9ec9288..1b7809b875f 100644 --- a/lib/yamlcpp/include/yaml-cpp/contrib/anchordict.h +++ b/lib/yamlcpp/include/yaml-cpp/contrib/anchordict.h @@ -22,6 +22,7 @@ namespace YAML { template class AnchorDict { public: + AnchorDict() : m_data{} {} void Register(anchor_t anchor, T value) { if (anchor > m_data.size()) { m_data.resize(anchor); @@ -34,6 +35,6 @@ class AnchorDict { private: std::vector m_data; }; -} +} // namespace YAML #endif // ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/lib/yamlcpp/include/yaml-cpp/emitter.h b/lib/yamlcpp/include/yaml-cpp/emitter.h index ef92cc4035b..6f142b01160 100644 --- a/lib/yamlcpp/include/yaml-cpp/emitter.h +++ b/lib/yamlcpp/include/yaml-cpp/emitter.h @@ -7,16 +7,18 @@ #pragma once #endif +#include #include +#include #include #include #include +#include #include "yaml-cpp/binary.h" #include "yaml-cpp/dll.h" #include "yaml-cpp/emitterdef.h" #include "yaml-cpp/emittermanip.h" -#include "yaml-cpp/noncopyable.h" #include "yaml-cpp/null.h" #include "yaml-cpp/ostream_wrapper.h" @@ -28,10 +30,12 @@ struct _Null; namespace YAML { class EmitterState; -class YAML_CPP_API Emitter : private noncopyable { +class YAML_CPP_API Emitter { public: Emitter(); explicit Emitter(std::ostream& stream); + Emitter(const Emitter&) = delete; + Emitter& operator=(const Emitter&) = delete; ~Emitter(); // output @@ -152,7 +156,28 @@ inline Emitter& Emitter::WriteStreamable(T value) { std::stringstream stream; SetStreamablePrecision(stream); - stream << value; + + bool special = false; + if (std::is_floating_point::value) { + if ((std::numeric_limits::has_quiet_NaN || + std::numeric_limits::has_signaling_NaN) && + std::isnan(value)) { + special = true; + stream << ".nan"; + } else if (std::numeric_limits::has_infinity) { + if (value == std::numeric_limits::infinity()) { + special = true; + stream << ".inf"; + } else if (value == -std::numeric_limits::infinity()) { + special = true; + stream << "-.inf"; + } + } + } + + if (!special) { + stream << value; + } m_stream << stream.str(); StartedScalar(); @@ -249,6 +274,6 @@ inline Emitter& operator<<(Emitter& emitter, _Indent indent) { inline Emitter& operator<<(Emitter& emitter, _Precision precision) { return emitter.SetLocalPrecision(precision); } -} +} // namespace YAML #endif // EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/lib/yamlcpp/include/yaml-cpp/eventhandler.h b/lib/yamlcpp/include/yaml-cpp/eventhandler.h index efe381c6218..29718ffa1f9 100644 --- a/lib/yamlcpp/include/yaml-cpp/eventhandler.h +++ b/lib/yamlcpp/include/yaml-cpp/eventhandler.h @@ -34,7 +34,12 @@ class EventHandler { virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor, EmitterStyle::value style) = 0; virtual void OnMapEnd() = 0; + + virtual void OnAnchor(const Mark& /*mark*/, + const std::string& /*anchor_name*/) { + // empty default implementation for compatibility + } }; -} +} // namespace YAML #endif // EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/lib/yamlcpp/include/yaml-cpp/exceptions.h b/lib/yamlcpp/include/yaml-cpp/exceptions.h index 9c96859b2c9..eef22833a81 100644 --- a/lib/yamlcpp/include/yaml-cpp/exceptions.h +++ b/lib/yamlcpp/include/yaml-cpp/exceptions.h @@ -15,7 +15,7 @@ // This is here for compatibility with older versions of Visual Studio // which don't support noexcept -#ifdef _MSC_VER +#if defined(_MSC_VER) && _MSC_VER < 1900 #define YAML_CPP_NOEXCEPT _NOEXCEPT #else #define YAML_CPP_NOEXCEPT noexcept @@ -114,6 +114,35 @@ inline const std::string KEY_NOT_FOUND_WITH_KEY( stream << KEY_NOT_FOUND << ": " << key; return stream.str(); } + +template +inline const std::string BAD_SUBSCRIPT_WITH_KEY( + const T&, typename disable_if>::type* = nullptr) { + return BAD_SUBSCRIPT; +} + +inline const std::string BAD_SUBSCRIPT_WITH_KEY(const std::string& key) { + std::stringstream stream; + stream << BAD_SUBSCRIPT << " (key: \"" << key << "\")"; + return stream.str(); +} + +template +inline const std::string BAD_SUBSCRIPT_WITH_KEY( + const T& key, typename enable_if>::type* = nullptr) { + std::stringstream stream; + stream << BAD_SUBSCRIPT << " (key: \"" << key << "\")"; + return stream.str(); +} + +inline const std::string INVALID_NODE_WITH_KEY(const std::string& key) { + std::stringstream stream; + if (key.empty()) { + return INVALID_NODE; + } + stream << "invalid node; first invalid key: \"" << key << "\""; + return stream.str(); +} } class YAML_CPP_API Exception : public std::runtime_error { @@ -131,7 +160,7 @@ class YAML_CPP_API Exception : public std::runtime_error { static const std::string build_what(const Mark& mark, const std::string& msg) { if (mark.is_null()) { - return msg.c_str(); + return msg; } std::stringstream output; @@ -194,8 +223,9 @@ inline TypedKeyNotFound MakeTypedKeyNotFound(const Mark& mark, class YAML_CPP_API InvalidNode : public RepresentationException { public: - InvalidNode() - : RepresentationException(Mark::null_mark(), ErrorMsg::INVALID_NODE) {} + InvalidNode(std::string key) + : RepresentationException(Mark::null_mark(), + ErrorMsg::INVALID_NODE_WITH_KEY(key)) {} InvalidNode(const InvalidNode&) = default; virtual ~InvalidNode() YAML_CPP_NOEXCEPT; }; @@ -224,8 +254,10 @@ class YAML_CPP_API BadDereference : public RepresentationException { class YAML_CPP_API BadSubscript : public RepresentationException { public: - BadSubscript() - : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_SUBSCRIPT) {} + template + BadSubscript(const Key& key) + : RepresentationException(Mark::null_mark(), + ErrorMsg::BAD_SUBSCRIPT_WITH_KEY(key)) {} BadSubscript(const BadSubscript&) = default; virtual ~BadSubscript() YAML_CPP_NOEXCEPT; }; diff --git a/lib/yamlcpp/include/yaml-cpp/node/convert.h b/lib/yamlcpp/include/yaml-cpp/node/convert.h index 45a878ab0c0..d61b73d09db 100644 --- a/lib/yamlcpp/include/yaml-cpp/node/convert.h +++ b/lib/yamlcpp/include/yaml-cpp/node/convert.h @@ -93,7 +93,7 @@ struct convert<_Null> { struct convert { \ static Node encode(const type& rhs) { \ std::stringstream stream; \ - stream.precision(std::numeric_limits::digits10 + 1); \ + stream.precision(std::numeric_limits::max_digits10); \ stream << rhs; \ return Node(stream.str()); \ } \ @@ -116,10 +116,11 @@ struct convert<_Null> { } \ } \ \ - if (std::numeric_limits::has_quiet_NaN && \ - conversion::IsNaN(input)) { \ - rhs = std::numeric_limits::quiet_NaN(); \ - return true; \ + if (std::numeric_limits::has_quiet_NaN) { \ + if (conversion::IsNaN(input)) { \ + rhs = std::numeric_limits::quiet_NaN(); \ + return true; \ + } \ } \ \ return false; \ diff --git a/lib/yamlcpp/include/yaml-cpp/node/detail/impl.h b/lib/yamlcpp/include/yaml-cpp/node/detail/impl.h index 09e55f838c2..4123b85da54 100644 --- a/lib/yamlcpp/include/yaml-cpp/node/detail/impl.h +++ b/lib/yamlcpp/include/yaml-cpp/node/detail/impl.h @@ -17,7 +17,7 @@ template struct get_idx { static node* get(const std::vector& /* sequence */, const Key& /* key */, shared_memory_holder /* pMemory */) { - return 0; + return nullptr; } }; @@ -27,12 +27,12 @@ struct get_idx::value>::type> { static node* get(const std::vector& sequence, const Key& key, shared_memory_holder /* pMemory */) { - return key < sequence.size() ? sequence[key] : 0; + return key < sequence.size() ? sequence[key] : nullptr; } static node* get(std::vector& sequence, const Key& key, shared_memory_holder pMemory) { - if (key > sequence.size() || (key > 0 && !sequence[key-1]->is_defined())) + if (key > sequence.size() || (key > 0 && !sequence[key - 1]->is_defined())) return 0; if (key == sequence.size()) sequence.push_back(&pMemory->create_node()); @@ -46,13 +46,44 @@ struct get_idx::value>::type> { shared_memory_holder pMemory) { return key >= 0 ? get_idx::get( sequence, static_cast(key), pMemory) - : 0; + : nullptr; } static node* get(std::vector& sequence, const Key& key, shared_memory_holder pMemory) { return key >= 0 ? get_idx::get( sequence, static_cast(key), pMemory) - : 0; + : nullptr; + } +}; + +template +struct remove_idx { + static bool remove(std::vector&, const Key&) { return false; } +}; + +template +struct remove_idx< + Key, typename std::enable_if::value && + !std::is_same::value>::type> { + + static bool remove(std::vector& sequence, const Key& key) { + if (key >= sequence.size()) { + return false; + } else { + sequence.erase(sequence.begin() + key); + return true; + } + } +}; + +template +struct remove_idx::value>::type> { + + static bool remove(std::vector& sequence, const Key& key) { + return key >= 0 ? remove_idx::remove( + sequence, static_cast(key)) + : false; } }; @@ -78,13 +109,13 @@ inline node* node_data::get(const Key& key, break; case NodeType::Undefined: case NodeType::Null: - return NULL; + return nullptr; case NodeType::Sequence: if (node* pNode = get_idx::get(m_sequence, key, pMemory)) return pNode; - return NULL; + return nullptr; case NodeType::Scalar: - throw BadSubscript(); + throw BadSubscript(key); } for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) { @@ -93,7 +124,7 @@ inline node* node_data::get(const Key& key, } } - return NULL; + return nullptr; } template @@ -112,7 +143,7 @@ inline node& node_data::get(const Key& key, shared_memory_holder pMemory) { convert_to_map(pMemory); break; case NodeType::Scalar: - throw BadSubscript(); + throw BadSubscript(key); } for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) { @@ -129,21 +160,23 @@ inline node& node_data::get(const Key& key, shared_memory_holder pMemory) { template inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) { - if (m_type != NodeType::Map) - return false; - - for (kv_pairs::iterator it = m_undefinedPairs.begin(); - it != m_undefinedPairs.end();) { - kv_pairs::iterator jt = std::next(it); - if (it->first->equals(key, pMemory)) - m_undefinedPairs.erase(it); - it = jt; - } + if (m_type == NodeType::Sequence) { + return remove_idx::remove(m_sequence, key); + } else if (m_type == NodeType::Map) { + kv_pairs::iterator it = m_undefinedPairs.begin(); + while (it != m_undefinedPairs.end()) { + kv_pairs::iterator jt = std::next(it); + if (it->first->equals(key, pMemory)) { + m_undefinedPairs.erase(it); + } + it = jt; + } - for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) { - if (it->first->equals(key, pMemory)) { - m_map.erase(it); - return true; + for (node_map::iterator iter = m_map.begin(); iter != m_map.end(); ++iter) { + if (iter->first->equals(key, pMemory)) { + m_map.erase(iter); + return true; + } } } diff --git a/lib/yamlcpp/include/yaml-cpp/node/detail/iterator.h b/lib/yamlcpp/include/yaml-cpp/node/detail/iterator.h index deec8fb62cd..966107d959d 100644 --- a/lib/yamlcpp/include/yaml-cpp/node/detail/iterator.h +++ b/lib/yamlcpp/include/yaml-cpp/node/detail/iterator.h @@ -8,19 +8,19 @@ #endif #include "yaml-cpp/dll.h" +#include "yaml-cpp/node/detail/node_iterator.h" #include "yaml-cpp/node/node.h" #include "yaml-cpp/node/ptr.h" -#include "yaml-cpp/node/detail/node_iterator.h" #include #include + namespace YAML { namespace detail { struct iterator_value; template -class iterator_base : public std::iterator { +class iterator_base { private: template @@ -37,7 +37,11 @@ class iterator_base : public std::iterator namespace YAML { namespace detail { class node { public: - node() : m_pRef(new node_ref) {} + node() : m_pRef(new node_ref), m_dependencies{} {} node(const node&) = delete; node& operator=(const node&) = delete; @@ -163,7 +163,7 @@ class node { typedef std::set nodes; nodes m_dependencies; }; -} -} +} // namespace detail +} // namespace YAML #endif // NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/lib/yamlcpp/include/yaml-cpp/node/detail/node_data.h b/lib/yamlcpp/include/yaml-cpp/node/detail/node_data.h index 50bcd74352d..82fb79adef9 100644 --- a/lib/yamlcpp/include/yaml-cpp/node/detail/node_data.h +++ b/lib/yamlcpp/include/yaml-cpp/node/detail/node_data.h @@ -81,7 +81,7 @@ class YAML_CPP_API node_data { shared_memory_holder pMemory); public: - static std::string empty_scalar; + static const std::string& empty_scalar(); private: void compute_seq_size() const; diff --git a/lib/yamlcpp/include/yaml-cpp/node/detail/node_iterator.h b/lib/yamlcpp/include/yaml-cpp/node/detail/node_iterator.h index 088090fe743..ab6916fea47 100644 --- a/lib/yamlcpp/include/yaml-cpp/node/detail/node_iterator.h +++ b/lib/yamlcpp/include/yaml-cpp/node/detail/node_iterator.h @@ -26,9 +26,9 @@ template struct node_iterator_value : public std::pair { typedef std::pair kv; - node_iterator_value() : kv(), pNode(0) {} + node_iterator_value() : kv(), pNode(nullptr) {} explicit node_iterator_value(V& rhs) : kv(), pNode(&rhs) {} - explicit node_iterator_value(V& key, V& value) : kv(&key, &value), pNode(0) {} + explicit node_iterator_value(V& key, V& value) : kv(&key, &value), pNode(nullptr) {} V& operator*() const { return *pNode; } V& operator->() const { return *pNode; } diff --git a/lib/yamlcpp/include/yaml-cpp/node/impl.h b/lib/yamlcpp/include/yaml-cpp/node/impl.h index 20c487a687f..7a3deacf906 100644 --- a/lib/yamlcpp/include/yaml-cpp/node/impl.h +++ b/lib/yamlcpp/include/yaml-cpp/node/impl.h @@ -7,18 +7,21 @@ #pragma once #endif -#include "yaml-cpp/node/node.h" -#include "yaml-cpp/node/iterator.h" +#include "yaml-cpp/exceptions.h" #include "yaml-cpp/node/detail/memory.h" #include "yaml-cpp/node/detail/node.h" -#include "yaml-cpp/exceptions.h" +#include "yaml-cpp/node/iterator.h" +#include "yaml-cpp/node/node.h" +#include #include namespace YAML { -inline Node::Node() : m_isValid(true), m_pNode(NULL) {} +inline Node::Node() + : m_isValid(true), m_invalidKey{}, m_pMemory(nullptr), m_pNode(nullptr) {} inline Node::Node(NodeType::value type) : m_isValid(true), + m_invalidKey{}, m_pMemory(new detail::memory_holder), m_pNode(&m_pMemory->create_node()) { m_pNode->set_type(type); @@ -27,6 +30,7 @@ inline Node::Node(NodeType::value type) template inline Node::Node(const T& rhs) : m_isValid(true), + m_invalidKey{}, m_pMemory(new detail::memory_holder), m_pNode(&m_pMemory->create_node()) { Assign(rhs); @@ -34,24 +38,30 @@ inline Node::Node(const T& rhs) inline Node::Node(const detail::iterator_value& rhs) : m_isValid(rhs.m_isValid), + m_invalidKey(rhs.m_invalidKey), m_pMemory(rhs.m_pMemory), m_pNode(rhs.m_pNode) {} inline Node::Node(const Node& rhs) : m_isValid(rhs.m_isValid), + m_invalidKey(rhs.m_invalidKey), m_pMemory(rhs.m_pMemory), m_pNode(rhs.m_pNode) {} -inline Node::Node(Zombie) : m_isValid(false), m_pNode(NULL) {} +inline Node::Node(Zombie) + : m_isValid(false), m_invalidKey{}, m_pMemory{}, m_pNode(nullptr) {} + +inline Node::Node(Zombie, const std::string& key) + : m_isValid(false), m_invalidKey(key), m_pMemory{}, m_pNode(nullptr) {} inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory) - : m_isValid(true), m_pMemory(pMemory), m_pNode(&node) {} + : m_isValid(true), m_invalidKey{}, m_pMemory(pMemory), m_pNode(&node) {} inline Node::~Node() {} inline void Node::EnsureNodeExists() const { if (!m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); if (!m_pNode) { m_pMemory.reset(new detail::memory_holder); m_pNode = &m_pMemory->create_node(); @@ -68,14 +78,14 @@ inline bool Node::IsDefined() const { inline Mark Node::Mark() const { if (!m_isValid) { - throw InvalidNode(); + throw InvalidNode(m_invalidKey); } return m_pNode ? m_pNode->mark() : Mark::null_mark(); } inline NodeType::value Node::Type() const { if (!m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); return m_pNode ? m_pNode->type() : NodeType::Null; } @@ -142,7 +152,7 @@ struct as_if { template inline T Node::as() const { if (!m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); return as_if(*this)(); } @@ -155,32 +165,32 @@ inline T Node::as(const S& fallback) const { inline const std::string& Node::Scalar() const { if (!m_isValid) - throw InvalidNode(); - return m_pNode ? m_pNode->scalar() : detail::node_data::empty_scalar; + throw InvalidNode(m_invalidKey); + return m_pNode ? m_pNode->scalar() : detail::node_data::empty_scalar(); } inline const std::string& Node::Tag() const { if (!m_isValid) - throw InvalidNode(); - return m_pNode ? m_pNode->tag() : detail::node_data::empty_scalar; + throw InvalidNode(m_invalidKey); + return m_pNode ? m_pNode->tag() : detail::node_data::empty_scalar(); } inline void Node::SetTag(const std::string& tag) { if (!m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); EnsureNodeExists(); m_pNode->set_tag(tag); } inline EmitterStyle::value Node::Style() const { if (!m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); return m_pNode ? m_pNode->style() : EmitterStyle::Default; } inline void Node::SetStyle(EmitterStyle::value style) { if (!m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); EnsureNodeExists(); m_pNode->set_style(style); } @@ -188,7 +198,7 @@ inline void Node::SetStyle(EmitterStyle::value style) { // assignment inline bool Node::is(const Node& rhs) const { if (!m_isValid || !rhs.m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); if (!m_pNode || !rhs.m_pNode) return false; return m_pNode->is(*rhs.m_pNode); @@ -197,14 +207,23 @@ inline bool Node::is(const Node& rhs) const { template inline Node& Node::operator=(const T& rhs) { if (!m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); Assign(rhs); return *this; } +inline Node& Node::operator=(const Node& rhs) { + if (!m_isValid || !rhs.m_isValid) + throw InvalidNode(m_invalidKey); + if (is(rhs)) + return *this; + AssignNode(rhs); + return *this; +} + inline void Node::reset(const YAML::Node& rhs) { if (!m_isValid || !rhs.m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); m_pMemory = rhs.m_pMemory; m_pNode = rhs.m_pNode; } @@ -212,44 +231,35 @@ inline void Node::reset(const YAML::Node& rhs) { template inline void Node::Assign(const T& rhs) { if (!m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); AssignData(convert::encode(rhs)); } template <> inline void Node::Assign(const std::string& rhs) { if (!m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); EnsureNodeExists(); m_pNode->set_scalar(rhs); } inline void Node::Assign(const char* rhs) { if (!m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); EnsureNodeExists(); m_pNode->set_scalar(rhs); } inline void Node::Assign(char* rhs) { if (!m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); EnsureNodeExists(); m_pNode->set_scalar(rhs); } -inline Node& Node::operator=(const Node& rhs) { - if (!m_isValid || !rhs.m_isValid) - throw InvalidNode(); - if (is(rhs)) - return *this; - AssignNode(rhs); - return *this; -} - inline void Node::AssignData(const Node& rhs) { if (!m_isValid || !rhs.m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); EnsureNodeExists(); rhs.EnsureNodeExists(); @@ -259,7 +269,7 @@ inline void Node::AssignData(const Node& rhs) { inline void Node::AssignNode(const Node& rhs) { if (!m_isValid || !rhs.m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); rhs.EnsureNodeExists(); if (!m_pNode) { @@ -276,7 +286,7 @@ inline void Node::AssignNode(const Node& rhs) { // size/iterator inline std::size_t Node::size() const { if (!m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); return m_pNode ? m_pNode->size() : 0; } @@ -309,13 +319,13 @@ inline iterator Node::end() { template inline void Node::push_back(const T& rhs) { if (!m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); push_back(Node(rhs)); } inline void Node::push_back(const Node& rhs) { if (!m_isValid || !rhs.m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); EnsureNodeExists(); rhs.EnsureNodeExists(); @@ -366,18 +376,23 @@ template inline typename to_value_t::return_type to_value(const T& t) { return to_value_t(t)(); } +} // namespace detail + +template +std::string key_to_string(const Key& key) { + return streamable_to_string::value>().impl(key); } // indexing template inline const Node Node::operator[](const Key& key) const { if (!m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); EnsureNodeExists(); - detail::node* value = static_cast(*m_pNode) - .get(detail::to_value(key), m_pMemory); + detail::node* value = static_cast(*m_pNode).get( + detail::to_value(key), m_pMemory); if (!value) { - return Node(ZombieNode); + return Node(ZombieNode, key_to_string(key)); } return Node(*value, m_pMemory); } @@ -385,7 +400,7 @@ inline const Node Node::operator[](const Key& key) const { template inline Node Node::operator[](const Key& key) { if (!m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); EnsureNodeExists(); detail::node& value = m_pNode->get(detail::to_value(key), m_pMemory); return Node(value, m_pMemory); @@ -394,28 +409,28 @@ inline Node Node::operator[](const Key& key) { template inline bool Node::remove(const Key& key) { if (!m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); EnsureNodeExists(); return m_pNode->remove(detail::to_value(key), m_pMemory); } inline const Node Node::operator[](const Node& key) const { if (!m_isValid || !key.m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); EnsureNodeExists(); key.EnsureNodeExists(); m_pMemory->merge(*key.m_pMemory); detail::node* value = static_cast(*m_pNode).get(*key.m_pNode, m_pMemory); if (!value) { - return Node(ZombieNode); + return Node(ZombieNode, key_to_string(key)); } return Node(*value, m_pMemory); } inline Node Node::operator[](const Node& key) { if (!m_isValid || !key.m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); EnsureNodeExists(); key.EnsureNodeExists(); m_pMemory->merge(*key.m_pMemory); @@ -425,7 +440,7 @@ inline Node Node::operator[](const Node& key) { inline bool Node::remove(const Node& key) { if (!m_isValid || !key.m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); EnsureNodeExists(); key.EnsureNodeExists(); return m_pNode->remove(*key.m_pNode, m_pMemory); @@ -435,7 +450,7 @@ inline bool Node::remove(const Node& key) { template inline void Node::force_insert(const Key& key, const Value& value) { if (!m_isValid) - throw InvalidNode(); + throw InvalidNode(m_invalidKey); EnsureNodeExists(); m_pNode->force_insert(detail::to_value(key), detail::to_value(value), m_pMemory); @@ -443,6 +458,6 @@ inline void Node::force_insert(const Key& key, const Value& value) { // free functions inline bool operator==(const Node& lhs, const Node& rhs) { return lhs.is(rhs); } -} +} // namespace YAML #endif // NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/lib/yamlcpp/include/yaml-cpp/node/node.h b/lib/yamlcpp/include/yaml-cpp/node/node.h index 1ded7d27b72..49af58e5c42 100644 --- a/lib/yamlcpp/include/yaml-cpp/node/node.h +++ b/lib/yamlcpp/include/yaml-cpp/node/node.h @@ -8,6 +8,7 @@ #endif #include +#include #include "yaml-cpp/dll.h" #include "yaml-cpp/emitterstyle.h" @@ -116,6 +117,7 @@ class YAML_CPP_API Node { private: enum Zombie { ZombieNode }; explicit Node(Zombie); + explicit Node(Zombie, const std::string&); explicit Node(detail::node& node, detail::shared_memory_holder pMemory); void EnsureNodeExists() const; @@ -130,6 +132,8 @@ class YAML_CPP_API Node { private: bool m_isValid; + // String representation of invalid key, if the node is invalid. + std::string m_invalidKey; mutable detail::shared_memory_holder m_pMemory; mutable detail::node* m_pNode; }; diff --git a/lib/yamlcpp/include/yaml-cpp/noncopyable.h b/lib/yamlcpp/include/yaml-cpp/noncopyable.h deleted file mode 100644 index a261040739b..00000000000 --- a/lib/yamlcpp/include/yaml-cpp/noncopyable.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#define NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 - -#if defined(_MSC_VER) || \ - (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ - (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 -#pragma once -#endif - -#include "yaml-cpp/dll.h" - -namespace YAML { -// this is basically boost::noncopyable -class YAML_CPP_API noncopyable { - protected: - noncopyable() {} - ~noncopyable() {} - - private: - noncopyable(const noncopyable&); - const noncopyable& operator=(const noncopyable&); -}; -} - -#endif // NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/lib/yamlcpp/include/yaml-cpp/ostream_wrapper.h b/lib/yamlcpp/include/yaml-cpp/ostream_wrapper.h index 09d45f39b78..cf89741d093 100644 --- a/lib/yamlcpp/include/yaml-cpp/ostream_wrapper.h +++ b/lib/yamlcpp/include/yaml-cpp/ostream_wrapper.h @@ -17,6 +17,10 @@ class YAML_CPP_API ostream_wrapper { public: ostream_wrapper(); explicit ostream_wrapper(std::ostream& stream); + ostream_wrapper(const ostream_wrapper&) = delete; + ostream_wrapper(ostream_wrapper&&) = delete; + ostream_wrapper& operator=(const ostream_wrapper&) = delete; + ostream_wrapper& operator=(ostream_wrapper&&) = delete; ~ostream_wrapper(); void write(const std::string& str); @@ -26,7 +30,7 @@ class YAML_CPP_API ostream_wrapper { const char* str() const { if (m_pStream) { - return 0; + return nullptr; } else { m_buffer[m_pos] = '\0'; return &m_buffer[0]; @@ -52,7 +56,7 @@ class YAML_CPP_API ostream_wrapper { template inline ostream_wrapper& operator<<(ostream_wrapper& stream, - const char(&str)[N]) { + const char (&str)[N]) { stream.write(str, N - 1); return stream; } @@ -67,6 +71,6 @@ inline ostream_wrapper& operator<<(ostream_wrapper& stream, char ch) { stream.write(&ch, 1); return stream; } -} +} // namespace YAML #endif // OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/lib/yamlcpp/include/yaml-cpp/parser.h b/lib/yamlcpp/include/yaml-cpp/parser.h index ceac22d0268..2f403c35048 100644 --- a/lib/yamlcpp/include/yaml-cpp/parser.h +++ b/lib/yamlcpp/include/yaml-cpp/parser.h @@ -11,7 +11,6 @@ #include #include "yaml-cpp/dll.h" -#include "yaml-cpp/noncopyable.h" namespace YAML { class EventHandler; @@ -24,11 +23,16 @@ struct Token; * A parser turns a stream of bytes into one stream of "events" per YAML * document in the input stream. */ -class YAML_CPP_API Parser : private noncopyable { +class YAML_CPP_API Parser { public: /** Constructs an empty parser (with no input. */ Parser(); + Parser(const Parser&) = delete; + Parser(Parser&&) = delete; + Parser& operator=(const Parser&) = delete; + Parser& operator=(Parser&&) = delete; + /** * Constructs a parser from the given input stream. The input stream must * live as long as the parser. @@ -81,6 +85,6 @@ class YAML_CPP_API Parser : private noncopyable { std::unique_ptr m_pScanner; std::unique_ptr m_pDirectives; }; -} +} // namespace YAML #endif // PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/lib/yamlcpp/include/yaml-cpp/traits.h b/lib/yamlcpp/include/yaml-cpp/traits.h index f33d0e1f637..36d406ba49d 100644 --- a/lib/yamlcpp/include/yaml-cpp/traits.h +++ b/lib/yamlcpp/include/yaml-cpp/traits.h @@ -7,6 +7,11 @@ #pragma once #endif +#include +#include +#include +#include + namespace YAML { template struct is_numeric { @@ -100,4 +105,31 @@ template struct disable_if : public disable_if_c {}; } +template +struct is_streamable { + template + static auto test(int) + -> decltype(std::declval() << std::declval(), std::true_type()); + + template + static auto test(...) -> std::false_type; + + static const bool value = decltype(test(0))::value; +}; + +template +struct streamable_to_string { + static std::string impl(const Key& key) { + std::stringstream ss; + ss << key; + return ss.str(); + } +}; + +template +struct streamable_to_string { + static std::string impl(const Key&) { + return ""; + } +}; #endif // TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/lib/yamlcpp/src/binary.cpp b/lib/yamlcpp/src/binary.cpp index a7e51301b82..4db6d0b977d 100644 --- a/lib/yamlcpp/src/binary.cpp +++ b/lib/yamlcpp/src/binary.cpp @@ -1,5 +1,7 @@ #include "yaml-cpp/binary.h" +#include + namespace YAML { static const char encoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; @@ -72,19 +74,24 @@ std::vector DecodeBase64(const std::string &input) { unsigned char *out = &ret[0]; unsigned value = 0; - for (std::size_t i = 0; i < input.size(); i++) { + for (std::size_t i = 0, cnt = 0; i < input.size(); i++) { + if (std::isspace(input[i])) { + // skip newlines + continue; + } unsigned char d = decoding[static_cast(input[i])]; if (d == 255) return ret_type(); value = (value << 6) | d; - if (i % 4 == 3) { + if (cnt % 4 == 3) { *out++ = value >> 16; if (i > 0 && input[i - 1] != '=') *out++ = value >> 8; if (input[i] != '=') *out++ = value; } + ++cnt; } ret.resize(out - &ret[0]); diff --git a/lib/yamlcpp/src/collectionstack.h b/lib/yamlcpp/src/collectionstack.h index 2302786e037..9feba967951 100644 --- a/lib/yamlcpp/src/collectionstack.h +++ b/lib/yamlcpp/src/collectionstack.h @@ -7,8 +7,8 @@ #pragma once #endif -#include #include +#include namespace YAML { struct CollectionType { @@ -17,6 +17,7 @@ struct CollectionType { class CollectionStack { public: + CollectionStack() : collectionStack{} {} CollectionType::value GetCurCollectionType() const { if (collectionStack.empty()) return CollectionType::NoCollection; @@ -28,12 +29,13 @@ class CollectionStack { } void PopCollectionType(CollectionType::value type) { assert(type == GetCurCollectionType()); + (void)type; collectionStack.pop(); } private: std::stack collectionStack; }; -} +} // namespace YAML #endif // COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/lib/yamlcpp/src/contrib/graphbuilder.cpp b/lib/yamlcpp/src/contrib/graphbuilder.cpp index 416c1359db6..bf251627953 100644 --- a/lib/yamlcpp/src/contrib/graphbuilder.cpp +++ b/lib/yamlcpp/src/contrib/graphbuilder.cpp @@ -11,7 +11,7 @@ void* BuildGraphOfNextDocument(Parser& parser, if (parser.HandleNextDocument(eventHandler)) { return eventHandler.RootNode(); } else { - return NULL; + return nullptr; } } } diff --git a/lib/yamlcpp/src/contrib/graphbuilderadapter.cpp b/lib/yamlcpp/src/contrib/graphbuilderadapter.cpp index 02a3d972a50..b9e0b657102 100644 --- a/lib/yamlcpp/src/contrib/graphbuilderadapter.cpp +++ b/lib/yamlcpp/src/contrib/graphbuilderadapter.cpp @@ -49,7 +49,7 @@ void GraphBuilderAdapter::OnMapStart(const Mark &mark, const std::string &tag, EmitterStyle::value /* style */) { void *pNode = m_builder.NewMap(mark, tag, GetCurrentParent()); m_containers.push(ContainerFrame(pNode, m_pKeyNode)); - m_pKeyNode = NULL; + m_pKeyNode = nullptr; RegisterAnchor(anchor, pNode); } @@ -62,7 +62,7 @@ void GraphBuilderAdapter::OnMapEnd() { void *GraphBuilderAdapter::GetCurrentParent() const { if (m_containers.empty()) { - return NULL; + return nullptr; } return m_containers.top().pContainer; } @@ -83,7 +83,7 @@ void GraphBuilderAdapter::DispositionNode(void *pNode) { if (m_containers.top().isMap()) { if (m_pKeyNode) { m_builder.AssignInMap(pContainer, m_pKeyNode, pNode); - m_pKeyNode = NULL; + m_pKeyNode = nullptr; } else { m_pKeyNode = pNode; } diff --git a/lib/yamlcpp/src/contrib/graphbuilderadapter.h b/lib/yamlcpp/src/contrib/graphbuilderadapter.h index 0d1e579208c..9078cdfdacd 100644 --- a/lib/yamlcpp/src/contrib/graphbuilderadapter.h +++ b/lib/yamlcpp/src/contrib/graphbuilderadapter.h @@ -26,7 +26,15 @@ namespace YAML { class GraphBuilderAdapter : public EventHandler { public: GraphBuilderAdapter(GraphBuilderInterface& builder) - : m_builder(builder), m_pRootNode(NULL), m_pKeyNode(NULL) {} + : m_builder(builder), + m_containers{}, + m_anchors{}, + m_pRootNode(nullptr), + m_pKeyNode(nullptr) {} + GraphBuilderAdapter(const GraphBuilderAdapter&) = delete; + GraphBuilderAdapter(GraphBuilderAdapter&&) = delete; + GraphBuilderAdapter& operator=(const GraphBuilderAdapter&) = delete; + GraphBuilderAdapter& operator=(GraphBuilderAdapter&&) = delete; virtual void OnDocumentStart(const Mark& mark) { (void)mark; } virtual void OnDocumentEnd() {} @@ -50,8 +58,8 @@ class GraphBuilderAdapter : public EventHandler { struct ContainerFrame { ContainerFrame(void* pSequence) : pContainer(pSequence), pPrevKeyNode(&sequenceMarker) {} - ContainerFrame(void* pMap, void* pPrevKeyNode) - : pContainer(pMap), pPrevKeyNode(pPrevKeyNode) {} + ContainerFrame(void* pMap, void* pPreviousKeyNode) + : pContainer(pMap), pPrevKeyNode(pPreviousKeyNode) {} void* pContainer; void* pPrevKeyNode; @@ -74,6 +82,6 @@ class GraphBuilderAdapter : public EventHandler { void RegisterAnchor(anchor_t anchor, void* pNode); void DispositionNode(void* pNode); }; -} +} // namespace YAML #endif // GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/lib/yamlcpp/src/contrib/yaml-cpp.natvis b/lib/yamlcpp/src/contrib/yaml-cpp.natvis new file mode 100644 index 00000000000..d5c222be52c --- /dev/null +++ b/lib/yamlcpp/src/contrib/yaml-cpp.natvis @@ -0,0 +1,32 @@ + + + + + {{invalid}} + {{pNode==nullptr}} + {{ {*m_pNode} }} + + m_pNode->m_pRef._Ptr->m_pData._Ptr->m_scalar + m_pNode->m_pRef._Ptr->m_pData._Ptr->m_sequence + m_pNode->m_pRef._Ptr->m_pData._Ptr->m_map + m_pNode->m_pRef._Ptr->m_pData._Ptr + + + + + {{node:pRef==nullptr}} + {{node:pRef->pData==nullptr}} + {{undefined}} + {{{m_pRef._Ptr->m_pData._Ptr->m_scalar}}} + {{ Map {m_pRef._Ptr->m_pData._Ptr->m_map}}} + {{ Seq {m_pRef._Ptr->m_pData._Ptr->m_sequence}}} + {{{m_pRef._Ptr->m_pData._Ptr->m_type}}} + + m_pRef._Ptr->m_pData._Ptr->m_scalar + m_pRef._Ptr->m_pData._Ptr->m_sequence + m_pRef._Ptr->m_pData._Ptr->m_map + m_pRef._Ptr->m_pData._Ptr + + + + diff --git a/lib/yamlcpp/src/contrib/yaml-cpp.natvis.md b/lib/yamlcpp/src/contrib/yaml-cpp.natvis.md new file mode 100644 index 00000000000..f1d68a86c61 --- /dev/null +++ b/lib/yamlcpp/src/contrib/yaml-cpp.natvis.md @@ -0,0 +1,9 @@ +# MSVC debugger visualizer for YAML::Node + +## How to use +Add yaml-cpp.natvis to your Visual C++ project like any other source file. It will be included in the debug information, and improve debugger display on YAML::Node and contained types. + +## Compatibility and Troubleshooting + +This has been tested for MSVC 2017. It is expected to be compatible with VS 2015 and VS 2019. If you have any problems, you can open an issue here: https://github.com/peterchen-cp/yaml-cpp-natvis + diff --git a/lib/yamlcpp/src/directives.cpp b/lib/yamlcpp/src/directives.cpp index 963bd2cd379..0c85d0ff37a 100644 --- a/lib/yamlcpp/src/directives.cpp +++ b/lib/yamlcpp/src/directives.cpp @@ -1,12 +1,7 @@ #include "directives.h" namespace YAML { -Directives::Directives() { - // version - version.isDefault = true; - version.major = 1; - version.minor = 2; -} +Directives::Directives() : version{true, 1, 2}, tags{} {} const std::string Directives::TranslateTagHandle( const std::string& handle) const { @@ -19,4 +14,4 @@ const std::string Directives::TranslateTagHandle( return it->second; } -} +} // namespace YAML diff --git a/lib/yamlcpp/src/emitfromevents.cpp b/lib/yamlcpp/src/emitfromevents.cpp index 4832649f3c7..5a51bb471e3 100644 --- a/lib/yamlcpp/src/emitfromevents.cpp +++ b/lib/yamlcpp/src/emitfromevents.cpp @@ -16,10 +16,11 @@ std::string ToString(YAML::anchor_t anchor) { stream << anchor; return stream.str(); } -} +} // namespace namespace YAML { -EmitFromEvents::EmitFromEvents(Emitter& emitter) : m_emitter(emitter) {} +EmitFromEvents::EmitFromEvents(Emitter& emitter) + : m_emitter(emitter), m_stateStack{} {} void EmitFromEvents::OnDocumentStart(const Mark&) {} @@ -116,4 +117,4 @@ void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor) { if (anchor) m_emitter << Anchor(ToString(anchor)); } -} +} // namespace YAML diff --git a/lib/yamlcpp/src/emitter.cpp b/lib/yamlcpp/src/emitter.cpp index ebeb059554e..016beb12c0d 100644 --- a/lib/yamlcpp/src/emitter.cpp +++ b/lib/yamlcpp/src/emitter.cpp @@ -11,7 +11,7 @@ namespace YAML { class Binary; struct _Null; -Emitter::Emitter() : m_pState(new EmitterState) {} +Emitter::Emitter() : m_pState(new EmitterState), m_stream{} {} Emitter::Emitter(std::ostream& stream) : m_pState(new EmitterState), m_stream(stream) {} @@ -285,10 +285,8 @@ void Emitter::PrepareTopNode(EmitterNodeType::value child) { if (child == EmitterNodeType::NoType) return; - if (m_pState->CurGroupChildCount() > 0 && m_stream.col() > 0) { - if (child != EmitterNodeType::NoType) - EmitBeginDoc(); - } + if (m_pState->CurGroupChildCount() > 0 && m_stream.col() > 0) + EmitBeginDoc(); switch (child) { case EmitterNodeType::NoType: @@ -908,4 +906,4 @@ Emitter& Emitter::Write(const Binary& binary) { return *this; } -} +} // namespace YAML diff --git a/lib/yamlcpp/src/emitterstate.cpp b/lib/yamlcpp/src/emitterstate.cpp index 3542aaf5071..890b4f0d2e7 100644 --- a/lib/yamlcpp/src/emitterstate.cpp +++ b/lib/yamlcpp/src/emitterstate.cpp @@ -6,27 +6,31 @@ namespace YAML { EmitterState::EmitterState() : m_isGood(true), + m_lastError{}, + // default global manipulators + m_charset(EmitNonAscii), + m_strFmt(Auto), + m_boolFmt(TrueFalseBool), + m_boolLengthFmt(LongBool), + m_boolCaseFmt(LowerCase), + m_intFmt(Dec), + m_indent(2), + m_preCommentIndent(2), + m_postCommentIndent(1), + m_seqFmt(Block), + m_mapFmt(Block), + m_mapKeyFmt(Auto), + m_floatPrecision(std::numeric_limits::max_digits10), + m_doublePrecision(std::numeric_limits::max_digits10), + // + m_modifiedSettings{}, + m_globalModifiedSettings{}, + m_groups{}, m_curIndent(0), m_hasAnchor(false), m_hasTag(false), m_hasNonContent(false), - m_docCount(0) { - // set default global manipulators - m_charset.set(EmitNonAscii); - m_strFmt.set(Auto); - m_boolFmt.set(TrueFalseBool); - m_boolLengthFmt.set(LongBool); - m_boolCaseFmt.set(LowerCase); - m_intFmt.set(Dec); - m_indent.set(2); - m_preCommentIndent.set(2); - m_postCommentIndent.set(1); - m_seqFmt.set(Block); - m_mapFmt.set(Block); - m_mapKeyFmt.set(Auto); - m_floatPrecision.set(std::numeric_limits::digits10 + 1); - m_doublePrecision.set(std::numeric_limits::digits10 + 1); -} + m_docCount(0) {} EmitterState::~EmitterState() {} @@ -349,7 +353,7 @@ bool EmitterState::SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope) { } bool EmitterState::SetFloatPrecision(std::size_t value, FmtScope::value scope) { - if (value > std::numeric_limits::digits10 + 1) + if (value > std::numeric_limits::max_digits10) return false; _Set(m_floatPrecision, value, scope); return true; @@ -357,9 +361,9 @@ bool EmitterState::SetFloatPrecision(std::size_t value, FmtScope::value scope) { bool EmitterState::SetDoublePrecision(std::size_t value, FmtScope::value scope) { - if (value > std::numeric_limits::digits10 + 1) + if (value > std::numeric_limits::max_digits10) return false; _Set(m_doublePrecision, value, scope); return true; } -} +} // namespace YAML diff --git a/lib/yamlcpp/src/emitterstate.h b/lib/yamlcpp/src/emitterstate.h index 0937f000d9f..75e216695cd 100644 --- a/lib/yamlcpp/src/emitterstate.h +++ b/lib/yamlcpp/src/emitterstate.h @@ -145,7 +145,12 @@ class EmitterState { struct Group { explicit Group(GroupType::value type_) - : type(type_), indent(0), childCount(0), longKey(false) {} + : type(type_), + flowType{}, + indent(0), + childCount(0), + longKey(false), + modifiedSettings{} {} GroupType::value type; FlowType::value flowType; @@ -198,6 +203,6 @@ void EmitterState::_Set(Setting& fmt, T value, FmtScope::value scope) { assert(false); } } -} +} // namespace YAML #endif // EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/lib/yamlcpp/src/emitterutils.cpp b/lib/yamlcpp/src/emitterutils.cpp index 147738ad8a1..e348599d53d 100644 --- a/lib/yamlcpp/src/emitterutils.cpp +++ b/lib/yamlcpp/src/emitterutils.cpp @@ -8,8 +8,8 @@ #include "regeximpl.h" #include "stringsource.h" #include "yaml-cpp/binary.h" // IWYU pragma: keep -#include "yaml-cpp/ostream_wrapper.h" #include "yaml-cpp/null.h" +#include "yaml-cpp/ostream_wrapper.h" namespace YAML { namespace Utils { @@ -134,12 +134,12 @@ void WriteCodePoint(ostream_wrapper& out, int codePoint) { if (codePoint < 0 || codePoint > 0x10FFFF) { codePoint = REPLACEMENT_CHARACTER; } - if (codePoint < 0x7F) { + if (codePoint <= 0x7F) { out << static_cast(codePoint); - } else if (codePoint < 0x7FF) { + } else if (codePoint <= 0x7FF) { out << static_cast(0xC0 | (codePoint >> 6)) << static_cast(0x80 | (codePoint & 0x3F)); - } else if (codePoint < 0xFFFF) { + } else if (codePoint <= 0xFFFF) { out << static_cast(0xE0 | (codePoint >> 12)) << static_cast(0x80 | ((codePoint >> 6) & 0x3F)) << static_cast(0x80 | (codePoint & 0x3F)); @@ -173,12 +173,12 @@ bool IsValidPlainScalar(const std::string& str, FlowType::value flowType, // then check until something is disallowed static const RegEx& disallowed_flow = - Exp::EndScalarInFlow() || (Exp::BlankOrBreak() + Exp::Comment()) || - Exp::NotPrintable() || Exp::Utf8_ByteOrderMark() || Exp::Break() || + Exp::EndScalarInFlow() | (Exp::BlankOrBreak() + Exp::Comment()) | + Exp::NotPrintable() | Exp::Utf8_ByteOrderMark() | Exp::Break() | Exp::Tab(); static const RegEx& disallowed_block = - Exp::EndScalar() || (Exp::BlankOrBreak() + Exp::Comment()) || - Exp::NotPrintable() || Exp::Utf8_ByteOrderMark() || Exp::Break() || + Exp::EndScalar() | (Exp::BlankOrBreak() + Exp::Comment()) | + Exp::NotPrintable() | Exp::Utf8_ByteOrderMark() | Exp::Break() | Exp::Tab(); const RegEx& disallowed = flowType == FlowType::Flow ? disallowed_flow : disallowed_block; @@ -258,7 +258,7 @@ bool WriteAliasName(ostream_wrapper& out, const std::string& str) { } return true; } -} +} // namespace StringFormat::value ComputeStringFormat(const std::string& str, EMITTER_MANIP strFormat, @@ -382,7 +382,7 @@ bool WriteChar(ostream_wrapper& out, char ch) { out << "\"\\b\""; } else if (ch == '\\') { out << "\"\\\\\""; - } else if ((0x20 <= ch && ch <= 0x7e) || ch == ' ') { + } else if (0x20 <= ch && ch <= 0x7e) { out << "\"" << ch << "\""; } else { out << "\""; @@ -401,8 +401,8 @@ bool WriteComment(ostream_wrapper& out, const std::string& str, for (std::string::const_iterator i = str.begin(); GetNextCodePointAndAdvance(codePoint, i, str.end());) { if (codePoint == '\n') { - out << "\n" << IndentTo(curIndent) << "#" - << Indentation(postCommentIndent); + out << "\n" + << IndentTo(curIndent) << "#" << Indentation(postCommentIndent); out.set_comment(); } else { WriteCodePoint(out, codePoint); @@ -479,5 +479,5 @@ bool WriteBinary(ostream_wrapper& out, const Binary& binary) { false); return true; } -} -} +} // namespace Utils +} // namespace YAML diff --git a/lib/yamlcpp/src/exceptions.cpp b/lib/yamlcpp/src/exceptions.cpp index 9b6d8912c18..841549e0dfb 100644 --- a/lib/yamlcpp/src/exceptions.cpp +++ b/lib/yamlcpp/src/exceptions.cpp @@ -2,7 +2,7 @@ // This is here for compatibility with older versions of Visual Studio // which don't support noexcept -#ifdef _MSC_VER +#if defined(_MSC_VER) && _MSC_VER < 1900 #define YAML_CPP_NOEXCEPT _NOEXCEPT #else #define YAML_CPP_NOEXCEPT noexcept diff --git a/lib/yamlcpp/src/exp.h b/lib/yamlcpp/src/exp.h index 7c02cf6e451..fe36535b578 100644 --- a/lib/yamlcpp/src/exp.h +++ b/lib/yamlcpp/src/exp.h @@ -33,15 +33,15 @@ inline const RegEx& Tab() { return e; } inline const RegEx& Blank() { - static const RegEx e = Space() || Tab(); + static const RegEx e = Space() | Tab(); return e; } inline const RegEx& Break() { - static const RegEx e = RegEx('\n') || RegEx("\r\n"); + static const RegEx e = RegEx('\n') | RegEx("\r\n"); return e; } inline const RegEx& BlankOrBreak() { - static const RegEx e = Blank() || Break(); + static const RegEx e = Blank() | Break(); return e; } inline const RegEx& Digit() { @@ -49,29 +49,29 @@ inline const RegEx& Digit() { return e; } inline const RegEx& Alpha() { - static const RegEx e = RegEx('a', 'z') || RegEx('A', 'Z'); + static const RegEx e = RegEx('a', 'z') | RegEx('A', 'Z'); return e; } inline const RegEx& AlphaNumeric() { - static const RegEx e = Alpha() || Digit(); + static const RegEx e = Alpha() | Digit(); return e; } inline const RegEx& Word() { - static const RegEx e = AlphaNumeric() || RegEx('-'); + static const RegEx e = AlphaNumeric() | RegEx('-'); return e; } inline const RegEx& Hex() { - static const RegEx e = Digit() || RegEx('A', 'F') || RegEx('a', 'f'); + static const RegEx e = Digit() | RegEx('A', 'F') | RegEx('a', 'f'); return e; } // Valid Unicode code points that are not part of c-printable (YAML 1.2, sec. // 5.1) inline const RegEx& NotPrintable() { static const RegEx e = - RegEx(0) || - RegEx("\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F", REGEX_OR) || - RegEx(0x0E, 0x1F) || - (RegEx('\xC2') + (RegEx('\x80', '\x84') || RegEx('\x86', '\x9F'))); + RegEx(0) | + RegEx("\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F", REGEX_OR) | + RegEx(0x0E, 0x1F) | + (RegEx('\xC2') + (RegEx('\x80', '\x84') | RegEx('\x86', '\x9F'))); return e; } inline const RegEx& Utf8_ByteOrderMark() { @@ -82,19 +82,19 @@ inline const RegEx& Utf8_ByteOrderMark() { // actual tags inline const RegEx& DocStart() { - static const RegEx e = RegEx("---") + (BlankOrBreak() || RegEx()); + static const RegEx e = RegEx("---") + (BlankOrBreak() | RegEx()); return e; } inline const RegEx& DocEnd() { - static const RegEx e = RegEx("...") + (BlankOrBreak() || RegEx()); + static const RegEx e = RegEx("...") + (BlankOrBreak() | RegEx()); return e; } inline const RegEx& DocIndicator() { - static const RegEx e = DocStart() || DocEnd(); + static const RegEx e = DocStart() | DocEnd(); return e; } inline const RegEx& BlockEntry() { - static const RegEx e = RegEx('-') + (BlankOrBreak() || RegEx()); + static const RegEx e = RegEx('-') + (BlankOrBreak() | RegEx()); return e; } inline const RegEx& Key() { @@ -106,11 +106,11 @@ inline const RegEx& KeyInFlow() { return e; } inline const RegEx& Value() { - static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx()); + static const RegEx e = RegEx(':') + (BlankOrBreak() | RegEx()); return e; } inline const RegEx& ValueInFlow() { - static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx(",}", REGEX_OR)); + static const RegEx e = RegEx(':') + (BlankOrBreak() | RegEx(",}", REGEX_OR)); return e; } inline const RegEx& ValueInJSONFlow() { @@ -122,20 +122,20 @@ inline const RegEx Comment() { return e; } inline const RegEx& Anchor() { - static const RegEx e = !(RegEx("[]{},", REGEX_OR) || BlankOrBreak()); + static const RegEx e = !(RegEx("[]{},", REGEX_OR) | BlankOrBreak()); return e; } inline const RegEx& AnchorEnd() { - static const RegEx e = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak(); + static const RegEx e = RegEx("?:,]}%@`", REGEX_OR) | BlankOrBreak(); return e; } inline const RegEx& URI() { - static const RegEx e = Word() || RegEx("#;/?:@&=+$,_.!~*'()[]", REGEX_OR) || + static const RegEx e = Word() | RegEx("#;/?:@&=+$,_.!~*'()[]", REGEX_OR) | (RegEx('%') + Hex() + Hex()); return e; } inline const RegEx& Tag() { - static const RegEx e = Word() || RegEx("#;/?:@&=+$_.~*'()", REGEX_OR) || + static const RegEx e = Word() | RegEx("#;/?:@&=+$_.~*'()", REGEX_OR) | (RegEx('%') + Hex() + Hex()); return e; } @@ -148,34 +148,34 @@ inline const RegEx& Tag() { // space. inline const RegEx& PlainScalar() { static const RegEx e = - !(BlankOrBreak() || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) || - (RegEx("-?:", REGEX_OR) + (BlankOrBreak() || RegEx()))); + !(BlankOrBreak() | RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) | + (RegEx("-?:", REGEX_OR) + (BlankOrBreak() | RegEx()))); return e; } inline const RegEx& PlainScalarInFlow() { static const RegEx e = - !(BlankOrBreak() || RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) || + !(BlankOrBreak() | RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) | (RegEx("-:", REGEX_OR) + Blank())); return e; } inline const RegEx& EndScalar() { - static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx()); + static const RegEx e = RegEx(':') + (BlankOrBreak() | RegEx()); return e; } inline const RegEx& EndScalarInFlow() { static const RegEx e = - (RegEx(':') + (BlankOrBreak() || RegEx() || RegEx(",]}", REGEX_OR))) || + (RegEx(':') + (BlankOrBreak() | RegEx() | RegEx(",]}", REGEX_OR))) | RegEx(",?[]{}", REGEX_OR); return e; } inline const RegEx& ScanScalarEndInFlow() { - static const RegEx e = (EndScalarInFlow() || (BlankOrBreak() + Comment())); + static const RegEx e = (EndScalarInFlow() | (BlankOrBreak() + Comment())); return e; } inline const RegEx& ScanScalarEnd() { - static const RegEx e = EndScalar() || (BlankOrBreak() + Comment()); + static const RegEx e = EndScalar() | (BlankOrBreak() + Comment()); return e; } inline const RegEx& EscSingleQuote() { @@ -192,8 +192,8 @@ inline const RegEx& ChompIndicator() { return e; } inline const RegEx& Chomp() { - static const RegEx e = (ChompIndicator() + Digit()) || - (Digit() + ChompIndicator()) || ChompIndicator() || + static const RegEx e = (ChompIndicator() + Digit()) | + (Digit() + ChompIndicator()) | ChompIndicator() | Digit(); return e; } diff --git a/lib/yamlcpp/src/node_data.cpp b/lib/yamlcpp/src/node_data.cpp index 77cd4657806..6cfedfc3c7f 100644 --- a/lib/yamlcpp/src/node_data.cpp +++ b/lib/yamlcpp/src/node_data.cpp @@ -13,14 +13,22 @@ namespace YAML { namespace detail { -std::string node_data::empty_scalar; +const std::string& node_data::empty_scalar() { + static const std::string svalue; + return svalue; +} node_data::node_data() : m_isDefined(false), m_mark(Mark::null_mark()), m_type(NodeType::Null), + m_tag{}, m_style(EmitterStyle::Default), - m_seqSize(0) {} + m_scalar{}, + m_sequence{}, + m_seqSize(0), + m_map{}, + m_undefinedPairs{} {} void node_data::mark_defined() { if (m_type == NodeType::Undefined) @@ -188,7 +196,7 @@ void node_data::insert(node& key, node& value, shared_memory_holder pMemory) { convert_to_map(pMemory); break; case NodeType::Scalar: - throw BadSubscript(); + throw BadSubscript(key); } insert_map_pair(key, value); @@ -197,7 +205,7 @@ void node_data::insert(node& key, node& value, shared_memory_holder pMemory) { // indexing node* node_data::get(node& key, shared_memory_holder /* pMemory */) const { if (m_type != NodeType::Map) { - return NULL; + return nullptr; } for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) { @@ -205,7 +213,7 @@ node* node_data::get(node& key, shared_memory_holder /* pMemory */) const { return it->second; } - return NULL; + return nullptr; } node& node_data::get(node& key, shared_memory_holder pMemory) { @@ -218,7 +226,7 @@ node& node_data::get(node& key, shared_memory_holder pMemory) { convert_to_map(pMemory); break; case NodeType::Scalar: - throw BadSubscript(); + throw BadSubscript(key); } for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) { @@ -235,6 +243,14 @@ bool node_data::remove(node& key, shared_memory_holder /* pMemory */) { if (m_type != NodeType::Map) return false; + for (kv_pairs::iterator it = m_undefinedPairs.begin(); + it != m_undefinedPairs.end();) { + kv_pairs::iterator jt = std::next(it); + if (it->first->is(key)) + m_undefinedPairs.erase(it); + it = jt; + } + for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) { if (it->first->is(key)) { m_map.erase(it); @@ -296,5 +312,5 @@ void node_data::convert_sequence_to_map(shared_memory_holder pMemory) { reset_sequence(); m_type = NodeType::Map; } -} -} +} // namespace detail +} // namespace YAML diff --git a/lib/yamlcpp/src/nodebuilder.cpp b/lib/yamlcpp/src/nodebuilder.cpp index 093d2efeb77..c90a66cb878 100644 --- a/lib/yamlcpp/src/nodebuilder.cpp +++ b/lib/yamlcpp/src/nodebuilder.cpp @@ -11,8 +11,13 @@ namespace YAML { struct Mark; NodeBuilder::NodeBuilder() - : m_pMemory(new detail::memory_holder), m_pRoot(0), m_mapDepth(0) { - m_anchors.push_back(0); // since the anchors start at 1 + : m_pMemory(new detail::memory_holder), + m_pRoot(nullptr), + m_stack{}, + m_anchors{}, + m_keys{}, + m_mapDepth(0) { + m_anchors.push_back(nullptr); // since the anchors start at 1 } NodeBuilder::~NodeBuilder() {} @@ -127,4 +132,4 @@ void NodeBuilder::RegisterAnchor(anchor_t anchor, detail::node& node) { m_anchors.push_back(&node); } } -} +} // namespace YAML diff --git a/lib/yamlcpp/src/nodebuilder.h b/lib/yamlcpp/src/nodebuilder.h index a6a47f007bb..642da36cc2a 100644 --- a/lib/yamlcpp/src/nodebuilder.h +++ b/lib/yamlcpp/src/nodebuilder.h @@ -27,6 +27,10 @@ class Node; class NodeBuilder : public EventHandler { public: NodeBuilder(); + NodeBuilder(const NodeBuilder&) = delete; + NodeBuilder(NodeBuilder&&) = delete; + NodeBuilder& operator=(const NodeBuilder&) = delete; + NodeBuilder& operator=(NodeBuilder&&) = delete; virtual ~NodeBuilder(); Node Root(); @@ -65,6 +69,6 @@ class NodeBuilder : public EventHandler { std::vector m_keys; std::size_t m_mapDepth; }; -} +} // namespace YAML #endif // NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/lib/yamlcpp/src/nodeevents.cpp b/lib/yamlcpp/src/nodeevents.cpp index 82261feb058..b7222e068ed 100644 --- a/lib/yamlcpp/src/nodeevents.cpp +++ b/lib/yamlcpp/src/nodeevents.cpp @@ -20,7 +20,7 @@ anchor_t NodeEvents::AliasManager::LookupAnchor( } NodeEvents::NodeEvents(const Node& node) - : m_pMemory(node.m_pMemory), m_root(node.m_pNode) { + : m_pMemory(node.m_pMemory), m_root(node.m_pNode), m_refCount{} { if (m_root) Setup(*m_root); } @@ -98,4 +98,4 @@ bool NodeEvents::IsAliased(const detail::node& node) const { RefCount::const_iterator it = m_refCount.find(node.ref()); return it != m_refCount.end() && it->second > 1; } -} +} // namespace YAML diff --git a/lib/yamlcpp/src/nodeevents.h b/lib/yamlcpp/src/nodeevents.h index 49c18eb854a..dbed5d2066f 100644 --- a/lib/yamlcpp/src/nodeevents.h +++ b/lib/yamlcpp/src/nodeevents.h @@ -26,13 +26,17 @@ class Node; class NodeEvents { public: explicit NodeEvents(const Node& node); + NodeEvents(const NodeEvents&) = delete; + NodeEvents(NodeEvents&&) = delete; + NodeEvents& operator=(const NodeEvents&) = delete; + NodeEvents& operator=(NodeEvents&&) = delete; void Emit(EventHandler& handler); private: class AliasManager { public: - AliasManager() : m_curAnchor(0) {} + AliasManager() : m_anchorByIdentity{}, m_curAnchor(0) {} void RegisterReference(const detail::node& node); anchor_t LookupAnchor(const detail::node& node) const; @@ -59,6 +63,6 @@ class NodeEvents { typedef std::map RefCount; RefCount m_refCount; }; -} +} // namespace YAML #endif // NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/lib/yamlcpp/src/ostream_wrapper.cpp b/lib/yamlcpp/src/ostream_wrapper.cpp index 357fc0094c4..5fa58589736 100644 --- a/lib/yamlcpp/src/ostream_wrapper.cpp +++ b/lib/yamlcpp/src/ostream_wrapper.cpp @@ -7,14 +7,19 @@ namespace YAML { ostream_wrapper::ostream_wrapper() : m_buffer(1, '\0'), - m_pStream(0), + m_pStream(nullptr), m_pos(0), m_row(0), m_col(0), m_comment(false) {} ostream_wrapper::ostream_wrapper(std::ostream& stream) - : m_pStream(&stream), m_pos(0), m_row(0), m_col(0), m_comment(false) {} + : m_buffer{}, + m_pStream(&stream), + m_pos(0), + m_row(0), + m_col(0), + m_comment(false) {} ostream_wrapper::~ostream_wrapper() {} @@ -54,4 +59,4 @@ void ostream_wrapper::update_pos(char ch) { m_comment = false; } } -} +} // namespace YAML diff --git a/lib/yamlcpp/src/parser.cpp b/lib/yamlcpp/src/parser.cpp index cd69f39fcec..7bc0c7828af 100644 --- a/lib/yamlcpp/src/parser.cpp +++ b/lib/yamlcpp/src/parser.cpp @@ -11,9 +11,9 @@ namespace YAML { class EventHandler; -Parser::Parser() {} +Parser::Parser() : m_pScanner{}, m_pDirectives{} {} -Parser::Parser(std::istream& in) { Load(in); } +Parser::Parser(std::istream& in) : Parser() { Load(in); } Parser::~Parser() {} @@ -126,4 +126,4 @@ void Parser::PrintTokens(std::ostream& out) { m_pScanner->pop(); } } -} +} // namespace YAML diff --git a/lib/yamlcpp/src/ptr_vector.h b/lib/yamlcpp/src/ptr_vector.h index 955aebd8d56..d58de04cb62 100644 --- a/lib/yamlcpp/src/ptr_vector.h +++ b/lib/yamlcpp/src/ptr_vector.h @@ -12,15 +12,17 @@ #include #include -#include "yaml-cpp/noncopyable.h" - namespace YAML { // TODO: This class is no longer needed template -class ptr_vector : private YAML::noncopyable { +class ptr_vector { public: - ptr_vector() {} + ptr_vector() : m_data{} {} + ptr_vector(const ptr_vector&) = delete; + ptr_vector(ptr_vector&&) = default; + ptr_vector& operator=(const ptr_vector&) = delete; + ptr_vector& operator=(ptr_vector&&) = default; void clear() { m_data.clear(); } @@ -38,6 +40,6 @@ class ptr_vector : private YAML::noncopyable { private: std::vector> m_data; }; -} +} // namespace YAML #endif // PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/lib/yamlcpp/src/regex_yaml.cpp b/lib/yamlcpp/src/regex_yaml.cpp index 20b772051d2..bf1784b41d5 100644 --- a/lib/yamlcpp/src/regex_yaml.cpp +++ b/lib/yamlcpp/src/regex_yaml.cpp @@ -2,18 +2,16 @@ namespace YAML { // constructors -RegEx::RegEx() : m_op(REGEX_EMPTY) {} -RegEx::RegEx(REGEX_OP op) : m_op(op) {} +RegEx::RegEx(REGEX_OP op) : m_op(op), m_a(0), m_z(0), m_params{} {} +RegEx::RegEx() : RegEx(REGEX_EMPTY) {} -RegEx::RegEx(char ch) : m_op(REGEX_MATCH), m_a(ch) {} +RegEx::RegEx(char ch) : m_op(REGEX_MATCH), m_a(ch), m_z(0), m_params{} {} -RegEx::RegEx(char a, char z) : m_op(REGEX_RANGE), m_a(a), m_z(z) {} +RegEx::RegEx(char a, char z) : m_op(REGEX_RANGE), m_a(a), m_z(z), m_params{} {} -RegEx::RegEx(const std::string& str, REGEX_OP op) : m_op(op) { - for (std::size_t i = 0; i < str.size(); i++) - m_params.push_back(RegEx(str[i])); -} +RegEx::RegEx(const std::string& str, REGEX_OP op) + : m_op(op), m_a(0), m_z(0), m_params(str.begin(), str.end()) {} // combination constructors RegEx operator!(const RegEx& ex) { @@ -22,14 +20,14 @@ RegEx operator!(const RegEx& ex) { return ret; } -RegEx operator||(const RegEx& ex1, const RegEx& ex2) { +RegEx operator|(const RegEx& ex1, const RegEx& ex2) { RegEx ret(REGEX_OR); ret.m_params.push_back(ex1); ret.m_params.push_back(ex2); return ret; } -RegEx operator&&(const RegEx& ex1, const RegEx& ex2) { +RegEx operator&(const RegEx& ex1, const RegEx& ex2) { RegEx ret(REGEX_AND); ret.m_params.push_back(ex1); ret.m_params.push_back(ex2); @@ -42,4 +40,4 @@ RegEx operator+(const RegEx& ex1, const RegEx& ex2) { ret.m_params.push_back(ex2); return ret; } -} +} // namespace YAML diff --git a/lib/yamlcpp/src/regex_yaml.h b/lib/yamlcpp/src/regex_yaml.h index 8f28b852a29..3a347bbd082 100644 --- a/lib/yamlcpp/src/regex_yaml.h +++ b/lib/yamlcpp/src/regex_yaml.h @@ -31,14 +31,14 @@ enum REGEX_OP { class YAML_CPP_API RegEx { public: RegEx(); - RegEx(char ch); + explicit RegEx(char ch); RegEx(char a, char z); RegEx(const std::string& str, REGEX_OP op = REGEX_SEQ); ~RegEx() {} friend YAML_CPP_API RegEx operator!(const RegEx& ex); - friend YAML_CPP_API RegEx operator||(const RegEx& ex1, const RegEx& ex2); - friend YAML_CPP_API RegEx operator&&(const RegEx& ex1, const RegEx& ex2); + friend YAML_CPP_API RegEx operator|(const RegEx& ex1, const RegEx& ex2); + friend YAML_CPP_API RegEx operator&(const RegEx& ex1, const RegEx& ex2); friend YAML_CPP_API RegEx operator+(const RegEx& ex1, const RegEx& ex2); bool Matches(char ch) const; @@ -53,7 +53,7 @@ class YAML_CPP_API RegEx { int Match(const Source& source) const; private: - RegEx(REGEX_OP op); + explicit RegEx(REGEX_OP op); template bool IsValidSource(const Source& source) const; @@ -77,10 +77,11 @@ class YAML_CPP_API RegEx { private: REGEX_OP m_op; - char m_a, m_z; + char m_a{}; + char m_z{}; std::vector m_params; }; -} +} // namespace YAML #include "regeximpl.h" diff --git a/lib/yamlcpp/src/scanner.cpp b/lib/yamlcpp/src/scanner.cpp index b5cfcc12b22..ac848924fc7 100644 --- a/lib/yamlcpp/src/scanner.cpp +++ b/lib/yamlcpp/src/scanner.cpp @@ -9,10 +9,15 @@ namespace YAML { Scanner::Scanner(std::istream& in) : INPUT(in), + m_tokens{}, m_startedStream(false), m_endedStream(false), m_simpleKeyAllowed(false), - m_canBeJSONFlow(false) {} + m_canBeJSONFlow(false), + m_simpleKeys{}, + m_indents{}, + m_indentRefs{}, + m_flows{} {} Scanner::~Scanner() {} @@ -282,7 +287,7 @@ Scanner::IndentMarker* Scanner::PushIndentTo(int column, IndentMarker::INDENT_TYPE type) { // are we in flow? if (InFlowContext()) { - return 0; + return nullptr; } std::unique_ptr pIndent(new IndentMarker(column, type)); @@ -291,12 +296,12 @@ Scanner::IndentMarker* Scanner::PushIndentTo(int column, // is this actually an indentation? if (indent.column < lastIndent.column) { - return 0; + return nullptr; } if (indent.column == lastIndent.column && !(indent.type == IndentMarker::SEQ && lastIndent.type == IndentMarker::MAP)) { - return 0; + return nullptr; } // push a start token diff --git a/lib/yamlcpp/src/scanner.h b/lib/yamlcpp/src/scanner.h index 7bb2ccc71a5..c653ac69ff6 100644 --- a/lib/yamlcpp/src/scanner.h +++ b/lib/yamlcpp/src/scanner.h @@ -49,7 +49,7 @@ class Scanner { enum INDENT_TYPE { MAP, SEQ, NONE }; enum STATUS { VALID, INVALID, UNKNOWN }; IndentMarker(int column_, INDENT_TYPE type_) - : column(column_), type(type_), status(VALID), pStartToken(0) {} + : column(column_), type(type_), status(VALID), pStartToken(nullptr) {} int column; INDENT_TYPE type; diff --git a/lib/yamlcpp/src/scanscalar.cpp b/lib/yamlcpp/src/scanscalar.cpp index 10e359d4466..e5b0973ee8d 100644 --- a/lib/yamlcpp/src/scanscalar.cpp +++ b/lib/yamlcpp/src/scanscalar.cpp @@ -183,7 +183,7 @@ std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) { case FOLD_FLOW: if (nextEmptyLine) { scalar += "\n"; - } else if (!emptyLine && !nextEmptyLine && !escapedNewline) { + } else if (!emptyLine && !escapedNewline) { scalar += " "; } break; diff --git a/lib/yamlcpp/src/scantoken.cpp b/lib/yamlcpp/src/scantoken.cpp index fd8758d7815..325de571502 100644 --- a/lib/yamlcpp/src/scantoken.cpp +++ b/lib/yamlcpp/src/scantoken.cpp @@ -338,7 +338,7 @@ void Scanner::ScanQuotedScalar() { // setup the scanning parameters ScanScalarParams params; - RegEx end = (single ? RegEx(quote) && !Exp::EscSingleQuote() : RegEx(quote)); + RegEx end = (single ? RegEx(quote) & !Exp::EscSingleQuote() : RegEx(quote)); params.end = &end; params.eatEnd = true; params.escape = (single ? '\'' : '\\'); @@ -434,4 +434,4 @@ void Scanner::ScanBlockScalar() { token.value = scalar; m_tokens.push(token); } -} +} // namespace YAML diff --git a/lib/yamlcpp/src/setting.h b/lib/yamlcpp/src/setting.h index b78d40e2e85..280d1e72b30 100644 --- a/lib/yamlcpp/src/setting.h +++ b/lib/yamlcpp/src/setting.h @@ -8,8 +8,8 @@ #endif #include +#include #include -#include "yaml-cpp/noncopyable.h" namespace YAML { class SettingChangeBase; @@ -18,6 +18,7 @@ template class Setting { public: Setting() : m_value() {} + Setting(const T& value) : m_value() { set(value); } const T get() const { return m_value; } std::unique_ptr set(const T& value); @@ -36,10 +37,14 @@ class SettingChangeBase { template class SettingChange : public SettingChangeBase { public: - SettingChange(Setting* pSetting) : m_pCurSetting(pSetting) { - // copy old setting to save its state - m_oldSetting = *pSetting; - } + SettingChange(Setting* pSetting) + : m_pCurSetting(pSetting), + m_oldSetting(*pSetting) // copy old setting to save its state + {} + SettingChange(const SettingChange&) = delete; + SettingChange(SettingChange&&) = delete; + SettingChange& operator=(const SettingChange&) = delete; + SettingChange& operator=(SettingChange&&) = delete; virtual void pop() { m_pCurSetting->restore(m_oldSetting); } @@ -55,9 +60,12 @@ inline std::unique_ptr Setting::set(const T& value) { return pChange; } -class SettingChanges : private noncopyable { +class SettingChanges { public: - SettingChanges() {} + SettingChanges() : m_settingChanges{} {} + SettingChanges(const SettingChanges&) = delete; + SettingChanges(SettingChanges&&) = default; + SettingChanges& operator=(const SettingChanges&) = delete; ~SettingChanges() { clear(); } void clear() { @@ -90,6 +98,6 @@ class SettingChanges : private noncopyable { typedef std::vector> setting_changes; setting_changes m_settingChanges; }; -} +} // namespace YAML #endif // SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/lib/yamlcpp/src/simplekey.cpp b/lib/yamlcpp/src/simplekey.cpp index 70f56b6ae42..c7a21355275 100644 --- a/lib/yamlcpp/src/simplekey.cpp +++ b/lib/yamlcpp/src/simplekey.cpp @@ -5,7 +5,7 @@ namespace YAML { struct Mark; Scanner::SimpleKey::SimpleKey(const Mark& mark_, std::size_t flowLevel_) - : mark(mark_), flowLevel(flowLevel_), pIndent(0), pMapStart(0), pKey(0) {} + : mark(mark_), flowLevel(flowLevel_), pIndent(nullptr), pMapStart(nullptr), pKey(nullptr) {} void Scanner::SimpleKey::Validate() { // Note: pIndent will *not* be garbage here; diff --git a/lib/yamlcpp/src/singledocparser.cpp b/lib/yamlcpp/src/singledocparser.cpp index a27c1c3b04d..be82741531a 100644 --- a/lib/yamlcpp/src/singledocparser.cpp +++ b/lib/yamlcpp/src/singledocparser.cpp @@ -18,6 +18,7 @@ SingleDocParser::SingleDocParser(Scanner& scanner, const Directives& directives) : m_scanner(scanner), m_directives(directives), m_pCollectionStack(new CollectionStack), + m_anchors{}, m_curAnchor(0) {} SingleDocParser::~SingleDocParser() {} @@ -71,8 +72,12 @@ void SingleDocParser::HandleNode(EventHandler& eventHandler) { } std::string tag; + std::string anchor_name; anchor_t anchor; - ParseProperties(tag, anchor); + ParseProperties(tag, anchor, anchor_name); + + if (!anchor_name.empty()) + eventHandler.OnAnchor(mark, anchor_name); const Token& token = m_scanner.peek(); @@ -166,10 +171,10 @@ void SingleDocParser::HandleBlockSequence(EventHandler& eventHandler) { // check for null if (!m_scanner.empty()) { - const Token& token = m_scanner.peek(); - if (token.type == Token::BLOCK_ENTRY || - token.type == Token::BLOCK_SEQ_END) { - eventHandler.OnNull(token.mark, NullAnchor); + const Token& nextToken = m_scanner.peek(); + if (nextToken.type == Token::BLOCK_ENTRY || + nextToken.type == Token::BLOCK_SEQ_END) { + eventHandler.OnNull(nextToken.mark, NullAnchor); continue; } } @@ -356,8 +361,10 @@ void SingleDocParser::HandleCompactMapWithNoKey(EventHandler& eventHandler) { // ParseProperties // . Grabs any tag or anchor tokens and deals with them. -void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor) { +void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor, + std::string& anchor_name) { tag.clear(); + anchor_name.clear(); anchor = NullAnchor; while (1) { @@ -369,7 +376,7 @@ void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor) { ParseTag(tag); break; case Token::ANCHOR: - ParseAnchor(anchor); + ParseAnchor(anchor, anchor_name); break; default: return; @@ -387,11 +394,12 @@ void SingleDocParser::ParseTag(std::string& tag) { m_scanner.pop(); } -void SingleDocParser::ParseAnchor(anchor_t& anchor) { +void SingleDocParser::ParseAnchor(anchor_t& anchor, std::string& anchor_name) { Token& token = m_scanner.peek(); if (anchor) throw ParserException(token.mark, ErrorMsg::MULTIPLE_ANCHORS); + anchor_name = token.value; anchor = RegisterAnchor(token.value); m_scanner.pop(); } @@ -411,4 +419,4 @@ anchor_t SingleDocParser::LookupAnchor(const Mark& mark, return it->second; } -} +} // namespace YAML diff --git a/lib/yamlcpp/src/singledocparser.h b/lib/yamlcpp/src/singledocparser.h index 2b92067cddb..392453ec79d 100644 --- a/lib/yamlcpp/src/singledocparser.h +++ b/lib/yamlcpp/src/singledocparser.h @@ -12,7 +12,6 @@ #include #include "yaml-cpp/anchor.h" -#include "yaml-cpp/noncopyable.h" namespace YAML { class CollectionStack; @@ -23,9 +22,13 @@ struct Directives; struct Mark; struct Token; -class SingleDocParser : private noncopyable { +class SingleDocParser { public: SingleDocParser(Scanner& scanner, const Directives& directives); + SingleDocParser(const SingleDocParser&) = delete; + SingleDocParser(SingleDocParser&&) = delete; + SingleDocParser& operator=(const SingleDocParser&) = delete; + SingleDocParser& operator=(SingleDocParser&&) = delete; ~SingleDocParser(); void HandleDocument(EventHandler& eventHandler); @@ -43,9 +46,10 @@ class SingleDocParser : private noncopyable { void HandleCompactMap(EventHandler& eventHandler); void HandleCompactMapWithNoKey(EventHandler& eventHandler); - void ParseProperties(std::string& tag, anchor_t& anchor); + void ParseProperties(std::string& tag, anchor_t& anchor, + std::string& anchor_name); void ParseTag(std::string& tag); - void ParseAnchor(anchor_t& anchor); + void ParseAnchor(anchor_t& anchor, std::string& anchor_name); anchor_t RegisterAnchor(const std::string& name); anchor_t LookupAnchor(const Mark& mark, const std::string& name) const; @@ -60,6 +64,6 @@ class SingleDocParser : private noncopyable { anchor_t m_curAnchor; }; -} +} // namespace YAML #endif // SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/lib/yamlcpp/src/stream.cpp b/lib/yamlcpp/src/stream.cpp index 3b013cfa7d3..592802d1791 100644 --- a/lib/yamlcpp/src/stream.cpp +++ b/lib/yamlcpp/src/stream.cpp @@ -111,24 +111,15 @@ static UtfIntroState s_introTransitions[][uictMax] = { static char s_introUngetCount[][uictMax] = { // uict00, uictBB, uictBF, uictEF, uictFE, uictFF, uictAscii, uictOther - {0, 1, 1, 0, 0, 0, 0, 1}, - {0, 2, 2, 2, 2, 2, 2, 2}, - {3, 3, 3, 3, 0, 3, 3, 3}, - {4, 4, 4, 4, 4, 0, 4, 4}, - {1, 1, 1, 1, 1, 1, 1, 1}, - {1, 1, 1, 1, 1, 1, 1, 1}, - {2, 2, 2, 2, 2, 0, 2, 2}, - {2, 2, 2, 2, 0, 2, 2, 2}, - {0, 1, 1, 1, 1, 1, 1, 1}, - {0, 2, 2, 2, 2, 2, 2, 2}, - {1, 1, 1, 1, 1, 1, 1, 1}, - {1, 1, 1, 1, 1, 1, 1, 1}, - {0, 2, 2, 2, 2, 2, 2, 2}, - {0, 3, 3, 3, 3, 3, 3, 3}, - {4, 4, 4, 4, 4, 4, 4, 4}, - {2, 0, 2, 2, 2, 2, 2, 2}, - {3, 3, 0, 3, 3, 3, 3, 3}, - {1, 1, 1, 1, 1, 1, 1, 1}, + {0, 1, 1, 0, 0, 0, 0, 1}, {0, 2, 2, 2, 2, 2, 2, 2}, + {3, 3, 3, 3, 0, 3, 3, 3}, {4, 4, 4, 4, 4, 0, 4, 4}, + {1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1}, + {2, 2, 2, 2, 2, 0, 2, 2}, {2, 2, 2, 2, 0, 2, 2, 2}, + {0, 1, 1, 1, 1, 1, 1, 1}, {0, 2, 2, 2, 2, 2, 2, 2}, + {1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1}, + {0, 2, 2, 2, 2, 2, 2, 2}, {0, 3, 3, 3, 3, 3, 3, 3}, + {4, 4, 4, 4, 4, 4, 4, 4}, {2, 0, 2, 2, 2, 2, 2, 2}, + {3, 3, 0, 3, 3, 3, 3, 3}, {1, 1, 1, 1, 1, 1, 1, 1}, }; inline UtfIntroCharType IntroCharTypeOf(std::istream::int_type ch) { @@ -192,6 +183,9 @@ inline void QueueUnicodeCodepoint(std::deque& q, unsigned long ch) { Stream::Stream(std::istream& input) : m_input(input), + m_mark{}, + m_charSet{}, + m_readahead{}, m_pPrefetched(new unsigned char[YAML_PREFETCH_SIZE]), m_nPrefetchedAvailable(0), m_nPrefetchedUsed(0) { @@ -445,4 +439,4 @@ void Stream::StreamInUtf32() const { QueueUnicodeCodepoint(m_readahead, ch); } -} +} // namespace YAML diff --git a/lib/yamlcpp/src/stream.h b/lib/yamlcpp/src/stream.h index 42d542d5b16..ff5149e970c 100644 --- a/lib/yamlcpp/src/stream.h +++ b/lib/yamlcpp/src/stream.h @@ -7,7 +7,6 @@ #pragma once #endif -#include "yaml-cpp/noncopyable.h" #include "yaml-cpp/mark.h" #include #include @@ -17,11 +16,15 @@ #include namespace YAML { -class Stream : private noncopyable { +class Stream { public: friend class StreamCharSource; Stream(std::istream& input); + Stream(const Stream&) = delete; + Stream(Stream&&) = delete; + Stream& operator=(const Stream&) = delete; + Stream& operator=(Stream&&) = delete; ~Stream(); operator bool() const; @@ -71,6 +74,6 @@ inline bool Stream::ReadAheadTo(size_t i) const { return true; return _ReadAheadTo(i); } -} +} // namespace YAML #endif // STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/lib/yamlcpp/src/streamcharsource.h b/lib/yamlcpp/src/streamcharsource.h index 624599e65da..4b6a143ea37 100644 --- a/lib/yamlcpp/src/streamcharsource.h +++ b/lib/yamlcpp/src/streamcharsource.h @@ -7,7 +7,6 @@ #pragma once #endif -#include "yaml-cpp/noncopyable.h" #include namespace YAML { @@ -16,6 +15,9 @@ class StreamCharSource { StreamCharSource(const Stream& stream) : m_offset(0), m_stream(stream) {} StreamCharSource(const StreamCharSource& source) : m_offset(source.m_offset), m_stream(source.m_stream) {} + StreamCharSource(StreamCharSource&&) = default; + StreamCharSource& operator=(const StreamCharSource&) = delete; + StreamCharSource& operator=(StreamCharSource&&) = delete; ~StreamCharSource() {} operator bool() const; @@ -27,8 +29,6 @@ class StreamCharSource { private: std::size_t m_offset; const Stream& m_stream; - - StreamCharSource& operator=(const StreamCharSource&); // non-assignable }; inline StreamCharSource::operator bool() const { @@ -43,6 +43,6 @@ inline const StreamCharSource StreamCharSource::operator+(int i) const { source.m_offset = 0; return source; } -} +} // namespace YAML #endif // STREAMCHARSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/lib/yamlcpp/src/tag.cpp b/lib/yamlcpp/src/tag.cpp index 51435520e46..df8a2cf4613 100644 --- a/lib/yamlcpp/src/tag.cpp +++ b/lib/yamlcpp/src/tag.cpp @@ -6,7 +6,8 @@ #include "token.h" namespace YAML { -Tag::Tag(const Token& token) : type(static_cast(token.data)) { +Tag::Tag(const Token& token) + : type(static_cast(token.data)), handle{}, value{} { switch (type) { case VERBATIM: value = token.value; @@ -46,4 +47,4 @@ const std::string Tag::Translate(const Directives& directives) { } throw std::runtime_error("yaml-cpp: internal error, bad tag type"); } -} +} // namespace YAML diff --git a/lib/yamlcpp/src/token.h b/lib/yamlcpp/src/token.h index ad0b7d0a005..9a27f3d6c12 100644 --- a/lib/yamlcpp/src/token.h +++ b/lib/yamlcpp/src/token.h @@ -14,10 +14,11 @@ namespace YAML { const std::string TokenNames[] = { - "DIRECTIVE", "DOC_START", "DOC_END", "BLOCK_SEQ_START", "BLOCK_MAP_START", - "BLOCK_SEQ_END", "BLOCK_MAP_END", "BLOCK_ENTRY", "FLOW_SEQ_START", - "FLOW_MAP_START", "FLOW_SEQ_END", "FLOW_MAP_END", "FLOW_MAP_COMPACT", - "FLOW_ENTRY", "KEY", "VALUE", "ANCHOR", "ALIAS", "TAG", "SCALAR"}; + "DIRECTIVE", "DOC_START", "DOC_END", "BLOCK_SEQ_START", + "BLOCK_MAP_START", "BLOCK_SEQ_END", "BLOCK_MAP_END", "BLOCK_ENTRY", + "FLOW_SEQ_START", "FLOW_MAP_START", "FLOW_SEQ_END", "FLOW_MAP_END", + "FLOW_MAP_COMPACT", "FLOW_ENTRY", "KEY", "VALUE", + "ANCHOR", "ALIAS", "TAG", "SCALAR"}; struct Token { // enums @@ -48,7 +49,7 @@ struct Token { // data Token(TYPE type_, const Mark& mark_) - : status(VALID), type(type_), mark(mark_), data(0) {} + : status(VALID), type(type_), mark(mark_), value{}, params{}, data(0) {} friend std::ostream& operator<<(std::ostream& out, const Token& token) { out << TokenNames[token.type] << std::string(": ") << token.value; @@ -64,6 +65,6 @@ struct Token { std::vector params; int data; }; -} +} // namespace YAML #endif // TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/lib/yamlcpp/test/CMakeLists.txt b/lib/yamlcpp/test/CMakeLists.txt index 3633da578b3..0a669d5cc86 100644 --- a/lib/yamlcpp/test/CMakeLists.txt +++ b/lib/yamlcpp/test/CMakeLists.txt @@ -1,26 +1,39 @@ -set(gtest_force_shared_crt ${MSVC_SHARED_RT} CACHE BOOL - "Use shared (DLL) run-time lib even when Google Test built as a static lib.") -add_subdirectory(gtest-1.8.0) -include_directories(SYSTEM gtest-1.8.0/googlemock/include) -include_directories(SYSTEM gtest-1.8.0/googletest/include) - -if(WIN32 AND BUILD_SHARED_LIBS) - add_definitions("-DGTEST_LINKED_AS_SHARED_LIBRARY") +include(ExternalProject) + +if(MSVC) + # MS Visual Studio expects lib prefix on static libraries, + # but CMake compiles them without prefix + # See https://gitlab.kitware.com/cmake/cmake/issues/17338 + set(CMAKE_STATIC_LIBRARY_PREFIX "") endif() +ExternalProject_Add( + googletest_project + SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.8.0" + INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/prefix" + CMAKE_ARGS + -DCMAKE_INSTALL_PREFIX:PATH= + -DBUILD_GMOCK=ON + -Dgtest_force_shared_crt=ON +) + +add_library(gmock UNKNOWN IMPORTED) +set_target_properties(gmock PROPERTIES + IMPORTED_LOCATION + ${PROJECT_BINARY_DIR}/test/prefix/lib/${CMAKE_STATIC_LIBRARY_PREFIX}gmock${CMAKE_STATIC_LIBRARY_SUFFIX} +) + +find_package(Threads) + +include_directories(SYSTEM "${PROJECT_BINARY_DIR}/test/prefix/include") + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR - CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(yaml_test_flags "-Wno-variadic-macros -Wno-sign-compare") - - if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(yaml_test_flags "${yaml_test_flags} -Wno-c99-extensions") - endif() - - if(CMAKE_COMPILER_IS_GNUCXX) - set(yaml_test_flags "${yaml_test_flags} -std=gnu++11") - else() - set(yaml_test_flags "${yaml_test_flags} -std=c++11") - endif() + CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(yaml_test_flags "-Wno-variadic-macros -Wno-sign-compare") + + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(yaml_test_flags "${yaml_test_flags} -Wno-c99-extensions") + endif() endif() file(GLOB test_headers [a-z_]*.h) @@ -30,15 +43,27 @@ file(GLOB test_new_api_sources new-api/[a-z]*.cpp) list(APPEND test_sources ${test_new_api_sources}) add_sources(${test_sources} ${test_headers}) +include_directories(${YAML_CPP_SOURCE_DIR}/src) include_directories(${YAML_CPP_SOURCE_DIR}/test) add_executable(run-tests - ${test_sources} - ${test_headers} + ${test_sources} + ${test_headers} +) + +set_target_properties(run-tests PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED ON ) + +add_dependencies(run-tests googletest_project) + set_target_properties(run-tests PROPERTIES - COMPILE_FLAGS "${yaml_c_flags} ${yaml_cxx_flags} ${yaml_test_flags}" + COMPILE_FLAGS "${yaml_c_flags} ${yaml_cxx_flags} ${yaml_test_flags}" ) -target_link_libraries(run-tests yaml-cpp gmock) +target_link_libraries(run-tests + yaml-cpp + gmock + ${CMAKE_THREAD_LIBS_INIT}) add_test(yaml-test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/run-tests) diff --git a/lib/yamlcpp/test/create-emitter-tests.py b/lib/yamlcpp/test/create-emitter-tests.py index a6bf3a4dcec..7295544f1be 100644 --- a/lib/yamlcpp/test/create-emitter-tests.py +++ b/lib/yamlcpp/test/create-emitter-tests.py @@ -35,10 +35,12 @@ def doc_end(implicit=False): def scalar(value, tag='', anchor='', anchor_id=0): emit = [] + handle = [] if tag: emit += ['VerbatimTag("%s")' % encode(tag)] if anchor: emit += ['Anchor("%s")' % encode(anchor)] + handle += ['OnAnchor(_, "%s")' % encode(anchor)] if tag: out_tag = encode(tag) else: @@ -47,39 +49,46 @@ def scalar(value, tag='', anchor='', anchor_id=0): else: out_tag = '!' emit += ['"%s"' % encode(value)] - return {'emit': emit, 'handle': 'OnScalar(_, "%s", %s, "%s")' % (out_tag, anchor_id, encode(value))} + handle += ['OnScalar(_, "%s", %s, "%s")' % (out_tag, anchor_id, encode(value))] + return {'emit': emit, 'handle': handle} def comment(value): return {'emit': 'Comment("%s")' % value, 'handle': ''} def seq_start(tag='', anchor='', anchor_id=0, style='_'): emit = [] + handle = [] if tag: emit += ['VerbatimTag("%s")' % encode(tag)] if anchor: emit += ['Anchor("%s")' % encode(anchor)] + handle += ['OnAnchor(_, "%s")' % encode(anchor)] if tag: out_tag = encode(tag) else: out_tag = '?' emit += ['BeginSeq'] - return {'emit': emit, 'handle': 'OnSequenceStart(_, "%s", %s, %s)' % (out_tag, anchor_id, style)} + handle += ['OnSequenceStart(_, "%s", %s, %s)' % (out_tag, anchor_id, style)] + return {'emit': emit, 'handle': handle} def seq_end(): return {'emit': 'EndSeq', 'handle': 'OnSequenceEnd()'} def map_start(tag='', anchor='', anchor_id=0, style='_'): emit = [] + handle = [] if tag: emit += ['VerbatimTag("%s")' % encode(tag)] if anchor: emit += ['Anchor("%s")' % encode(anchor)] + handle += ['OnAnchor(_, "%s")' % encode(anchor)] if tag: out_tag = encode(tag) else: out_tag = '?' emit += ['BeginMap'] - return {'emit': emit, 'handle': 'OnMapStart(_, "%s", %s, %s)' % (out_tag, anchor_id, style)} + handle += ['OnMapStart(_, "%s", %s, %s)' % (out_tag, anchor_id, style)] + return {'emit': emit, 'handle': handle} def map_end(): return {'emit': 'EndMap', 'handle': 'OnMapEnd()'} @@ -124,7 +133,7 @@ def expand(template): for car in expand(template[:1]): for cdr in expand(template[1:]): yield car + cdr - + def gen_events(): for template in gen_templates(): @@ -144,7 +153,7 @@ class Writer(object): def __init__(self, out): self.out = out self.indent = 0 - + def writeln(self, s): self.out.write('%s%s\n' % (' ' * self.indent, s)) @@ -157,14 +166,14 @@ def __init__(self, writer, name, indent): def __enter__(self): self.writer.writeln('%s {' % self.name) self.writer.indent += self.indent - + def __exit__(self, type, value, traceback): self.writer.indent -= self.indent self.writer.writeln('}') def create_emitter_tests(out): out = Writer(out) - + includes = [ 'handler_test.h', 'yaml-cpp/yaml.h', @@ -202,7 +211,10 @@ def create_emitter_tests(out): out.writeln('') for event in test['events']: handle = event['handle'] - if handle: + if isinstance(handle, list): + for e in handle: + out.writeln('EXPECT_CALL(handler, %s);' % e) + elif handle: out.writeln('EXPECT_CALL(handler, %s);' % handle) out.writeln('Parse(out.c_str());') out.writeln('') diff --git a/lib/yamlcpp/test/integration/emitter_test.cpp b/lib/yamlcpp/test/integration/emitter_test.cpp index 27808380d5a..3a5783bffcf 100644 --- a/lib/yamlcpp/test/integration/emitter_test.cpp +++ b/lib/yamlcpp/test/integration/emitter_test.cpp @@ -253,8 +253,9 @@ TEST_F(EmitterTest, ScalarFormat) { out << DoubleQuoted << "explicit double-quoted scalar"; out << "auto-detected\ndouble-quoted scalar"; out << "a non-\"auto-detected\" double-quoted scalar"; - out << Literal << "literal scalar\nthat may span\nmany, many\nlines " - "and have \"whatever\" crazy\tsymbols that we like"; + out << Literal + << "literal scalar\nthat may span\nmany, many\nlines " + "and have \"whatever\" crazy\tsymbols that we like"; out << EndSeq; ExpectEmit( @@ -526,9 +527,10 @@ TEST_F(EmitterTest, SimpleComment) { TEST_F(EmitterTest, MultiLineComment) { out << BeginSeq; - out << "item 1" << Comment( - "really really long\ncomment that couldn't " - "possibly\nfit on one line"); + out << "item 1" + << Comment( + "really really long\ncomment that couldn't " + "possibly\nfit on one line"); out << "item 2"; out << EndSeq; @@ -901,18 +903,18 @@ TEST_F(EmitterTest, SingleChar) { TEST_F(EmitterTest, DefaultPrecision) { out << BeginSeq; - out << 1.234f; - out << 3.14159265358979; + out << 1.3125f; + out << 1.23455810546875; out << EndSeq; - ExpectEmit("- 1.234\n- 3.14159265358979"); + ExpectEmit("- 1.3125\n- 1.23455810546875"); } TEST_F(EmitterTest, SetPrecision) { out << BeginSeq; - out << FloatPrecision(3) << 1.234f; - out << DoublePrecision(6) << 3.14159265358979; + out << FloatPrecision(3) << 1.3125f; + out << DoublePrecision(6) << 1.23455810546875; out << EndSeq; - ExpectEmit("- 1.23\n- 3.14159"); + ExpectEmit("- 1.31\n- 1.23456"); } TEST_F(EmitterTest, DashInBlockContext) { @@ -984,6 +986,45 @@ TEST_F(EmitterTest, ValueOfBackslash) { ExpectEmit("foo: \"\\\\\""); } +TEST_F(EmitterTest, Infinity) { + out << YAML::BeginMap; + out << YAML::Key << "foo" << YAML::Value + << std::numeric_limits::infinity(); + out << YAML::Key << "bar" << YAML::Value + << std::numeric_limits::infinity(); + out << YAML::EndMap; + + ExpectEmit( + "foo: .inf\n" + "bar: .inf"); +} + +TEST_F(EmitterTest, NegInfinity) { + out << YAML::BeginMap; + out << YAML::Key << "foo" << YAML::Value + << -std::numeric_limits::infinity(); + out << YAML::Key << "bar" << YAML::Value + << -std::numeric_limits::infinity(); + out << YAML::EndMap; + + ExpectEmit( + "foo: -.inf\n" + "bar: -.inf"); +} + +TEST_F(EmitterTest, NaN) { + out << YAML::BeginMap; + out << YAML::Key << "foo" << YAML::Value + << std::numeric_limits::quiet_NaN(); + out << YAML::Key << "bar" << YAML::Value + << std::numeric_limits::quiet_NaN(); + out << YAML::EndMap; + + ExpectEmit( + "foo: .nan\n" + "bar: .nan"); +} + class EmitterErrorTest : public ::testing::Test { protected: void ExpectEmitError(const std::string& expectedError) { @@ -1034,5 +1075,5 @@ TEST_F(EmitterErrorTest, InvalidAlias) { ExpectEmitError(ErrorMsg::INVALID_ALIAS); } -} -} +} // namespace +} // namespace YAML diff --git a/lib/yamlcpp/test/integration/error_messages_test.cpp b/lib/yamlcpp/test/integration/error_messages_test.cpp new file mode 100644 index 00000000000..64ab6b9e5e8 --- /dev/null +++ b/lib/yamlcpp/test/integration/error_messages_test.cpp @@ -0,0 +1,61 @@ +#include "yaml-cpp/yaml.h" // IWYU pragma: keep + +#include "gtest/gtest.h" + +#define EXPECT_THROW_EXCEPTION(exception_type, statement, message) \ + ASSERT_THROW(statement, exception_type); \ + try { \ + statement; \ + } catch (const exception_type& e) { \ + EXPECT_EQ(e.msg, message); \ + } + +namespace YAML { +namespace { + +TEST(ErrorMessageTest, BadSubscriptErrorMessage) { + const char *example_yaml = "first:\n" + " second: 1\n" + " third: 2\n"; + + Node doc = Load(example_yaml); + + // Test that printable key is part of error message + EXPECT_THROW_EXCEPTION(YAML::BadSubscript, doc["first"]["second"]["fourth"], + "operator[] call on a scalar (key: \"fourth\")"); + + EXPECT_THROW_EXCEPTION(YAML::BadSubscript, doc["first"]["second"][37], + "operator[] call on a scalar (key: \"37\")"); + + + // Non-printable key is not included in error message + EXPECT_THROW_EXCEPTION(YAML::BadSubscript, + doc["first"]["second"][std::vector()], + "operator[] call on a scalar"); + + EXPECT_THROW_EXCEPTION(YAML::BadSubscript, doc["first"]["second"][Node()], + "operator[] call on a scalar"); +} + +TEST(ErrorMessageTest, Ex9_1_InvalidNodeErrorMessage) { + const char *example_yaml = "first:\n" + " second: 1\n" + " third: 2\n"; + + const Node doc = Load(example_yaml); + + // Test that printable key is part of error message + EXPECT_THROW_EXCEPTION(YAML::InvalidNode, doc["first"]["fourth"].as(), + "invalid node; first invalid key: \"fourth\""); + + EXPECT_THROW_EXCEPTION(YAML::InvalidNode, doc["first"][37].as(), + "invalid node; first invalid key: \"37\""); + + // Non-printable key is not included in error message + EXPECT_THROW_EXCEPTION(YAML::InvalidNode, + doc["first"][std::vector()].as(), + "invalid node; this may result from using a map " + "iterator as a sequence iterator, or vice-versa"); +} +} +} diff --git a/lib/yamlcpp/test/integration/gen_emitter_test.cpp b/lib/yamlcpp/test/integration/gen_emitter_test.cpp index e44eee6da7d..35361447423 100644 --- a/lib/yamlcpp/test/integration/gen_emitter_test.cpp +++ b/lib/yamlcpp/test/integration/gen_emitter_test.cpp @@ -10,7 +10,7 @@ namespace { typedef HandlerTest GenEmitterTest; -TEST_F(GenEmitterTest, testbf4e63edf2258c91fb88) { +TEST_F(GenEmitterTest, testf2a8b6e6359fb2c30830) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -23,7 +23,7 @@ TEST_F(GenEmitterTest, testbf4e63edf2258c91fb88) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test8c2aa26989357a4c8d2d) { +TEST_F(GenEmitterTest, testa2c9c04eab06a05bf1a3) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -36,7 +36,7 @@ TEST_F(GenEmitterTest, test8c2aa26989357a4c8d2d) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testf8818f97591e2c51179c) { +TEST_F(GenEmitterTest, testc5fae995bf84b2f62627) { Emitter out; out << BeginDoc; out << "foo"; @@ -49,7 +49,7 @@ TEST_F(GenEmitterTest, testf8818f97591e2c51179c) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test2b9d697f1ec84bdc484f) { +TEST_F(GenEmitterTest, test208b4fb7399a936fce93) { Emitter out; out << BeginDoc; out << "foo"; @@ -62,7 +62,7 @@ TEST_F(GenEmitterTest, test2b9d697f1ec84bdc484f) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test969d8cf1535db02242b4) { +TEST_F(GenEmitterTest, test402085442ada9788bc4e) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -74,7 +74,7 @@ TEST_F(GenEmitterTest, test969d8cf1535db02242b4) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test4d16d2c638f0b1131d42) { +TEST_F(GenEmitterTest, test279346c761f7d9a10aec) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -86,7 +86,7 @@ TEST_F(GenEmitterTest, test4d16d2c638f0b1131d42) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test3bdad9a4ffa67cc4201b) { +TEST_F(GenEmitterTest, test386f6766d57a48ccb316) { Emitter out; out << BeginDoc; out << "foo"; @@ -98,7 +98,7 @@ TEST_F(GenEmitterTest, test3bdad9a4ffa67cc4201b) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa57103d877a04b0da3c9) { +TEST_F(GenEmitterTest, test989baa41ede860374193) { Emitter out; out << BeginDoc; out << "foo"; @@ -110,7 +110,7 @@ TEST_F(GenEmitterTest, testa57103d877a04b0da3c9) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testf838cbd6db90346652d6) { +TEST_F(GenEmitterTest, test718fa11b9bfa9dfc6632) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -123,7 +123,7 @@ TEST_F(GenEmitterTest, testf838cbd6db90346652d6) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste65456c6070d7ed9b292) { +TEST_F(GenEmitterTest, test7986c74c7cab2ff062e7) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -136,7 +136,7 @@ TEST_F(GenEmitterTest, teste65456c6070d7ed9b292) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test365273601c89ebaeec61) { +TEST_F(GenEmitterTest, test1a432be0760ebcf72dde) { Emitter out; out << BeginDoc; out << "foo\n"; @@ -149,7 +149,7 @@ TEST_F(GenEmitterTest, test365273601c89ebaeec61) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test92d67b382f78c6a58c2a) { +TEST_F(GenEmitterTest, test9b4714c8c6dd71f963f1) { Emitter out; out << BeginDoc; out << "foo\n"; @@ -162,7 +162,7 @@ TEST_F(GenEmitterTest, test92d67b382f78c6a58c2a) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test49e0bb235c344722e0df) { +TEST_F(GenEmitterTest, test59d039102f43b05233b2) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -174,7 +174,7 @@ TEST_F(GenEmitterTest, test49e0bb235c344722e0df) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test3010c495cd1c61d1ccf2) { +TEST_F(GenEmitterTest, test15371be5fc126b3601ee) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -186,7 +186,7 @@ TEST_F(GenEmitterTest, test3010c495cd1c61d1ccf2) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test22e48c3bc91b32853688) { +TEST_F(GenEmitterTest, test5a2a5702a41d71567a10) { Emitter out; out << BeginDoc; out << "foo\n"; @@ -198,7 +198,7 @@ TEST_F(GenEmitterTest, test22e48c3bc91b32853688) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test03e42bee2a2c6ffc1dd8) { +TEST_F(GenEmitterTest, test7975acd31f55f66c21a9) { Emitter out; out << BeginDoc; out << "foo\n"; @@ -210,7 +210,7 @@ TEST_F(GenEmitterTest, test03e42bee2a2c6ffc1dd8) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test9662984f64ea0b79b267) { +TEST_F(GenEmitterTest, test9ab358e41e3af0e1852c) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -224,7 +224,7 @@ TEST_F(GenEmitterTest, test9662984f64ea0b79b267) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testf3867ffaec6663c515ff) { +TEST_F(GenEmitterTest, test6571b17e1089f3f34d41) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -238,7 +238,7 @@ TEST_F(GenEmitterTest, testf3867ffaec6663c515ff) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testfd8783233e21636f7f12) { +TEST_F(GenEmitterTest, test7c8476d0a02eeab3326f) { Emitter out; out << BeginDoc; out << VerbatimTag("tag"); @@ -252,7 +252,7 @@ TEST_F(GenEmitterTest, testfd8783233e21636f7f12) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test3fc20508ecea0f4cb165) { +TEST_F(GenEmitterTest, test0883fa5d170d96324325) { Emitter out; out << BeginDoc; out << VerbatimTag("tag"); @@ -266,7 +266,7 @@ TEST_F(GenEmitterTest, test3fc20508ecea0f4cb165) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste120c09230c813be6c30) { +TEST_F(GenEmitterTest, test7f44d870f57878e83749) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -279,7 +279,7 @@ TEST_F(GenEmitterTest, teste120c09230c813be6c30) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test835d37d226cbacaa4b2d) { +TEST_F(GenEmitterTest, testc7b8d9af2a71da438220) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -292,7 +292,7 @@ TEST_F(GenEmitterTest, test835d37d226cbacaa4b2d) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7a26848396e9291bf1f1) { +TEST_F(GenEmitterTest, testa27a4f0174aee7622160) { Emitter out; out << BeginDoc; out << VerbatimTag("tag"); @@ -305,7 +305,7 @@ TEST_F(GenEmitterTest, test7a26848396e9291bf1f1) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test34a821220a5e1441f553) { +TEST_F(GenEmitterTest, testf06e77dc66bc51682e57) { Emitter out; out << BeginDoc; out << VerbatimTag("tag"); @@ -318,7 +318,7 @@ TEST_F(GenEmitterTest, test34a821220a5e1441f553) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test53e5179db889a79c3ea2) { +TEST_F(GenEmitterTest, test28c636f42558c217d90b) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -327,12 +327,13 @@ TEST_F(GenEmitterTest, test53e5179db889a79c3ea2) { out << EndDoc; EXPECT_CALL(handler, OnDocumentStart(_)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testb8450c68977e0df66c5b) { +TEST_F(GenEmitterTest, testa8e930c2f4f761519825) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -341,12 +342,13 @@ TEST_F(GenEmitterTest, testb8450c68977e0df66c5b) { out << EndDoc; EXPECT_CALL(handler, OnDocumentStart(_)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste0277d1ed537e53294b4) { +TEST_F(GenEmitterTest, testc73b721f492b45035034) { Emitter out; out << BeginDoc; out << Anchor("anchor"); @@ -355,12 +357,13 @@ TEST_F(GenEmitterTest, teste0277d1ed537e53294b4) { out << EndDoc; EXPECT_CALL(handler, OnDocumentStart(_)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testd6ebe62492bf8757ddde) { +TEST_F(GenEmitterTest, testb401b54145c71ea07848) { Emitter out; out << BeginDoc; out << Anchor("anchor"); @@ -369,12 +372,13 @@ TEST_F(GenEmitterTest, testd6ebe62492bf8757ddde) { out << Comment("comment"); EXPECT_CALL(handler, OnDocumentStart(_)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test56c67a81a5989623dad7) { +TEST_F(GenEmitterTest, test380d9af0ae2e27279526) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -382,12 +386,13 @@ TEST_F(GenEmitterTest, test56c67a81a5989623dad7) { out << "foo"; EXPECT_CALL(handler, OnDocumentStart(_)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testea4c45819b88c22d02b6) { +TEST_F(GenEmitterTest, test6969308096c6106d1f55) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -395,12 +400,13 @@ TEST_F(GenEmitterTest, testea4c45819b88c22d02b6) { out << "foo"; EXPECT_CALL(handler, OnDocumentStart(_)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testfa05ed7573dd54074344) { +TEST_F(GenEmitterTest, testa8afc0036fffa3b2d185) { Emitter out; out << BeginDoc; out << Anchor("anchor"); @@ -408,12 +414,13 @@ TEST_F(GenEmitterTest, testfa05ed7573dd54074344) { out << Comment("comment"); EXPECT_CALL(handler, OnDocumentStart(_)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test52431165a20aa2a085dc) { +TEST_F(GenEmitterTest, test7b41f0a32b90bf5f138d) { Emitter out; out << BeginDoc; out << Anchor("anchor"); @@ -421,12 +428,13 @@ TEST_F(GenEmitterTest, test52431165a20aa2a085dc) { out << Comment("comment"); EXPECT_CALL(handler, OnDocumentStart(_)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test2e1bf781941755fc5944) { +TEST_F(GenEmitterTest, test99b1e0027d74c641f4fc) { Emitter out; out << Comment("comment"); out << "foo"; @@ -438,7 +446,7 @@ TEST_F(GenEmitterTest, test2e1bf781941755fc5944) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test5405b9f863e524bb3e81) { +TEST_F(GenEmitterTest, test8e45fdb3ff3c00d56f27) { Emitter out; out << Comment("comment"); out << "foo"; @@ -450,7 +458,7 @@ TEST_F(GenEmitterTest, test5405b9f863e524bb3e81) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test0a7d85109d068170e547) { +TEST_F(GenEmitterTest, testf898ade0c92d48d498cf) { Emitter out; out << "foo"; out << Comment("comment"); @@ -462,7 +470,7 @@ TEST_F(GenEmitterTest, test0a7d85109d068170e547) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testba8dc6889d6983fb0f05) { +TEST_F(GenEmitterTest, test3eb11fe6897b9638b90c) { Emitter out; out << "foo"; out << EndDoc; @@ -474,7 +482,7 @@ TEST_F(GenEmitterTest, testba8dc6889d6983fb0f05) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testd8743fc1225fef185b69) { +TEST_F(GenEmitterTest, test4e7428248511a461fdae) { Emitter out; out << Comment("comment"); out << "foo"; @@ -485,7 +493,7 @@ TEST_F(GenEmitterTest, testd8743fc1225fef185b69) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testc2f808fe5fb8b2970b89) { +TEST_F(GenEmitterTest, testb811cba8e9f57399cd40) { Emitter out; out << Comment("comment"); out << "foo"; @@ -496,7 +504,7 @@ TEST_F(GenEmitterTest, testc2f808fe5fb8b2970b89) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test984d0572a31be4451efc) { +TEST_F(GenEmitterTest, testc625669ef35d9165757f) { Emitter out; out << "foo"; out << Comment("comment"); @@ -507,7 +515,7 @@ TEST_F(GenEmitterTest, test984d0572a31be4451efc) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa3883cf6b7f84c32ba99) { +TEST_F(GenEmitterTest, test0bc005214f48707274f7) { Emitter out; out << "foo"; out << Comment("comment"); @@ -518,7 +526,7 @@ TEST_F(GenEmitterTest, testa3883cf6b7f84c32ba99) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test1fe1f2d242b3a00c5f83) { +TEST_F(GenEmitterTest, testdccc5288dfb2f680dd82) { Emitter out; out << Comment("comment"); out << "foo\n"; @@ -530,7 +538,7 @@ TEST_F(GenEmitterTest, test1fe1f2d242b3a00c5f83) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test80e82792ed68bb0cadbc) { +TEST_F(GenEmitterTest, test0a928620b149d5644a3b) { Emitter out; out << Comment("comment"); out << "foo\n"; @@ -542,7 +550,7 @@ TEST_F(GenEmitterTest, test80e82792ed68bb0cadbc) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test6756b87f08499449fd53) { +TEST_F(GenEmitterTest, test72bf9f8ba5207fb041c3) { Emitter out; out << "foo\n"; out << Comment("comment"); @@ -554,7 +562,7 @@ TEST_F(GenEmitterTest, test6756b87f08499449fd53) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7d768a7e214b2e791928) { +TEST_F(GenEmitterTest, test39ba33ec287e431e70d0) { Emitter out; out << "foo\n"; out << EndDoc; @@ -566,7 +574,7 @@ TEST_F(GenEmitterTest, test7d768a7e214b2e791928) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test73470e304962e94c82ee) { +TEST_F(GenEmitterTest, testce39fe4e650942b617c6) { Emitter out; out << Comment("comment"); out << "foo\n"; @@ -577,7 +585,7 @@ TEST_F(GenEmitterTest, test73470e304962e94c82ee) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test220fcaca9f58ed63ab66) { +TEST_F(GenEmitterTest, test680e99eab986e1cdac01) { Emitter out; out << Comment("comment"); out << "foo\n"; @@ -588,7 +596,7 @@ TEST_F(GenEmitterTest, test220fcaca9f58ed63ab66) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7e4c037d370d52aa4da4) { +TEST_F(GenEmitterTest, teste6e7f73dfac0048154af) { Emitter out; out << "foo\n"; out << Comment("comment"); @@ -599,7 +607,7 @@ TEST_F(GenEmitterTest, test7e4c037d370d52aa4da4) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test79a2ffc6c8161726f1ed) { +TEST_F(GenEmitterTest, test19e2c91493d21a389511) { Emitter out; out << "foo\n"; out << Comment("comment"); @@ -610,7 +618,7 @@ TEST_F(GenEmitterTest, test79a2ffc6c8161726f1ed) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test2a634546fd8c4b92ad18) { +TEST_F(GenEmitterTest, testc15cdbdbf9661c853def) { Emitter out; out << Comment("comment"); out << VerbatimTag("tag"); @@ -623,7 +631,7 @@ TEST_F(GenEmitterTest, test2a634546fd8c4b92ad18) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test84a311c6ca4fe200eff5) { +TEST_F(GenEmitterTest, testa349878c464f03fa6d4e) { Emitter out; out << Comment("comment"); out << VerbatimTag("tag"); @@ -636,7 +644,7 @@ TEST_F(GenEmitterTest, test84a311c6ca4fe200eff5) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testef05b48cc1f9318b612f) { +TEST_F(GenEmitterTest, testc063a846f87b1e20e4e9) { Emitter out; out << VerbatimTag("tag"); out << "foo"; @@ -649,7 +657,7 @@ TEST_F(GenEmitterTest, testef05b48cc1f9318b612f) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa77250518abd6e019ab8) { +TEST_F(GenEmitterTest, testdfb3a9ec6da3b792f392) { Emitter out; out << VerbatimTag("tag"); out << "foo"; @@ -662,7 +670,7 @@ TEST_F(GenEmitterTest, testa77250518abd6e019ab8) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test3e9c6f05218917c77c62) { +TEST_F(GenEmitterTest, test6f545990782be38424bf) { Emitter out; out << Comment("comment"); out << VerbatimTag("tag"); @@ -674,7 +682,7 @@ TEST_F(GenEmitterTest, test3e9c6f05218917c77c62) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7392dd9d6829b8569e16) { +TEST_F(GenEmitterTest, test9d7dd5e044527a4e8f31) { Emitter out; out << Comment("comment"); out << VerbatimTag("tag"); @@ -686,7 +694,7 @@ TEST_F(GenEmitterTest, test7392dd9d6829b8569e16) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test8b3e535afd61211d988f) { +TEST_F(GenEmitterTest, testba570ae83f89342779ff) { Emitter out; out << VerbatimTag("tag"); out << "foo"; @@ -698,7 +706,7 @@ TEST_F(GenEmitterTest, test8b3e535afd61211d988f) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa88d36caa958ac21e487) { +TEST_F(GenEmitterTest, testc6fc50c169793aa60531) { Emitter out; out << VerbatimTag("tag"); out << "foo"; @@ -710,7 +718,7 @@ TEST_F(GenEmitterTest, testa88d36caa958ac21e487) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test0afc4387fea5a0ad574d) { +TEST_F(GenEmitterTest, testd10a9c9671992acd494d) { Emitter out; out << Comment("comment"); out << Anchor("anchor"); @@ -718,12 +726,13 @@ TEST_F(GenEmitterTest, test0afc4387fea5a0ad574d) { out << EndDoc; EXPECT_CALL(handler, OnDocumentStart(_)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test6e02b45ba1f87d0b17fa) { +TEST_F(GenEmitterTest, testd5ee8a3bdb42c8639ad4) { Emitter out; out << Comment("comment"); out << Anchor("anchor"); @@ -731,12 +740,13 @@ TEST_F(GenEmitterTest, test6e02b45ba1f87d0b17fa) { out << EndDoc; EXPECT_CALL(handler, OnDocumentStart(_)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test1ecee6697402f1ced486) { +TEST_F(GenEmitterTest, test24914f6c2b7f7d5843c4) { Emitter out; out << Anchor("anchor"); out << "foo"; @@ -744,12 +754,13 @@ TEST_F(GenEmitterTest, test1ecee6697402f1ced486) { out << EndDoc; EXPECT_CALL(handler, OnDocumentStart(_)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testf778d3e7e1fd4bc81ac8) { +TEST_F(GenEmitterTest, test9af19fe8c77aa18cd462) { Emitter out; out << Anchor("anchor"); out << "foo"; @@ -757,60 +768,65 @@ TEST_F(GenEmitterTest, testf778d3e7e1fd4bc81ac8) { out << Comment("comment"); EXPECT_CALL(handler, OnDocumentStart(_)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testce2ddd97c4f7b7cad993) { +TEST_F(GenEmitterTest, testc2f9274717aaf39b0838) { Emitter out; out << Comment("comment"); out << Anchor("anchor"); out << "foo"; EXPECT_CALL(handler, OnDocumentStart(_)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test9801aff946ce11347b78) { +TEST_F(GenEmitterTest, test75f3a7f62b5b77411653) { Emitter out; out << Comment("comment"); out << Anchor("anchor"); out << "foo"; EXPECT_CALL(handler, OnDocumentStart(_)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test02ae081b4d9719668378) { +TEST_F(GenEmitterTest, testea51373e6b4e598b2adf) { Emitter out; out << Anchor("anchor"); out << "foo"; out << Comment("comment"); EXPECT_CALL(handler, OnDocumentStart(_)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test1c75e643ba55491e9d58) { +TEST_F(GenEmitterTest, testa594204f0724101d4931) { Emitter out; out << Anchor("anchor"); out << "foo"; out << Comment("comment"); EXPECT_CALL(handler, OnDocumentStart(_)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa834d5e30e0fde106520) { +TEST_F(GenEmitterTest, test87638f2fba55c5235720) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -825,7 +841,7 @@ TEST_F(GenEmitterTest, testa834d5e30e0fde106520) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test26c5da2b48377ba6d9c3) { +TEST_F(GenEmitterTest, test786f027ec8e380bdeb45) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -840,7 +856,7 @@ TEST_F(GenEmitterTest, test26c5da2b48377ba6d9c3) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste5df2b4f5b7ed31f5843) { +TEST_F(GenEmitterTest, test9d9ca2fc29536ef5d392) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -855,7 +871,7 @@ TEST_F(GenEmitterTest, teste5df2b4f5b7ed31f5843) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7da7e14ccc523f8ef682) { +TEST_F(GenEmitterTest, testde9c33927d8f706e5191) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -870,7 +886,7 @@ TEST_F(GenEmitterTest, test7da7e14ccc523f8ef682) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test5dc6d560b8a5defab6a6) { +TEST_F(GenEmitterTest, testa03392eb1d9af2180eb2) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -885,7 +901,7 @@ TEST_F(GenEmitterTest, test5dc6d560b8a5defab6a6) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test5c2184c2ae1d09d7e486) { +TEST_F(GenEmitterTest, test8826ba8a4954e2775441) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -899,7 +915,7 @@ TEST_F(GenEmitterTest, test5c2184c2ae1d09d7e486) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testcb7ca22e0d0c01cdfd6c) { +TEST_F(GenEmitterTest, testf116d1ab8a1646bb4295) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -913,7 +929,7 @@ TEST_F(GenEmitterTest, testcb7ca22e0d0c01cdfd6c) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test764d56ed21bef8c8ed1d) { +TEST_F(GenEmitterTest, test1d4afe394248c5d6f190) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -927,7 +943,7 @@ TEST_F(GenEmitterTest, test764d56ed21bef8c8ed1d) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testff49b69cd78b76f680f4) { +TEST_F(GenEmitterTest, test4cc7b190d6dd08368f08) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -941,7 +957,7 @@ TEST_F(GenEmitterTest, testff49b69cd78b76f680f4) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testb8bbef15bc67a7e8a4f1) { +TEST_F(GenEmitterTest, testc623063380afa67c57c4) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -955,7 +971,7 @@ TEST_F(GenEmitterTest, testb8bbef15bc67a7e8a4f1) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testfe636c029a18a80da2bc) { +TEST_F(GenEmitterTest, teste24ef3f378c4c33107b2) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -972,7 +988,7 @@ TEST_F(GenEmitterTest, testfe636c029a18a80da2bc) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste61e3e6d8f0e748525e6) { +TEST_F(GenEmitterTest, test2aa8f68b872fd07fde8c) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -989,7 +1005,7 @@ TEST_F(GenEmitterTest, teste61e3e6d8f0e748525e6) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test410c9f00cef2fbe84d3f) { +TEST_F(GenEmitterTest, test940bf9330572d48b476f) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1006,7 +1022,7 @@ TEST_F(GenEmitterTest, test410c9f00cef2fbe84d3f) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test2438e75da6ea8f014749) { +TEST_F(GenEmitterTest, testd710bce67052a991abfa) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1023,7 +1039,7 @@ TEST_F(GenEmitterTest, test2438e75da6ea8f014749) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test0eb1e1c40f31df48889a) { +TEST_F(GenEmitterTest, testd2ac557dae648cd1ba66) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1040,7 +1056,7 @@ TEST_F(GenEmitterTest, test0eb1e1c40f31df48889a) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7d9b8575590f008b6dcf) { +TEST_F(GenEmitterTest, testb394f0e282404d1235d3) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1057,7 +1073,7 @@ TEST_F(GenEmitterTest, test7d9b8575590f008b6dcf) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test65e209ba68cc24d8b595) { +TEST_F(GenEmitterTest, testaf620080909b118a715d) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -1073,7 +1089,7 @@ TEST_F(GenEmitterTest, test65e209ba68cc24d8b595) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test507a8de1564951289f94) { +TEST_F(GenEmitterTest, testfc23fc6f424006e5907f) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -1089,7 +1105,7 @@ TEST_F(GenEmitterTest, test507a8de1564951289f94) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testfad3bc4da4b3117cbaac) { +TEST_F(GenEmitterTest, testbc5517fe466dd4988ce2) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1105,7 +1121,7 @@ TEST_F(GenEmitterTest, testfad3bc4da4b3117cbaac) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test56e0e2370b233fb813d0) { +TEST_F(GenEmitterTest, testc0db52f1be33ddf93852) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1121,7 +1137,7 @@ TEST_F(GenEmitterTest, test56e0e2370b233fb813d0) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test0a4ab861864d922b0ef3) { +TEST_F(GenEmitterTest, test279a9eef5b2d2cf98ecf) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1137,7 +1153,7 @@ TEST_F(GenEmitterTest, test0a4ab861864d922b0ef3) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testdfefc6ca543a9fdd2ab4) { +TEST_F(GenEmitterTest, test7f55b2f00c1090e43af5) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1153,7 +1169,7 @@ TEST_F(GenEmitterTest, testdfefc6ca543a9fdd2ab4) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test812eee6d9f35f45d4c74) { +TEST_F(GenEmitterTest, test1be996b4b790d9bd565d) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -1171,7 +1187,7 @@ TEST_F(GenEmitterTest, test812eee6d9f35f45d4c74) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test40cad31d965f6c4799b2) { +TEST_F(GenEmitterTest, testa5dea69e968ea27412cc) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -1189,7 +1205,7 @@ TEST_F(GenEmitterTest, test40cad31d965f6c4799b2) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testcd959e61fe82eb217264) { +TEST_F(GenEmitterTest, test77fe0d4370db4aa8af1a) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1207,7 +1223,7 @@ TEST_F(GenEmitterTest, testcd959e61fe82eb217264) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test6d9e41274914945389ad) { +TEST_F(GenEmitterTest, test6d0319a28dd1a931f211) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1225,7 +1241,7 @@ TEST_F(GenEmitterTest, test6d9e41274914945389ad) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testab6b07362d96686c11d0) { +TEST_F(GenEmitterTest, test0031c4cd5331366162a6) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1243,7 +1259,7 @@ TEST_F(GenEmitterTest, testab6b07362d96686c11d0) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testd4c0512efd628009c912) { +TEST_F(GenEmitterTest, testc0c74d483811e3322ed2) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1261,7 +1277,7 @@ TEST_F(GenEmitterTest, testd4c0512efd628009c912) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test2774792a756fc53a2ca9) { +TEST_F(GenEmitterTest, test0d0938c9dca1e78401d6) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -1278,7 +1294,7 @@ TEST_F(GenEmitterTest, test2774792a756fc53a2ca9) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test9f03b22824667c3b1189) { +TEST_F(GenEmitterTest, test0c83b8f0404e62673099) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -1295,7 +1311,7 @@ TEST_F(GenEmitterTest, test9f03b22824667c3b1189) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test24dd60172cf27492a619) { +TEST_F(GenEmitterTest, test733fd2f94ae082ea6076) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1312,7 +1328,7 @@ TEST_F(GenEmitterTest, test24dd60172cf27492a619) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa48e3f886fe68e9b48f5) { +TEST_F(GenEmitterTest, test04b57f98a492b0f2c1ad) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1329,7 +1345,7 @@ TEST_F(GenEmitterTest, testa48e3f886fe68e9b48f5) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testfc1258212ed3c60e6e0c) { +TEST_F(GenEmitterTest, test80d83a80f235341f1bff) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1346,7 +1362,7 @@ TEST_F(GenEmitterTest, testfc1258212ed3c60e6e0c) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test31c3570f387278586efc) { +TEST_F(GenEmitterTest, testecbe137bf7436ccd7976) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1363,7 +1379,7 @@ TEST_F(GenEmitterTest, test31c3570f387278586efc) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test0d2e56437573e1a68e06) { +TEST_F(GenEmitterTest, testf14f2e8202cacdf9252d) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -1375,13 +1391,14 @@ TEST_F(GenEmitterTest, test0d2e56437573e1a68e06) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test87f2bba12c122a5ef611) { +TEST_F(GenEmitterTest, test9c029f7cf565580a56fd) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -1393,13 +1410,14 @@ TEST_F(GenEmitterTest, test87f2bba12c122a5ef611) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testce2b83660fc3c47881d9) { +TEST_F(GenEmitterTest, test129cd28cda34c7b97a89) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1411,13 +1429,14 @@ TEST_F(GenEmitterTest, testce2b83660fc3c47881d9) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test1192cd9aee9977c43f91) { +TEST_F(GenEmitterTest, test1c55ee081412be96e00f) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1429,13 +1448,14 @@ TEST_F(GenEmitterTest, test1192cd9aee9977c43f91) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test5ec743a4a5f5d9f250e6) { +TEST_F(GenEmitterTest, testf9e9d15d9e09a8e98681) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1447,13 +1467,14 @@ TEST_F(GenEmitterTest, test5ec743a4a5f5d9f250e6) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test989ce0d2a8d41f94e563) { +TEST_F(GenEmitterTest, test03dd7104722840fe7fee) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1465,13 +1486,14 @@ TEST_F(GenEmitterTest, test989ce0d2a8d41f94e563) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test16b16527ce6d2047b885) { +TEST_F(GenEmitterTest, teste6c856a08270255404b6) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -1482,13 +1504,14 @@ TEST_F(GenEmitterTest, test16b16527ce6d2047b885) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test190462c295b7c1b9be90) { +TEST_F(GenEmitterTest, testf285ed8797058c0e4e2f) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -1499,13 +1522,14 @@ TEST_F(GenEmitterTest, test190462c295b7c1b9be90) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste179dd43311786d15564) { +TEST_F(GenEmitterTest, test906076647b894281787e) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1516,13 +1540,14 @@ TEST_F(GenEmitterTest, teste179dd43311786d15564) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test448c118909ba10e1e5c2) { +TEST_F(GenEmitterTest, test8a836336041c56130c5c) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1533,13 +1558,14 @@ TEST_F(GenEmitterTest, test448c118909ba10e1e5c2) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test2aa064c8455651bbbccf) { +TEST_F(GenEmitterTest, testc7f61ada097fb34f24ce) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1550,13 +1576,14 @@ TEST_F(GenEmitterTest, test2aa064c8455651bbbccf) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test68e7564605ae7013b858) { +TEST_F(GenEmitterTest, testec075d926fd1f95a1bae) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1567,13 +1594,14 @@ TEST_F(GenEmitterTest, test68e7564605ae7013b858) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test11fa4cf5f845696bf8c9) { +TEST_F(GenEmitterTest, testa79ce9edc0c3593faa31) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -1586,13 +1614,14 @@ TEST_F(GenEmitterTest, test11fa4cf5f845696bf8c9) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test2b2cd9f7d03b725c77f7) { +TEST_F(GenEmitterTest, test525c133ebf8f46a1962f) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -1605,13 +1634,14 @@ TEST_F(GenEmitterTest, test2b2cd9f7d03b725c77f7) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test846d35c91609d010038a) { +TEST_F(GenEmitterTest, testb06604d03a8c9cfbe7c2) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1624,13 +1654,14 @@ TEST_F(GenEmitterTest, test846d35c91609d010038a) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test0295ace15e4d18d3efff) { +TEST_F(GenEmitterTest, teste268ba5f2d54120eb665) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1643,13 +1674,14 @@ TEST_F(GenEmitterTest, test0295ace15e4d18d3efff) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test31f01031d12ec0623b22) { +TEST_F(GenEmitterTest, test7a646350a81bba70e44a) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1662,13 +1694,14 @@ TEST_F(GenEmitterTest, test31f01031d12ec0623b22) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test9dfa64a8b15cb1e411f3) { +TEST_F(GenEmitterTest, test025df570e0d8a1f818da) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1681,13 +1714,14 @@ TEST_F(GenEmitterTest, test9dfa64a8b15cb1e411f3) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test2e707476963eb0157f56) { +TEST_F(GenEmitterTest, test897087b9aba1d5773870) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -1699,13 +1733,14 @@ TEST_F(GenEmitterTest, test2e707476963eb0157f56) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test455d60cf99b6ecf73d46) { +TEST_F(GenEmitterTest, testa45ee0501da4a4e5da54) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -1717,13 +1752,14 @@ TEST_F(GenEmitterTest, test455d60cf99b6ecf73d46) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa370b09ea89f5df32d03) { +TEST_F(GenEmitterTest, teste751c06ea558ccca1821) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1735,13 +1771,14 @@ TEST_F(GenEmitterTest, testa370b09ea89f5df32d03) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test325554fe67b486e0ac43) { +TEST_F(GenEmitterTest, test8526d26e85cc930eecec) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1753,13 +1790,14 @@ TEST_F(GenEmitterTest, test325554fe67b486e0ac43) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test0e511740421ef2391918) { +TEST_F(GenEmitterTest, teste9a5a4a0f0e44311d01a) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1771,13 +1809,14 @@ TEST_F(GenEmitterTest, test0e511740421ef2391918) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test48e6238da58855f75d2d) { +TEST_F(GenEmitterTest, testac8a091ab93b65aee893) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1789,13 +1828,14 @@ TEST_F(GenEmitterTest, test48e6238da58855f75d2d) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test985ccda3f305aebbe7c1) { +TEST_F(GenEmitterTest, testee014788f524623b5075) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -1814,7 +1854,7 @@ TEST_F(GenEmitterTest, test985ccda3f305aebbe7c1) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test48a885b1b5192b7d6c42) { +TEST_F(GenEmitterTest, test57a067545c01c42a7b4e) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -1833,7 +1873,7 @@ TEST_F(GenEmitterTest, test48a885b1b5192b7d6c42) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test2d59de662bffd75bdd4e) { +TEST_F(GenEmitterTest, test948ac02da8825214c869) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1852,7 +1892,7 @@ TEST_F(GenEmitterTest, test2d59de662bffd75bdd4e) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test1876b50ad981242e1b5e) { +TEST_F(GenEmitterTest, testa3d6c5e8a1658c1dd726) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1871,7 +1911,7 @@ TEST_F(GenEmitterTest, test1876b50ad981242e1b5e) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test3be092fd7c3394e57a02) { +TEST_F(GenEmitterTest, test548d71006d7cafde91da) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1890,7 +1930,7 @@ TEST_F(GenEmitterTest, test3be092fd7c3394e57a02) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testdaaf6202df0524d94ba2) { +TEST_F(GenEmitterTest, test35e08ea7459dbee9eab8) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1909,7 +1949,7 @@ TEST_F(GenEmitterTest, testdaaf6202df0524d94ba2) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test0f9c4973bc77d8baa80b) { +TEST_F(GenEmitterTest, test87e79665a4339434d781) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1928,7 +1968,7 @@ TEST_F(GenEmitterTest, test0f9c4973bc77d8baa80b) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testfb738d9af8c3f5d0d89b) { +TEST_F(GenEmitterTest, test4928d09bc979129c05ca) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -1946,7 +1986,7 @@ TEST_F(GenEmitterTest, testfb738d9af8c3f5d0d89b) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7ba35bde1bf4471d19fd) { +TEST_F(GenEmitterTest, test1d2f73011af6b4486504) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -1964,7 +2004,7 @@ TEST_F(GenEmitterTest, test7ba35bde1bf4471d19fd) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test2fc98e907a537e17f435) { +TEST_F(GenEmitterTest, test2460718f7277d5f42306) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -1982,7 +2022,7 @@ TEST_F(GenEmitterTest, test2fc98e907a537e17f435) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test1c2cbe9d3ad5bca645f1) { +TEST_F(GenEmitterTest, test52309e87b3f0185f982b) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -2000,7 +2040,7 @@ TEST_F(GenEmitterTest, test1c2cbe9d3ad5bca645f1) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test999bff6d585448f6f195) { +TEST_F(GenEmitterTest, testa51d8f1cedfead1de5ab) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -2018,7 +2058,7 @@ TEST_F(GenEmitterTest, test999bff6d585448f6f195) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test8972a583224ae4553b81) { +TEST_F(GenEmitterTest, test537bf14b4d578f212f4d) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -2036,7 +2076,7 @@ TEST_F(GenEmitterTest, test8972a583224ae4553b81) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test77d2c64329579c726156) { +TEST_F(GenEmitterTest, teste19e3fd4d5cd52bf6754) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -2054,7 +2094,7 @@ TEST_F(GenEmitterTest, test77d2c64329579c726156) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testf60e4d264223ca1d8ed0) { +TEST_F(GenEmitterTest, testf27e53142f2ca0e96a99) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -2070,14 +2110,16 @@ TEST_F(GenEmitterTest, testf60e4d264223ca1d8ed0) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test954d6b81ce04cb78b6a9) { +TEST_F(GenEmitterTest, test8ce13fdbb0e53e131cbe) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -2093,14 +2135,16 @@ TEST_F(GenEmitterTest, test954d6b81ce04cb78b6a9) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test24e333326d100b0fb309) { +TEST_F(GenEmitterTest, test9fa693277f014353aa34) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -2116,14 +2160,16 @@ TEST_F(GenEmitterTest, test24e333326d100b0fb309) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test996f3742f7296a3dfc08) { +TEST_F(GenEmitterTest, testc3e4849fb38bc3556f45) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -2139,14 +2185,16 @@ TEST_F(GenEmitterTest, test996f3742f7296a3dfc08) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7c795dad3124d186fe05) { +TEST_F(GenEmitterTest, test34049495795f40da2d52) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -2162,14 +2210,16 @@ TEST_F(GenEmitterTest, test7c795dad3124d186fe05) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testc2b03c01b73703fad10f) { +TEST_F(GenEmitterTest, test14353701fc865919ab50) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -2185,14 +2235,16 @@ TEST_F(GenEmitterTest, testc2b03c01b73703fad10f) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testab877782f99ac0c76a54) { +TEST_F(GenEmitterTest, test74547fc0ba8d387c5423) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -2208,14 +2260,16 @@ TEST_F(GenEmitterTest, testab877782f99ac0c76a54) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test784517e5fb6049b5eeb8) { +TEST_F(GenEmitterTest, test52d2b69b185f6ccfff4c) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -2230,14 +2284,16 @@ TEST_F(GenEmitterTest, test784517e5fb6049b5eeb8) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testbb2a1aa3c8fb0b8c763f) { +TEST_F(GenEmitterTest, test44d442585e5bc9a7644a) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -2252,14 +2308,16 @@ TEST_F(GenEmitterTest, testbb2a1aa3c8fb0b8c763f) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testb360035c1b0988456eb8) { +TEST_F(GenEmitterTest, test3dc263684801dec471c9) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -2274,14 +2332,16 @@ TEST_F(GenEmitterTest, testb360035c1b0988456eb8) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test547ca5f2968b36666091) { +TEST_F(GenEmitterTest, testa04cde3245ad9b929b9a) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -2296,14 +2356,16 @@ TEST_F(GenEmitterTest, test547ca5f2968b36666091) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testcfb6b5ffda618b49a876) { +TEST_F(GenEmitterTest, testd911e740ca36e0509dfa) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -2318,14 +2380,16 @@ TEST_F(GenEmitterTest, testcfb6b5ffda618b49a876) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test0f42ce2ba53fb3e486f9) { +TEST_F(GenEmitterTest, testde44215fe9b2e87846ba) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -2340,14 +2404,16 @@ TEST_F(GenEmitterTest, test0f42ce2ba53fb3e486f9) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test93e437d10dbd42ac83bb) { +TEST_F(GenEmitterTest, test6390021323a4889f19d2) { Emitter out; out << BeginDoc; out << BeginSeq; @@ -2362,14 +2428,16 @@ TEST_F(GenEmitterTest, test93e437d10dbd42ac83bb) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test4267b4f75e3d9582d981) { +TEST_F(GenEmitterTest, test1db2fcb7347f6cb37dd4) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -2383,7 +2451,7 @@ TEST_F(GenEmitterTest, test4267b4f75e3d9582d981) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test62c1e6598c987e3d28a2) { +TEST_F(GenEmitterTest, test06b32e9d75498ee291d2) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -2397,7 +2465,7 @@ TEST_F(GenEmitterTest, test62c1e6598c987e3d28a2) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testbcf0ccd5a35fe73714b0) { +TEST_F(GenEmitterTest, test86654989004963952b15) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -2411,7 +2479,7 @@ TEST_F(GenEmitterTest, testbcf0ccd5a35fe73714b0) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa4c54e8a23771f781411) { +TEST_F(GenEmitterTest, test53d875fc5058faa44a4e) { Emitter out; out << BeginSeq; out << EndSeq; @@ -2425,7 +2493,7 @@ TEST_F(GenEmitterTest, testa4c54e8a23771f781411) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testad0a081525db9f568450) { +TEST_F(GenEmitterTest, test3f4b49a82b6e07eb11fd) { Emitter out; out << BeginSeq; out << EndSeq; @@ -2439,7 +2507,7 @@ TEST_F(GenEmitterTest, testad0a081525db9f568450) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test1c24a291665d1cc4404c) { +TEST_F(GenEmitterTest, testae4e2fa09d6a34077b6e) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -2452,7 +2520,7 @@ TEST_F(GenEmitterTest, test1c24a291665d1cc4404c) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testcb331bf2e56388df2f1a) { +TEST_F(GenEmitterTest, testb181b63559d96d5f848c) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -2465,7 +2533,7 @@ TEST_F(GenEmitterTest, testcb331bf2e56388df2f1a) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test122fe9269df7f8cb80f7) { +TEST_F(GenEmitterTest, test817661fec7d3730f4fa6) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -2478,7 +2546,7 @@ TEST_F(GenEmitterTest, test122fe9269df7f8cb80f7) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test6a09300420248adaddd4) { +TEST_F(GenEmitterTest, test34bb2700e9688718fa5a) { Emitter out; out << BeginSeq; out << EndSeq; @@ -2491,7 +2559,7 @@ TEST_F(GenEmitterTest, test6a09300420248adaddd4) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testf3bd03889c1e8dceb798) { +TEST_F(GenEmitterTest, test84e3c1999b6888d2e897) { Emitter out; out << BeginSeq; out << EndSeq; @@ -2504,7 +2572,7 @@ TEST_F(GenEmitterTest, testf3bd03889c1e8dceb798) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testce882fb9271babb66dc6) { +TEST_F(GenEmitterTest, testa9d113656780031a99f5) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -2520,7 +2588,7 @@ TEST_F(GenEmitterTest, testce882fb9271babb66dc6) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test9c237cf40d8848a18afd) { +TEST_F(GenEmitterTest, test1cd1ead50aaa7b827068) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -2536,7 +2604,7 @@ TEST_F(GenEmitterTest, test9c237cf40d8848a18afd) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testcadbaf942d41242c21fc) { +TEST_F(GenEmitterTest, test1389f95066b07eac89ef) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -2552,7 +2620,7 @@ TEST_F(GenEmitterTest, testcadbaf942d41242c21fc) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testfc6e5fb862b4ce920622) { +TEST_F(GenEmitterTest, test709f3a5c294f47f62c1e) { Emitter out; out << BeginSeq; out << "foo"; @@ -2568,7 +2636,7 @@ TEST_F(GenEmitterTest, testfc6e5fb862b4ce920622) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test4ecc85dc0cb57f446540) { +TEST_F(GenEmitterTest, test8a238d7fdee02a368203) { Emitter out; out << BeginSeq; out << "foo"; @@ -2584,7 +2652,7 @@ TEST_F(GenEmitterTest, test4ecc85dc0cb57f446540) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test4e844b231f7985238b21) { +TEST_F(GenEmitterTest, test0d13534e2949ea35ca96) { Emitter out; out << BeginSeq; out << "foo"; @@ -2600,7 +2668,7 @@ TEST_F(GenEmitterTest, test4e844b231f7985238b21) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test8ec201c2f040093428a7) { +TEST_F(GenEmitterTest, test10fe6827ed46e0e063a7) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -2615,7 +2683,7 @@ TEST_F(GenEmitterTest, test8ec201c2f040093428a7) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test92469ed608395adc2620) { +TEST_F(GenEmitterTest, testc7eb6d9da57005534c1c) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -2630,7 +2698,7 @@ TEST_F(GenEmitterTest, test92469ed608395adc2620) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test8a9d541f2dc9c468cbaa) { +TEST_F(GenEmitterTest, test3f424efd76e1d32727eb) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -2645,7 +2713,7 @@ TEST_F(GenEmitterTest, test8a9d541f2dc9c468cbaa) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test6a9392e1353590d282e2) { +TEST_F(GenEmitterTest, test2bdc361bc6b056f02465) { Emitter out; out << BeginSeq; out << "foo"; @@ -2660,7 +2728,7 @@ TEST_F(GenEmitterTest, test6a9392e1353590d282e2) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test87d8b037171651caa126) { +TEST_F(GenEmitterTest, test0cc1936afe5637ba1376) { Emitter out; out << BeginSeq; out << "foo"; @@ -2675,7 +2743,7 @@ TEST_F(GenEmitterTest, test87d8b037171651caa126) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test1b1bc972209abdacc529) { +TEST_F(GenEmitterTest, test7d3e2f793963d3480545) { Emitter out; out << BeginSeq; out << "foo"; @@ -2690,7 +2758,7 @@ TEST_F(GenEmitterTest, test1b1bc972209abdacc529) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test552483e6a5fe7eee1cc5) { +TEST_F(GenEmitterTest, testf3f50e76d7ef6e2b2bff) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -2707,7 +2775,7 @@ TEST_F(GenEmitterTest, test552483e6a5fe7eee1cc5) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test43d39704b3b5e188182a) { +TEST_F(GenEmitterTest, testcbf1cff67fec9148df1c) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -2724,7 +2792,7 @@ TEST_F(GenEmitterTest, test43d39704b3b5e188182a) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7318d9b71ec1a8f05621) { +TEST_F(GenEmitterTest, test168bd4b8dc78b4d524ee) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -2741,7 +2809,7 @@ TEST_F(GenEmitterTest, test7318d9b71ec1a8f05621) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test77302e5c536183072945) { +TEST_F(GenEmitterTest, testb616ef26030304bca6ef) { Emitter out; out << BeginSeq; out << VerbatimTag("tag"); @@ -2758,7 +2826,7 @@ TEST_F(GenEmitterTest, test77302e5c536183072945) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test5b740c51d614c5cedf1c) { +TEST_F(GenEmitterTest, test9fda976f36ddb23b38ee) { Emitter out; out << BeginSeq; out << VerbatimTag("tag"); @@ -2775,7 +2843,7 @@ TEST_F(GenEmitterTest, test5b740c51d614c5cedf1c) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testb66838e46cf76ce30c95) { +TEST_F(GenEmitterTest, test48e8c45c081edc86deb2) { Emitter out; out << BeginSeq; out << VerbatimTag("tag"); @@ -2792,7 +2860,7 @@ TEST_F(GenEmitterTest, testb66838e46cf76ce30c95) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test592cabeb320cc3d6a4a6) { +TEST_F(GenEmitterTest, test30f5136e817ddd8158de) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -2808,7 +2876,7 @@ TEST_F(GenEmitterTest, test592cabeb320cc3d6a4a6) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testdcc6e5388f6c2058954f) { +TEST_F(GenEmitterTest, testeb51d66281f593566172) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -2824,7 +2892,7 @@ TEST_F(GenEmitterTest, testdcc6e5388f6c2058954f) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test1ebbb7521464e6cc5da7) { +TEST_F(GenEmitterTest, testef6ffa5fa4658785ef00) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -2840,7 +2908,7 @@ TEST_F(GenEmitterTest, test1ebbb7521464e6cc5da7) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test8ccc7ae170ad81b12996) { +TEST_F(GenEmitterTest, test6db34efc6b59e8a7ba18) { Emitter out; out << BeginSeq; out << VerbatimTag("tag"); @@ -2856,7 +2924,7 @@ TEST_F(GenEmitterTest, test8ccc7ae170ad81b12996) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test6421c3c3ed7a65699e0b) { +TEST_F(GenEmitterTest, test537b9ecc9d9a5b546a9c) { Emitter out; out << BeginSeq; out << VerbatimTag("tag"); @@ -2872,7 +2940,7 @@ TEST_F(GenEmitterTest, test6421c3c3ed7a65699e0b) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test096939c5c407fed2178a) { +TEST_F(GenEmitterTest, testfadd6ee259c13382f5ce) { Emitter out; out << BeginSeq; out << VerbatimTag("tag"); @@ -2888,7 +2956,7 @@ TEST_F(GenEmitterTest, test096939c5c407fed2178a) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test1e79c736bdaf36bcc331) { +TEST_F(GenEmitterTest, test974ae82483391d01787b) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -2899,13 +2967,14 @@ TEST_F(GenEmitterTest, test1e79c736bdaf36bcc331) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa932875b266f62a32a15) { +TEST_F(GenEmitterTest, test7fc68b49cfe198b30eeb) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -2916,13 +2985,14 @@ TEST_F(GenEmitterTest, testa932875b266f62a32a15) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7211a0d0a7d7b8957fbd) { +TEST_F(GenEmitterTest, test41644c59ff95f8ec5ec2) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -2933,13 +3003,14 @@ TEST_F(GenEmitterTest, test7211a0d0a7d7b8957fbd) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testfe2ed84c5a19bea4324a) { +TEST_F(GenEmitterTest, testa3a24413b537aece4834) { Emitter out; out << BeginSeq; out << Anchor("anchor"); @@ -2950,13 +3021,14 @@ TEST_F(GenEmitterTest, testfe2ed84c5a19bea4324a) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test05fe79e124bcadf04952) { +TEST_F(GenEmitterTest, testc4516128af938868b120) { Emitter out; out << BeginSeq; out << Anchor("anchor"); @@ -2967,13 +3039,14 @@ TEST_F(GenEmitterTest, test05fe79e124bcadf04952) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test6deaaa4620537aec93bb) { +TEST_F(GenEmitterTest, testef3c20a56c8a3993cc2d) { Emitter out; out << BeginSeq; out << Anchor("anchor"); @@ -2984,13 +3057,14 @@ TEST_F(GenEmitterTest, test6deaaa4620537aec93bb) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testd8f4b7fd570238af0ac6) { +TEST_F(GenEmitterTest, test83aceee2ee6446347fba) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -3000,13 +3074,14 @@ TEST_F(GenEmitterTest, testd8f4b7fd570238af0ac6) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test6aa495401fa882fd6ef0) { +TEST_F(GenEmitterTest, test5a054d76c67b6de340e2) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -3016,13 +3091,14 @@ TEST_F(GenEmitterTest, test6aa495401fa882fd6ef0) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test3388236bb529c50f5341) { +TEST_F(GenEmitterTest, testc6706e6b6fc94d1e4752) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -3032,13 +3108,14 @@ TEST_F(GenEmitterTest, test3388236bb529c50f5341) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test79f4266262dffb3f8346) { +TEST_F(GenEmitterTest, test72f3ded341d6b5d21803) { Emitter out; out << BeginSeq; out << Anchor("anchor"); @@ -3048,13 +3125,14 @@ TEST_F(GenEmitterTest, test79f4266262dffb3f8346) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste858dd76c42bbd281706) { +TEST_F(GenEmitterTest, test7dc830828b604b5d1839) { Emitter out; out << BeginSeq; out << Anchor("anchor"); @@ -3064,13 +3142,14 @@ TEST_F(GenEmitterTest, teste858dd76c42bbd281706) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7487786b0131b1337e71) { +TEST_F(GenEmitterTest, test3a5baef0d6a62e5880ef) { Emitter out; out << BeginSeq; out << Anchor("anchor"); @@ -3080,13 +3159,14 @@ TEST_F(GenEmitterTest, test7487786b0131b1337e71) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa9b9110a8d2175a57e7c) { +TEST_F(GenEmitterTest, testfe7bf25b7a5525cab12a) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -3098,13 +3178,14 @@ TEST_F(GenEmitterTest, testa9b9110a8d2175a57e7c) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste99a7f40fb4d939e2da7) { +TEST_F(GenEmitterTest, test817bf3d583230e503f8e) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -3116,13 +3197,14 @@ TEST_F(GenEmitterTest, teste99a7f40fb4d939e2da7) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test0e253895bd9cff694f9a) { +TEST_F(GenEmitterTest, testab122e386b3e30ea59e2) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -3134,13 +3216,14 @@ TEST_F(GenEmitterTest, test0e253895bd9cff694f9a) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testf0a8ffd3a895826b093c) { +TEST_F(GenEmitterTest, test466c3e0dbec8e9660837) { Emitter out; out << BeginSeq; out << VerbatimTag("tag"); @@ -3152,13 +3235,14 @@ TEST_F(GenEmitterTest, testf0a8ffd3a895826b093c) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testdae2c374518234f70e9f) { +TEST_F(GenEmitterTest, test9fc49f92e554cd85e349) { Emitter out; out << BeginSeq; out << VerbatimTag("tag"); @@ -3170,13 +3254,14 @@ TEST_F(GenEmitterTest, testdae2c374518234f70e9f) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testc0dae4cd70b3f409cbb4) { +TEST_F(GenEmitterTest, testf9d2f39bdbd217d70868) { Emitter out; out << BeginSeq; out << VerbatimTag("tag"); @@ -3188,13 +3273,14 @@ TEST_F(GenEmitterTest, testc0dae4cd70b3f409cbb4) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testc26f714fb6f9b1ee6cf9) { +TEST_F(GenEmitterTest, test1ce3d77707f18ec48a19) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -3205,13 +3291,14 @@ TEST_F(GenEmitterTest, testc26f714fb6f9b1ee6cf9) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test9644620dcb35431e2969) { +TEST_F(GenEmitterTest, test71df6ecc32e49ea961d4) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -3222,13 +3309,14 @@ TEST_F(GenEmitterTest, test9644620dcb35431e2969) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test1cfceae5c8e4a64a43ae) { +TEST_F(GenEmitterTest, test8f37b0a6cc287f8c922f) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -3239,13 +3327,14 @@ TEST_F(GenEmitterTest, test1cfceae5c8e4a64a43ae) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test64f296d213a7ddc7738c) { +TEST_F(GenEmitterTest, testf992e2a1f7d737647506) { Emitter out; out << BeginSeq; out << VerbatimTag("tag"); @@ -3256,13 +3345,14 @@ TEST_F(GenEmitterTest, test64f296d213a7ddc7738c) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testb645b7ae7c95adc70e6f) { +TEST_F(GenEmitterTest, testd79381f97cdd0af81ae4) { Emitter out; out << BeginSeq; out << VerbatimTag("tag"); @@ -3273,13 +3363,14 @@ TEST_F(GenEmitterTest, testb645b7ae7c95adc70e6f) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test3a6fb33f542118758a78) { +TEST_F(GenEmitterTest, test74ca1feb5f0c520a8518) { Emitter out; out << BeginSeq; out << VerbatimTag("tag"); @@ -3290,13 +3381,14 @@ TEST_F(GenEmitterTest, test3a6fb33f542118758a78) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test98b9868c139b816dcc00) { +TEST_F(GenEmitterTest, teste86e6fd56707272c091b) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -3314,7 +3406,7 @@ TEST_F(GenEmitterTest, test98b9868c139b816dcc00) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test69526d609eb86d3b7917) { +TEST_F(GenEmitterTest, test1e6f73bc378c184c786b) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -3332,7 +3424,7 @@ TEST_F(GenEmitterTest, test69526d609eb86d3b7917) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testb569fe86774c96603a89) { +TEST_F(GenEmitterTest, test3fbac5e1aef66dc40bf7) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -3350,7 +3442,7 @@ TEST_F(GenEmitterTest, testb569fe86774c96603a89) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test03793bbef87d15c4ec74) { +TEST_F(GenEmitterTest, test558c4bf1c9c6e4e81e98) { Emitter out; out << BeginSeq; out << "foo"; @@ -3368,7 +3460,7 @@ TEST_F(GenEmitterTest, test03793bbef87d15c4ec74) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test508ca3314339f0dfb5c8) { +TEST_F(GenEmitterTest, testfa6d88b26c0072cddb26) { Emitter out; out << BeginSeq; out << "foo"; @@ -3386,7 +3478,7 @@ TEST_F(GenEmitterTest, test508ca3314339f0dfb5c8) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7c8a731b32213075b25a) { +TEST_F(GenEmitterTest, test40a5af3360fb3d9e79f1) { Emitter out; out << BeginSeq; out << "foo"; @@ -3404,7 +3496,7 @@ TEST_F(GenEmitterTest, test7c8a731b32213075b25a) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testb2a840af01cc1074e80f) { +TEST_F(GenEmitterTest, test451dd95b95b7e958bb03) { Emitter out; out << BeginSeq; out << "foo"; @@ -3422,7 +3514,7 @@ TEST_F(GenEmitterTest, testb2a840af01cc1074e80f) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test8e372218ea9564c579b6) { +TEST_F(GenEmitterTest, test1717ad2d772bafb9b573) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -3439,7 +3531,7 @@ TEST_F(GenEmitterTest, test8e372218ea9564c579b6) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test9135f186de91cf9e7538) { +TEST_F(GenEmitterTest, testedc6737e8b2f5b23b42e) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -3456,7 +3548,7 @@ TEST_F(GenEmitterTest, test9135f186de91cf9e7538) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test81be571777fd06470d73) { +TEST_F(GenEmitterTest, test771c7d28c0b8c184e2c7) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -3473,7 +3565,7 @@ TEST_F(GenEmitterTest, test81be571777fd06470d73) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7614d4928827481a2d8e) { +TEST_F(GenEmitterTest, test469a446f0b22e9b6d269) { Emitter out; out << BeginSeq; out << "foo"; @@ -3490,7 +3582,7 @@ TEST_F(GenEmitterTest, test7614d4928827481a2d8e) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste21f9902a4a5e3c73628) { +TEST_F(GenEmitterTest, testec45b0503f312be47336) { Emitter out; out << BeginSeq; out << "foo"; @@ -3507,7 +3599,7 @@ TEST_F(GenEmitterTest, teste21f9902a4a5e3c73628) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test879d7957916fb5526b7e) { +TEST_F(GenEmitterTest, test1bfc4f39d6730acb6a12) { Emitter out; out << BeginSeq; out << "foo"; @@ -3524,7 +3616,7 @@ TEST_F(GenEmitterTest, test879d7957916fb5526b7e) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test8e4e2b3618c7fe67384b) { +TEST_F(GenEmitterTest, test9bc9a72ad06084dc8cf8) { Emitter out; out << BeginSeq; out << "foo"; @@ -3541,7 +3633,7 @@ TEST_F(GenEmitterTest, test8e4e2b3618c7fe67384b) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test5e8672f96ce5a11b846a) { +TEST_F(GenEmitterTest, test62c996cdfc1d3b77b7ec) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -3556,14 +3648,16 @@ TEST_F(GenEmitterTest, test5e8672f96ce5a11b846a) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test26c021c876f1ef91cff4) { +TEST_F(GenEmitterTest, test1d038936a340d5bef490) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -3578,14 +3672,16 @@ TEST_F(GenEmitterTest, test26c021c876f1ef91cff4) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test04da690e5c32b7bf1dc3) { +TEST_F(GenEmitterTest, test7057f64ac570dbe3c1ca) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -3600,14 +3696,16 @@ TEST_F(GenEmitterTest, test04da690e5c32b7bf1dc3) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test4bf435d6bad0ca7f8016) { +TEST_F(GenEmitterTest, testbfe0890de3ffc73f0f9d) { Emitter out; out << BeginSeq; out << VerbatimTag("tag"); @@ -3622,14 +3720,16 @@ TEST_F(GenEmitterTest, test4bf435d6bad0ca7f8016) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test38a40c04ceadf66cb77a) { +TEST_F(GenEmitterTest, test5faa7320a493247b4f8b) { Emitter out; out << BeginSeq; out << VerbatimTag("tag"); @@ -3644,14 +3744,16 @@ TEST_F(GenEmitterTest, test38a40c04ceadf66cb77a) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test73f543da75154971fa58) { +TEST_F(GenEmitterTest, test929fbc93b3d6d98b1f0a) { Emitter out; out << BeginSeq; out << VerbatimTag("tag"); @@ -3666,14 +3768,16 @@ TEST_F(GenEmitterTest, test73f543da75154971fa58) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test9c2a6b8e53a71cc271f1) { +TEST_F(GenEmitterTest, testcc7d1ad7797581b37549) { Emitter out; out << BeginSeq; out << VerbatimTag("tag"); @@ -3688,14 +3792,16 @@ TEST_F(GenEmitterTest, test9c2a6b8e53a71cc271f1) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test76e7370aa293790ca0b6) { +TEST_F(GenEmitterTest, test1115ba981ba8f739ddf2) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -3709,14 +3815,16 @@ TEST_F(GenEmitterTest, test76e7370aa293790ca0b6) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test530430c212524fd2d917) { +TEST_F(GenEmitterTest, testf7ca743a82040e1313a8) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -3730,14 +3838,16 @@ TEST_F(GenEmitterTest, test530430c212524fd2d917) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testdc001467ce9060c3e34f) { +TEST_F(GenEmitterTest, testa4e0257ad6c987178ca4) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -3751,14 +3861,16 @@ TEST_F(GenEmitterTest, testdc001467ce9060c3e34f) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste650915c87ea88e85b7d) { +TEST_F(GenEmitterTest, testb65ceea0d4080b44180e) { Emitter out; out << BeginSeq; out << VerbatimTag("tag"); @@ -3772,14 +3884,16 @@ TEST_F(GenEmitterTest, teste650915c87ea88e85b7d) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testc288c80940cbb3539620) { +TEST_F(GenEmitterTest, test4fcd60d48dbd7b07e289) { Emitter out; out << BeginSeq; out << VerbatimTag("tag"); @@ -3793,14 +3907,16 @@ TEST_F(GenEmitterTest, testc288c80940cbb3539620) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test18256634c494bbf715ac) { +TEST_F(GenEmitterTest, test92704937d4e130b43390) { Emitter out; out << BeginSeq; out << VerbatimTag("tag"); @@ -3814,14 +3930,16 @@ TEST_F(GenEmitterTest, test18256634c494bbf715ac) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testfaecbb520871c68e74c2) { +TEST_F(GenEmitterTest, test029a31902f93dfa9ea7b) { Emitter out; out << BeginSeq; out << VerbatimTag("tag"); @@ -3835,14 +3953,16 @@ TEST_F(GenEmitterTest, testfaecbb520871c68e74c2) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testd3b1e7d0410f03b69666) { +TEST_F(GenEmitterTest, test40b4e7494e5b850d26f4) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -3857,7 +3977,7 @@ TEST_F(GenEmitterTest, testd3b1e7d0410f03b69666) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test2654cfdffd9be4c24917) { +TEST_F(GenEmitterTest, test64d2ab5993b67281212b) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -3872,7 +3992,7 @@ TEST_F(GenEmitterTest, test2654cfdffd9be4c24917) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testad5fd5e6d524dd2c4907) { +TEST_F(GenEmitterTest, teste71b9b975d71c18a2897) { Emitter out; out << BeginDoc; out << BeginMap; @@ -3887,7 +4007,7 @@ TEST_F(GenEmitterTest, testad5fd5e6d524dd2c4907) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testb1b59e0e48f25bf90045) { +TEST_F(GenEmitterTest, test138039761e432a5ba11e) { Emitter out; out << BeginDoc; out << BeginMap; @@ -3902,7 +4022,7 @@ TEST_F(GenEmitterTest, testb1b59e0e48f25bf90045) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test6a1cd91064a302335507) { +TEST_F(GenEmitterTest, test6684d2eacb3f094bfc84) { Emitter out; out << BeginDoc; out << BeginMap; @@ -3917,7 +4037,7 @@ TEST_F(GenEmitterTest, test6a1cd91064a302335507) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7542cfaba20c029d74d2) { +TEST_F(GenEmitterTest, test8624a705f2167d4db358) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -3931,7 +4051,7 @@ TEST_F(GenEmitterTest, test7542cfaba20c029d74d2) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7c64ec9fde647f95ae64) { +TEST_F(GenEmitterTest, test90877a1ec609edb69bce) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -3945,7 +4065,7 @@ TEST_F(GenEmitterTest, test7c64ec9fde647f95ae64) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testbba41212c116596476f3) { +TEST_F(GenEmitterTest, test5f925d3c910a7e32bb99) { Emitter out; out << BeginDoc; out << BeginMap; @@ -3959,7 +4079,7 @@ TEST_F(GenEmitterTest, testbba41212c116596476f3) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test66a3e0c8ba0580adcce7) { +TEST_F(GenEmitterTest, testffeb4955bf4ee9510a88) { Emitter out; out << BeginDoc; out << BeginMap; @@ -3973,7 +4093,7 @@ TEST_F(GenEmitterTest, test66a3e0c8ba0580adcce7) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test201f78790b978c826f38) { +TEST_F(GenEmitterTest, test769ee82c3bfc52d7a85d) { Emitter out; out << BeginDoc; out << BeginMap; @@ -3987,7 +4107,7 @@ TEST_F(GenEmitterTest, test201f78790b978c826f38) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test85630834239ca1a21b5f) { +TEST_F(GenEmitterTest, testdc4e16b5a48fe16102b4) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -4006,7 +4126,7 @@ TEST_F(GenEmitterTest, test85630834239ca1a21b5f) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test6e4aaceae87fea59c777) { +TEST_F(GenEmitterTest, testd3c578e5b5a6813a73c7) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -4025,7 +4145,7 @@ TEST_F(GenEmitterTest, test6e4aaceae87fea59c777) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test430815076958c69dc3ae) { +TEST_F(GenEmitterTest, test0034b2c9905b34f7f22e) { Emitter out; out << BeginDoc; out << BeginMap; @@ -4044,7 +4164,7 @@ TEST_F(GenEmitterTest, test430815076958c69dc3ae) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test699eb267a6012eb16178) { +TEST_F(GenEmitterTest, teste911e620becf080a4d96) { Emitter out; out << BeginDoc; out << BeginMap; @@ -4063,7 +4183,7 @@ TEST_F(GenEmitterTest, test699eb267a6012eb16178) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testf51a095fb67ab6d7a2c9) { +TEST_F(GenEmitterTest, test7f8bbf619609651a2e55) { Emitter out; out << BeginDoc; out << BeginMap; @@ -4082,7 +4202,7 @@ TEST_F(GenEmitterTest, testf51a095fb67ab6d7a2c9) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test9c926b68cb956ee2c349) { +TEST_F(GenEmitterTest, test2974bda177bed72619f4) { Emitter out; out << BeginDoc; out << BeginMap; @@ -4101,7 +4221,7 @@ TEST_F(GenEmitterTest, test9c926b68cb956ee2c349) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testeafd3facc48783e0e3a5) { +TEST_F(GenEmitterTest, testbc7a1599883ed8c27262) { Emitter out; out << BeginDoc; out << BeginMap; @@ -4120,7 +4240,7 @@ TEST_F(GenEmitterTest, testeafd3facc48783e0e3a5) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testd702fb9ab5607d2ac819) { +TEST_F(GenEmitterTest, test323e14a02e02b94939fb) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -4138,7 +4258,7 @@ TEST_F(GenEmitterTest, testd702fb9ab5607d2ac819) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste442f82a0e6799f2610c) { +TEST_F(GenEmitterTest, test705ff113324bf0b4897c) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -4156,7 +4276,7 @@ TEST_F(GenEmitterTest, teste442f82a0e6799f2610c) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test60c91197fb0bb0c6abc3) { +TEST_F(GenEmitterTest, test587f5739ba58f0e21e0e) { Emitter out; out << BeginDoc; out << BeginMap; @@ -4174,7 +4294,7 @@ TEST_F(GenEmitterTest, test60c91197fb0bb0c6abc3) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testb51cf53880c7efae7f00) { +TEST_F(GenEmitterTest, test31a8c7da96ebe3da3f6e) { Emitter out; out << BeginDoc; out << BeginMap; @@ -4192,7 +4312,7 @@ TEST_F(GenEmitterTest, testb51cf53880c7efae7f00) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test015d48eead15f53dda15) { +TEST_F(GenEmitterTest, test0b6fe270e4cf9fc21181) { Emitter out; out << BeginDoc; out << BeginMap; @@ -4210,7 +4330,7 @@ TEST_F(GenEmitterTest, test015d48eead15f53dda15) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa6ef6e851b7c9bb8695a) { +TEST_F(GenEmitterTest, testaf5869c722ea0dfb3394) { Emitter out; out << BeginDoc; out << BeginMap; @@ -4228,7 +4348,7 @@ TEST_F(GenEmitterTest, testa6ef6e851b7c9bb8695a) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test77f35be9920c06becdb3) { +TEST_F(GenEmitterTest, testc348837f92793a778246) { Emitter out; out << BeginDoc; out << BeginMap; @@ -4246,7 +4366,7 @@ TEST_F(GenEmitterTest, test77f35be9920c06becdb3) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testdabd5e4aaaf01a76ac53) { +TEST_F(GenEmitterTest, test9d26ae9ec8db76a06a6f) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -4262,14 +4382,16 @@ TEST_F(GenEmitterTest, testdabd5e4aaaf01a76ac53) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testfdfbe118771b6de1e966) { +TEST_F(GenEmitterTest, test28691969bbaa41191640) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -4285,14 +4407,16 @@ TEST_F(GenEmitterTest, testfdfbe118771b6de1e966) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test4153b34f6f6392539a57) { +TEST_F(GenEmitterTest, testb38c27cd2556a14bb479) { Emitter out; out << BeginDoc; out << BeginMap; @@ -4308,14 +4432,16 @@ TEST_F(GenEmitterTest, test4153b34f6f6392539a57) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test73cfd1e2fec4af9bcd24) { +TEST_F(GenEmitterTest, test1103d3c99e3525075da6) { Emitter out; out << BeginDoc; out << BeginMap; @@ -4331,14 +4457,16 @@ TEST_F(GenEmitterTest, test73cfd1e2fec4af9bcd24) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test9a25bda309eadfbe8323) { +TEST_F(GenEmitterTest, testeb7edb5d1dfd039c72c3) { Emitter out; out << BeginDoc; out << BeginMap; @@ -4354,14 +4482,16 @@ TEST_F(GenEmitterTest, test9a25bda309eadfbe8323) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7600d72d8bd5c481b7d2) { +TEST_F(GenEmitterTest, testa9862d708fcb755db479) { Emitter out; out << BeginDoc; out << BeginMap; @@ -4377,14 +4507,16 @@ TEST_F(GenEmitterTest, test7600d72d8bd5c481b7d2) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste03fdb7c4a58b419523d) { +TEST_F(GenEmitterTest, testae3e98286336f0c5d2af) { Emitter out; out << BeginDoc; out << BeginMap; @@ -4400,14 +4532,16 @@ TEST_F(GenEmitterTest, teste03fdb7c4a58b419523d) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testcfc06e7baf582f834f85) { +TEST_F(GenEmitterTest, test8bd970000ae21619e864) { Emitter out; out << Comment("comment"); out << BeginDoc; @@ -4422,14 +4556,16 @@ TEST_F(GenEmitterTest, testcfc06e7baf582f834f85) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test355c684d237adcf5d852) { +TEST_F(GenEmitterTest, test0a960fe3efeeb1b4fafe) { Emitter out; out << BeginDoc; out << Comment("comment"); @@ -4444,14 +4580,16 @@ TEST_F(GenEmitterTest, test355c684d237adcf5d852) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testbc2e12df3c174bd6b7e3) { +TEST_F(GenEmitterTest, testffec1dcba9a2622b57a3) { Emitter out; out << BeginDoc; out << BeginMap; @@ -4466,14 +4604,16 @@ TEST_F(GenEmitterTest, testbc2e12df3c174bd6b7e3) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test47220f053e2788618f28) { +TEST_F(GenEmitterTest, test9a181b6042027e7977bf) { Emitter out; out << BeginDoc; out << BeginMap; @@ -4488,14 +4628,16 @@ TEST_F(GenEmitterTest, test47220f053e2788618f28) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa71dd9a65f4e9563d114) { +TEST_F(GenEmitterTest, test5b42728bff7e0dd63ae8) { Emitter out; out << BeginDoc; out << BeginMap; @@ -4510,14 +4652,16 @@ TEST_F(GenEmitterTest, testa71dd9a65f4e9563d114) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test188c5ac5c1d6e2174110) { +TEST_F(GenEmitterTest, testa17514c4db3a70fe5084) { Emitter out; out << BeginDoc; out << BeginMap; @@ -4532,14 +4676,16 @@ TEST_F(GenEmitterTest, test188c5ac5c1d6e2174110) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testdc89b13ed8a4694f0296) { +TEST_F(GenEmitterTest, test2ac903a52c526db4b34b) { Emitter out; out << BeginDoc; out << BeginMap; @@ -4554,14 +4700,16 @@ TEST_F(GenEmitterTest, testdc89b13ed8a4694f0296) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test91fe618a569a60fa75d0) { +TEST_F(GenEmitterTest, testbebc6bc66d04a91bfa9c) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -4575,7 +4723,7 @@ TEST_F(GenEmitterTest, test91fe618a569a60fa75d0) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test1f18c55487cda597929f) { +TEST_F(GenEmitterTest, test0918e247384bfc94d831) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -4589,7 +4737,7 @@ TEST_F(GenEmitterTest, test1f18c55487cda597929f) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa74f5aa5747c1ec09ac2) { +TEST_F(GenEmitterTest, testf8512b2ebdaad8ae4cae) { Emitter out; out << BeginMap; out << Comment("comment"); @@ -4603,7 +4751,7 @@ TEST_F(GenEmitterTest, testa74f5aa5747c1ec09ac2) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testda71284d14e9f5902fe5) { +TEST_F(GenEmitterTest, test01a1d249079c380030ca) { Emitter out; out << BeginMap; out << EndMap; @@ -4617,7 +4765,7 @@ TEST_F(GenEmitterTest, testda71284d14e9f5902fe5) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testb041a1dda939d84dd6ed) { +TEST_F(GenEmitterTest, testcb48737e9c352108dc56) { Emitter out; out << BeginMap; out << EndMap; @@ -4631,7 +4779,7 @@ TEST_F(GenEmitterTest, testb041a1dda939d84dd6ed) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test0f39f734136f83edaab4) { +TEST_F(GenEmitterTest, testdea8106f3dce46929197) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -4644,7 +4792,7 @@ TEST_F(GenEmitterTest, test0f39f734136f83edaab4) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste8eed1f3ab25f5395d7b) { +TEST_F(GenEmitterTest, test2b91aa87abdaa0fc0b20) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -4657,7 +4805,7 @@ TEST_F(GenEmitterTest, teste8eed1f3ab25f5395d7b) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test3c7e3bbca86317884080) { +TEST_F(GenEmitterTest, test9c8b1fe0c5bbbf6a787e) { Emitter out; out << BeginMap; out << Comment("comment"); @@ -4670,7 +4818,7 @@ TEST_F(GenEmitterTest, test3c7e3bbca86317884080) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testdc6b30ad8f00369e0597) { +TEST_F(GenEmitterTest, test8808d4be9571f365f79a) { Emitter out; out << BeginMap; out << EndMap; @@ -4683,7 +4831,7 @@ TEST_F(GenEmitterTest, testdc6b30ad8f00369e0597) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa905ff4b380f9fbbb630) { +TEST_F(GenEmitterTest, teste77c95c5163513fa25c5) { Emitter out; out << BeginMap; out << EndMap; @@ -4696,7 +4844,7 @@ TEST_F(GenEmitterTest, testa905ff4b380f9fbbb630) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7143b34a608a3c7dc4bf) { +TEST_F(GenEmitterTest, testa3ed6e26dac366240579) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -4714,7 +4862,7 @@ TEST_F(GenEmitterTest, test7143b34a608a3c7dc4bf) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test3f56e373d59464d85912) { +TEST_F(GenEmitterTest, test136adbd0ad47d74cfa22) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -4732,7 +4880,7 @@ TEST_F(GenEmitterTest, test3f56e373d59464d85912) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test8790906cd88c45aba794) { +TEST_F(GenEmitterTest, test77f384e8387e39b54691) { Emitter out; out << BeginMap; out << Comment("comment"); @@ -4750,7 +4898,7 @@ TEST_F(GenEmitterTest, test8790906cd88c45aba794) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7eef04e795fe3d520c6f) { +TEST_F(GenEmitterTest, testf8f016177cf9e428fcd4) { Emitter out; out << BeginMap; out << "foo"; @@ -4768,7 +4916,7 @@ TEST_F(GenEmitterTest, test7eef04e795fe3d520c6f) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test3378c3dc3604de62c507) { +TEST_F(GenEmitterTest, test1cec69d3c95937f4137a) { Emitter out; out << BeginMap; out << "foo"; @@ -4786,7 +4934,7 @@ TEST_F(GenEmitterTest, test3378c3dc3604de62c507) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste9742c9cbd88de777d38) { +TEST_F(GenEmitterTest, testb1fe1a5c5c064bdfe505) { Emitter out; out << BeginMap; out << "foo"; @@ -4804,7 +4952,7 @@ TEST_F(GenEmitterTest, teste9742c9cbd88de777d38) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testb74cac7a45f30159f880) { +TEST_F(GenEmitterTest, test14200fdf4de8797d8dfb) { Emitter out; out << BeginMap; out << "foo"; @@ -4822,7 +4970,7 @@ TEST_F(GenEmitterTest, testb74cac7a45f30159f880) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa4475a6e0ca5a46213db) { +TEST_F(GenEmitterTest, testde7595a96199f66d7ac0) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -4839,7 +4987,7 @@ TEST_F(GenEmitterTest, testa4475a6e0ca5a46213db) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7aa5535404499fd9e6fe) { +TEST_F(GenEmitterTest, testb1434e1f508509c0ade4) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -4856,7 +5004,7 @@ TEST_F(GenEmitterTest, test7aa5535404499fd9e6fe) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test75a57ca05218b76d7aa1) { +TEST_F(GenEmitterTest, test0d3bd788298201abbe67) { Emitter out; out << BeginMap; out << Comment("comment"); @@ -4873,7 +5021,7 @@ TEST_F(GenEmitterTest, test75a57ca05218b76d7aa1) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test973f12b1e7cdd047a330) { +TEST_F(GenEmitterTest, test3c716f5c232001f04805) { Emitter out; out << BeginMap; out << "foo"; @@ -4890,7 +5038,7 @@ TEST_F(GenEmitterTest, test973f12b1e7cdd047a330) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test75086003fa734ba2e64c) { +TEST_F(GenEmitterTest, testa55ef29eecbda5bc5b69) { Emitter out; out << BeginMap; out << "foo"; @@ -4907,7 +5055,7 @@ TEST_F(GenEmitterTest, test75086003fa734ba2e64c) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testef9ab805717a642f5d50) { +TEST_F(GenEmitterTest, test55ddd593defa5ee8da90) { Emitter out; out << BeginMap; out << "foo"; @@ -4924,7 +5072,7 @@ TEST_F(GenEmitterTest, testef9ab805717a642f5d50) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testbbe1014c67cbcd9bff8f) { +TEST_F(GenEmitterTest, test7326f87fd5c3adff317b) { Emitter out; out << BeginMap; out << "foo"; @@ -4941,7 +5089,7 @@ TEST_F(GenEmitterTest, testbbe1014c67cbcd9bff8f) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa0fae19726738031a50d) { +TEST_F(GenEmitterTest, test5ebc413d376f3b965879) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -4956,14 +5104,16 @@ TEST_F(GenEmitterTest, testa0fae19726738031a50d) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test8cf4c10b22758615f5dc) { +TEST_F(GenEmitterTest, test4c7159334e528e2cfff8) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -4978,14 +5128,16 @@ TEST_F(GenEmitterTest, test8cf4c10b22758615f5dc) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test777130969e538d6086d6) { +TEST_F(GenEmitterTest, test6a6bc06cdfee9f58a094) { Emitter out; out << BeginMap; out << Comment("comment"); @@ -5000,14 +5152,16 @@ TEST_F(GenEmitterTest, test777130969e538d6086d6) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test5ab6ba08277cd6a6a349) { +TEST_F(GenEmitterTest, test0beedfaace1b1e71d0c6) { Emitter out; out << BeginMap; out << VerbatimTag("tag"); @@ -5022,14 +5176,16 @@ TEST_F(GenEmitterTest, test5ab6ba08277cd6a6a349) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test4e6b76c47d712e10f181) { +TEST_F(GenEmitterTest, test9f65fafc369193908b7b) { Emitter out; out << BeginMap; out << VerbatimTag("tag"); @@ -5044,14 +5200,16 @@ TEST_F(GenEmitterTest, test4e6b76c47d712e10f181) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test0ccc3ac76a8810b05ab3) { +TEST_F(GenEmitterTest, test3a5c3ac504d7a58a08ca) { Emitter out; out << BeginMap; out << VerbatimTag("tag"); @@ -5066,14 +5224,16 @@ TEST_F(GenEmitterTest, test0ccc3ac76a8810b05ab3) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test3def4b737140116db9f9) { +TEST_F(GenEmitterTest, testc007513c868038dd3a68) { Emitter out; out << BeginMap; out << VerbatimTag("tag"); @@ -5088,14 +5248,16 @@ TEST_F(GenEmitterTest, test3def4b737140116db9f9) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test9ca096634f9d9cec9b36) { +TEST_F(GenEmitterTest, test89f3ba065cbd341381ec) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -5109,14 +5271,16 @@ TEST_F(GenEmitterTest, test9ca096634f9d9cec9b36) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testbf2b7d7182dae8038726) { +TEST_F(GenEmitterTest, test692c2652cee84e90c096) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -5130,14 +5294,16 @@ TEST_F(GenEmitterTest, testbf2b7d7182dae8038726) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa3528cc9ec7b90fc1d8d) { +TEST_F(GenEmitterTest, test761fba62f7617a03fbf0) { Emitter out; out << BeginMap; out << Comment("comment"); @@ -5151,14 +5317,16 @@ TEST_F(GenEmitterTest, testa3528cc9ec7b90fc1d8d) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, testf5be0253b15048a37e3a) { +TEST_F(GenEmitterTest, teste960a69bc06912eb8c76) { Emitter out; out << BeginMap; out << VerbatimTag("tag"); @@ -5172,14 +5340,16 @@ TEST_F(GenEmitterTest, testf5be0253b15048a37e3a) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste338a8f7f7aa9b63cddb) { +TEST_F(GenEmitterTest, test8f6187c6c2419dbf1770) { Emitter out; out << BeginMap; out << VerbatimTag("tag"); @@ -5193,14 +5363,16 @@ TEST_F(GenEmitterTest, teste338a8f7f7aa9b63cddb) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test3628377ede539d44f975) { +TEST_F(GenEmitterTest, testba6cb3810a074fabc55e) { Emitter out; out << BeginMap; out << VerbatimTag("tag"); @@ -5214,14 +5386,16 @@ TEST_F(GenEmitterTest, test3628377ede539d44f975) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test6eb2c2967a88d82d83d9) { +TEST_F(GenEmitterTest, testac695c3621ec3f104672) { Emitter out; out << BeginMap; out << VerbatimTag("tag"); @@ -5235,14 +5409,16 @@ TEST_F(GenEmitterTest, test6eb2c2967a88d82d83d9) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, _)); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "tag", 1, "foo")); + EXPECT_CALL(handler, OnAnchor(_, "other")); EXPECT_CALL(handler, OnScalar(_, "tag", 2, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -TEST_F(GenEmitterTest, test03515aba5b291049c262) { +TEST_F(GenEmitterTest, test86494a6bcb6a65e7029e) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -5259,7 +5435,7 @@ TEST_F(GenEmitterTest, test03515aba5b291049c262) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test20eea0df7f54b919cb92) { +TEST_F(GenEmitterTest, testb406fb13323c199d709c) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -5276,7 +5452,7 @@ TEST_F(GenEmitterTest, test20eea0df7f54b919cb92) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test6c6ab6f66ce2828d26cd) { +TEST_F(GenEmitterTest, test4409f685a3e80b9ab415) { Emitter out; out << BeginMap; out << Comment("comment"); @@ -5293,7 +5469,7 @@ TEST_F(GenEmitterTest, test6c6ab6f66ce2828d26cd) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7f415ecadae422f7b0f5) { +TEST_F(GenEmitterTest, testa74ace9c1f5e18cf3f2a) { Emitter out; out << BeginMap; out << "foo"; @@ -5310,7 +5486,7 @@ TEST_F(GenEmitterTest, test7f415ecadae422f7b0f5) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test0797d220a5428528ec87) { +TEST_F(GenEmitterTest, testabfc8ce2ca4c3dafa013) { Emitter out; out << BeginMap; out << "foo"; @@ -5327,7 +5503,7 @@ TEST_F(GenEmitterTest, test0797d220a5428528ec87) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test6e29f19c88864559a43e) { +TEST_F(GenEmitterTest, test07ff4bbae6104c4e30c1) { Emitter out; out << BeginMap; out << "foo"; @@ -5344,7 +5520,7 @@ TEST_F(GenEmitterTest, test6e29f19c88864559a43e) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test0fe24accf63e33a71494) { +TEST_F(GenEmitterTest, test1e3559cacab6d46c98fe) { Emitter out; out << BeginMap; out << "foo"; @@ -5361,7 +5537,7 @@ TEST_F(GenEmitterTest, test0fe24accf63e33a71494) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test6cc44b957e440b365fbc) { +TEST_F(GenEmitterTest, test795830e12e5a20213a7e) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -5382,7 +5558,7 @@ TEST_F(GenEmitterTest, test6cc44b957e440b365fbc) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test5de19a26e7af5459141b) { +TEST_F(GenEmitterTest, test849f2c88c71734fcf3f3) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -5403,7 +5579,7 @@ TEST_F(GenEmitterTest, test5de19a26e7af5459141b) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testea71fb07f12c70473a81) { +TEST_F(GenEmitterTest, test7bb139ac1f14e8ae04e2) { Emitter out; out << BeginMap; out << Comment("comment"); @@ -5424,7 +5600,7 @@ TEST_F(GenEmitterTest, testea71fb07f12c70473a81) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa70d56c89e5219a106b6) { +TEST_F(GenEmitterTest, test58655e359c60bf73986f) { Emitter out; out << BeginMap; out << "foo"; @@ -5445,7 +5621,7 @@ TEST_F(GenEmitterTest, testa70d56c89e5219a106b6) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test9eac2d394b9528ccd982) { +TEST_F(GenEmitterTest, testde9f70648448cbd37245) { Emitter out; out << BeginMap; out << "foo"; @@ -5466,7 +5642,7 @@ TEST_F(GenEmitterTest, test9eac2d394b9528ccd982) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test25b8b26feb1a8e5e50f9) { +TEST_F(GenEmitterTest, testfff25037c90a64db8771) { Emitter out; out << BeginMap; out << "foo"; @@ -5487,7 +5663,7 @@ TEST_F(GenEmitterTest, test25b8b26feb1a8e5e50f9) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testc9498e8d4545fb7ba842) { +TEST_F(GenEmitterTest, test94b24a286074cac9b881) { Emitter out; out << BeginMap; out << "foo"; @@ -5508,7 +5684,7 @@ TEST_F(GenEmitterTest, testc9498e8d4545fb7ba842) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testaf3f79c8ce6b65a71427) { +TEST_F(GenEmitterTest, test0c678fe6c6dbd3ccf4eb) { Emitter out; out << BeginMap; out << "foo"; @@ -5529,7 +5705,7 @@ TEST_F(GenEmitterTest, testaf3f79c8ce6b65a71427) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test921c297e990d295cd067) { +TEST_F(GenEmitterTest, test15f6ce577f139b9f1b61) { Emitter out; out << BeginMap; out << "foo"; @@ -5550,7 +5726,7 @@ TEST_F(GenEmitterTest, test921c297e990d295cd067) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testd61d8ef3753e51e671a8) { +TEST_F(GenEmitterTest, test5e927c8865f44b5c1abe) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -5573,7 +5749,7 @@ TEST_F(GenEmitterTest, testd61d8ef3753e51e671a8) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test8fa800a208cdaa3e20d7) { +TEST_F(GenEmitterTest, test235aebc60786962899f1) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -5596,7 +5772,7 @@ TEST_F(GenEmitterTest, test8fa800a208cdaa3e20d7) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testdf78d6aa9976557adf35) { +TEST_F(GenEmitterTest, test45e109e1bc3ca312091d) { Emitter out; out << BeginMap; out << Comment("comment"); @@ -5619,7 +5795,7 @@ TEST_F(GenEmitterTest, testdf78d6aa9976557adf35) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testf13bfc9be619d52da2b9) { +TEST_F(GenEmitterTest, test9a58086d44719b21c6b3) { Emitter out; out << BeginMap; out << "foo"; @@ -5642,7 +5818,7 @@ TEST_F(GenEmitterTest, testf13bfc9be619d52da2b9) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testd69830b6ed705995e364) { +TEST_F(GenEmitterTest, testa3ac3fa06ae69e9f5c9d) { Emitter out; out << BeginMap; out << "foo"; @@ -5665,7 +5841,7 @@ TEST_F(GenEmitterTest, testd69830b6ed705995e364) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste41087bf41e163aa315d) { +TEST_F(GenEmitterTest, test9ccaf628d78cc8f27857) { Emitter out; out << BeginMap; out << "foo"; @@ -5688,7 +5864,7 @@ TEST_F(GenEmitterTest, teste41087bf41e163aa315d) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testf46aa6778b48f4a04e21) { +TEST_F(GenEmitterTest, test6b8483101720027fd945) { Emitter out; out << BeginMap; out << "foo"; @@ -5711,7 +5887,7 @@ TEST_F(GenEmitterTest, testf46aa6778b48f4a04e21) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste017eaffcd10bfedf757) { +TEST_F(GenEmitterTest, test1549a08694b053f8a2cb) { Emitter out; out << BeginMap; out << "foo"; @@ -5734,7 +5910,7 @@ TEST_F(GenEmitterTest, teste017eaffcd10bfedf757) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test1cd2c3e073dac695dfdb) { +TEST_F(GenEmitterTest, test0417f66daae22676ad66) { Emitter out; out << BeginMap; out << "foo"; @@ -5757,7 +5933,7 @@ TEST_F(GenEmitterTest, test1cd2c3e073dac695dfdb) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testd2eb393135a7a84aea37) { +TEST_F(GenEmitterTest, test6b3d4384d27d0ac90b01) { Emitter out; out << BeginMap; out << "foo"; @@ -5780,7 +5956,7 @@ TEST_F(GenEmitterTest, testd2eb393135a7a84aea37) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test79b4dcb868412729afed) { +TEST_F(GenEmitterTest, testbf166fa245c204799ea8) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -5801,7 +5977,7 @@ TEST_F(GenEmitterTest, test79b4dcb868412729afed) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test379fd004b428ddfbabe2) { +TEST_F(GenEmitterTest, testdf279b50896e8f084ed3) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -5822,7 +5998,7 @@ TEST_F(GenEmitterTest, test379fd004b428ddfbabe2) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test5c13b45235bb1b7e36a9) { +TEST_F(GenEmitterTest, test7d9b55fe33dfdc6cf930) { Emitter out; out << BeginMap; out << Comment("comment"); @@ -5843,7 +6019,7 @@ TEST_F(GenEmitterTest, test5c13b45235bb1b7e36a9) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test95b9c0c89b4cd2841446) { +TEST_F(GenEmitterTest, test2b0f0825ac5d9ac3baf7) { Emitter out; out << BeginMap; out << BeginSeq; @@ -5864,7 +6040,7 @@ TEST_F(GenEmitterTest, test95b9c0c89b4cd2841446) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test14810a0d0234bee070a2) { +TEST_F(GenEmitterTest, teste4865b227f48a727aafe) { Emitter out; out << BeginMap; out << BeginSeq; @@ -5885,7 +6061,7 @@ TEST_F(GenEmitterTest, test14810a0d0234bee070a2) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test8447a364c30880a42ca1) { +TEST_F(GenEmitterTest, testb02fb812ae14499cc30e) { Emitter out; out << BeginMap; out << BeginSeq; @@ -5906,7 +6082,7 @@ TEST_F(GenEmitterTest, test8447a364c30880a42ca1) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test09fbd11d82a3777ac376) { +TEST_F(GenEmitterTest, testa395515c1bce39e737b7) { Emitter out; out << BeginMap; out << BeginSeq; @@ -5927,7 +6103,7 @@ TEST_F(GenEmitterTest, test09fbd11d82a3777ac376) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testcbb2d4bd62f1ef2f66ad) { +TEST_F(GenEmitterTest, test813be458848be1ba3bf1) { Emitter out; out << BeginMap; out << BeginSeq; @@ -5948,7 +6124,7 @@ TEST_F(GenEmitterTest, testcbb2d4bd62f1ef2f66ad) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa0ecef367a1f54e08d00) { +TEST_F(GenEmitterTest, test23ab6af7b3fc7957a03d) { Emitter out; out << BeginMap; out << BeginSeq; @@ -5969,7 +6145,7 @@ TEST_F(GenEmitterTest, testa0ecef367a1f54e08d00) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test89c1ba14891887445d1a) { +TEST_F(GenEmitterTest, testc5fb40e239029d9efa58) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -5994,7 +6170,7 @@ TEST_F(GenEmitterTest, test89c1ba14891887445d1a) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test68436e821e03f93754e6) { +TEST_F(GenEmitterTest, test88b5c599a4f9ac52f951) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -6019,7 +6195,7 @@ TEST_F(GenEmitterTest, test68436e821e03f93754e6) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test9d56b9e336a032014977) { +TEST_F(GenEmitterTest, test3995578993108fa25f88) { Emitter out; out << BeginMap; out << Comment("comment"); @@ -6044,7 +6220,7 @@ TEST_F(GenEmitterTest, test9d56b9e336a032014977) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test38701040630c71bff30d) { +TEST_F(GenEmitterTest, test61a24036be6f8cd49a28) { Emitter out; out << BeginMap; out << BeginSeq; @@ -6069,7 +6245,7 @@ TEST_F(GenEmitterTest, test38701040630c71bff30d) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa5ee191882708767d03a) { +TEST_F(GenEmitterTest, testc13e02ab3c1bd1db6e55) { Emitter out; out << BeginMap; out << BeginSeq; @@ -6094,7 +6270,7 @@ TEST_F(GenEmitterTest, testa5ee191882708767d03a) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7f055e278180eb0f8c0d) { +TEST_F(GenEmitterTest, testb3ca69f6d7a888644064) { Emitter out; out << BeginMap; out << BeginSeq; @@ -6119,7 +6295,7 @@ TEST_F(GenEmitterTest, test7f055e278180eb0f8c0d) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testb17a6726041573ad5d90) { +TEST_F(GenEmitterTest, test4e6337821c858c2f7cfa) { Emitter out; out << BeginMap; out << BeginSeq; @@ -6144,7 +6320,7 @@ TEST_F(GenEmitterTest, testb17a6726041573ad5d90) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test0fe7dcb77bf033a58a7d) { +TEST_F(GenEmitterTest, test8dc4a01d956c779dd8b0) { Emitter out; out << BeginMap; out << BeginSeq; @@ -6169,7 +6345,7 @@ TEST_F(GenEmitterTest, test0fe7dcb77bf033a58a7d) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test4df73e774cb1a7044859) { +TEST_F(GenEmitterTest, test1dae9c6350559f6b9f89) { Emitter out; out << BeginMap; out << BeginSeq; @@ -6194,7 +6370,7 @@ TEST_F(GenEmitterTest, test4df73e774cb1a7044859) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test519ee9f4db0c2cc3cb22) { +TEST_F(GenEmitterTest, test9f891b1cdde286863956) { Emitter out; out << BeginMap; out << BeginSeq; @@ -6219,7 +6395,7 @@ TEST_F(GenEmitterTest, test519ee9f4db0c2cc3cb22) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test86fdfe330b8b39c502e3) { +TEST_F(GenEmitterTest, test0704315052c50c54b17a) { Emitter out; out << BeginMap; out << BeginSeq; @@ -6244,7 +6420,7 @@ TEST_F(GenEmitterTest, test86fdfe330b8b39c502e3) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testf1f415e2941ace087ef1) { +TEST_F(GenEmitterTest, test7f5b47cf1d2571afc033) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -6271,7 +6447,7 @@ TEST_F(GenEmitterTest, testf1f415e2941ace087ef1) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test61947172d8a42f6daa33) { +TEST_F(GenEmitterTest, test5040c19e850e3046d32d) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -6298,7 +6474,7 @@ TEST_F(GenEmitterTest, test61947172d8a42f6daa33) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testad7ddc91f2603dcd8af4) { +TEST_F(GenEmitterTest, test110665e2f3409ef307ff) { Emitter out; out << BeginMap; out << Comment("comment"); @@ -6325,7 +6501,7 @@ TEST_F(GenEmitterTest, testad7ddc91f2603dcd8af4) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test3ded81db555ef0e2dd4c) { +TEST_F(GenEmitterTest, teste9e1549f96267f93651c) { Emitter out; out << BeginMap; out << BeginSeq; @@ -6352,7 +6528,7 @@ TEST_F(GenEmitterTest, test3ded81db555ef0e2dd4c) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testb1da8147f5442f38a0af) { +TEST_F(GenEmitterTest, test6a5b6a20fdb6f7c3279e) { Emitter out; out << BeginMap; out << BeginSeq; @@ -6379,7 +6555,7 @@ TEST_F(GenEmitterTest, testb1da8147f5442f38a0af) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testdb0f2d85399318eb7957) { +TEST_F(GenEmitterTest, test7c568c68f77e34d5c714) { Emitter out; out << BeginMap; out << BeginSeq; @@ -6406,7 +6582,7 @@ TEST_F(GenEmitterTest, testdb0f2d85399318eb7957) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test456b6f61fd4fb5b4b516) { +TEST_F(GenEmitterTest, testfd8fe783b5297c92d17f) { Emitter out; out << BeginMap; out << BeginSeq; @@ -6433,7 +6609,7 @@ TEST_F(GenEmitterTest, test456b6f61fd4fb5b4b516) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test016098295ec6d033a470) { +TEST_F(GenEmitterTest, test418b1426e630825a7c85) { Emitter out; out << BeginMap; out << BeginSeq; @@ -6460,7 +6636,7 @@ TEST_F(GenEmitterTest, test016098295ec6d033a470) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test1cbee1bf6ca60fa72aa5) { +TEST_F(GenEmitterTest, test8161c5e486d317e7864e) { Emitter out; out << BeginMap; out << BeginSeq; @@ -6487,7 +6663,7 @@ TEST_F(GenEmitterTest, test1cbee1bf6ca60fa72aa5) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testaf9b292d92d4ec50429c) { +TEST_F(GenEmitterTest, testa48e1915ca7c919db445) { Emitter out; out << BeginMap; out << BeginSeq; @@ -6514,7 +6690,7 @@ TEST_F(GenEmitterTest, testaf9b292d92d4ec50429c) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test3aded59e694359fa222e) { +TEST_F(GenEmitterTest, test27124815aea27c053aab) { Emitter out; out << BeginMap; out << BeginSeq; @@ -6541,7 +6717,7 @@ TEST_F(GenEmitterTest, test3aded59e694359fa222e) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test6a79d05b97bf18ab27e9) { +TEST_F(GenEmitterTest, teste751377e4a74306bc555) { Emitter out; out << BeginMap; out << BeginSeq; @@ -6568,7 +6744,7 @@ TEST_F(GenEmitterTest, test6a79d05b97bf18ab27e9) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test96727e93c95d3dcb5a2b) { +TEST_F(GenEmitterTest, test36a4cc298255efdd1ef5) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -6591,7 +6767,7 @@ TEST_F(GenEmitterTest, test96727e93c95d3dcb5a2b) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test19387cf6dcd0618b416f) { +TEST_F(GenEmitterTest, test43471dee97b0506909b2) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -6614,7 +6790,7 @@ TEST_F(GenEmitterTest, test19387cf6dcd0618b416f) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test755733f3c3c00263610c) { +TEST_F(GenEmitterTest, test959c85b4e833f72173a6) { Emitter out; out << BeginMap; out << Comment("comment"); @@ -6637,7 +6813,7 @@ TEST_F(GenEmitterTest, test755733f3c3c00263610c) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test426a9d79d3e0421c9a57) { +TEST_F(GenEmitterTest, test3a09723dce29399bc865) { Emitter out; out << BeginMap; out << BeginMap; @@ -6660,7 +6836,7 @@ TEST_F(GenEmitterTest, test426a9d79d3e0421c9a57) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testefad231fdbf0147b5a46) { +TEST_F(GenEmitterTest, test958e404277a1c55139af) { Emitter out; out << BeginMap; out << BeginMap; @@ -6683,7 +6859,7 @@ TEST_F(GenEmitterTest, testefad231fdbf0147b5a46) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test03772c261806afb7c9cc) { +TEST_F(GenEmitterTest, testb1823407ab0601edc9cb) { Emitter out; out << BeginMap; out << BeginMap; @@ -6706,7 +6882,7 @@ TEST_F(GenEmitterTest, test03772c261806afb7c9cc) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test65734300dcf959922c18) { +TEST_F(GenEmitterTest, test9993e9dad983b28960aa) { Emitter out; out << BeginMap; out << BeginMap; @@ -6729,7 +6905,7 @@ TEST_F(GenEmitterTest, test65734300dcf959922c18) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test815ef14ef8792dc2de1d) { +TEST_F(GenEmitterTest, test8e87f559b25a9a20e11c) { Emitter out; out << BeginMap; out << BeginMap; @@ -6752,7 +6928,7 @@ TEST_F(GenEmitterTest, test815ef14ef8792dc2de1d) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test5266cf3b9eb70be75944) { +TEST_F(GenEmitterTest, testeb431be8504451636efe) { Emitter out; out << BeginMap; out << BeginMap; @@ -6775,7 +6951,7 @@ TEST_F(GenEmitterTest, test5266cf3b9eb70be75944) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test199b993f2f9302c1c0c8) { +TEST_F(GenEmitterTest, testf876965882befc7355df) { Emitter out; out << BeginMap; out << BeginMap; @@ -6798,7 +6974,7 @@ TEST_F(GenEmitterTest, test199b993f2f9302c1c0c8) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test448f8a30d377c0c01b26) { +TEST_F(GenEmitterTest, testf7e1d47f266f0b940fed) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -6825,7 +7001,7 @@ TEST_F(GenEmitterTest, test448f8a30d377c0c01b26) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa4a3cfe5a74aa90708a5) { +TEST_F(GenEmitterTest, teste5a4bc646f2182b78cc1) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -6852,7 +7028,7 @@ TEST_F(GenEmitterTest, testa4a3cfe5a74aa90708a5) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test6de6ac6c26a8d098b529) { +TEST_F(GenEmitterTest, test6cbedca25c9a8a6bb42e) { Emitter out; out << BeginMap; out << Comment("comment"); @@ -6879,7 +7055,7 @@ TEST_F(GenEmitterTest, test6de6ac6c26a8d098b529) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testc9e7f10371f284e94d20) { +TEST_F(GenEmitterTest, test07613cc34874a5b47577) { Emitter out; out << BeginMap; out << BeginMap; @@ -6906,7 +7082,7 @@ TEST_F(GenEmitterTest, testc9e7f10371f284e94d20) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test382360950d64ced8a0cc) { +TEST_F(GenEmitterTest, testa55b7ac19580aeb82d32) { Emitter out; out << BeginMap; out << BeginMap; @@ -6933,7 +7109,7 @@ TEST_F(GenEmitterTest, test382360950d64ced8a0cc) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test52b289c54900ca0a098e) { +TEST_F(GenEmitterTest, test458f9af92dfb9f64a488) { Emitter out; out << BeginMap; out << BeginMap; @@ -6960,7 +7136,7 @@ TEST_F(GenEmitterTest, test52b289c54900ca0a098e) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7266716f412852506771) { +TEST_F(GenEmitterTest, testc4a9c3769e95770bb455) { Emitter out; out << BeginMap; out << BeginMap; @@ -6987,7 +7163,7 @@ TEST_F(GenEmitterTest, test7266716f412852506771) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testd2ac7d6f40cc75a3c695) { +TEST_F(GenEmitterTest, testae56654f89fa2416f3db) { Emitter out; out << BeginMap; out << BeginMap; @@ -7014,7 +7190,7 @@ TEST_F(GenEmitterTest, testd2ac7d6f40cc75a3c695) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test368597fd8bcc0d3aaff0) { +TEST_F(GenEmitterTest, test1635f71f27e7303c730e) { Emitter out; out << BeginMap; out << BeginMap; @@ -7041,7 +7217,7 @@ TEST_F(GenEmitterTest, test368597fd8bcc0d3aaff0) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test9201309cd67ab579b883) { +TEST_F(GenEmitterTest, testcd9d835a8d8b8622c63b) { Emitter out; out << BeginMap; out << BeginMap; @@ -7068,7 +7244,7 @@ TEST_F(GenEmitterTest, test9201309cd67ab579b883) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test30e18cbdd5d04a552625) { +TEST_F(GenEmitterTest, test3c2d1f91e57040cb8fdd) { Emitter out; out << BeginMap; out << BeginMap; @@ -7095,7 +7271,7 @@ TEST_F(GenEmitterTest, test30e18cbdd5d04a552625) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa659d36137a8f34911a6) { +TEST_F(GenEmitterTest, test9bd5b4c002b3b637747f) { Emitter out; out << BeginMap; out << BeginMap; @@ -7122,7 +7298,7 @@ TEST_F(GenEmitterTest, testa659d36137a8f34911a6) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste0b8302185ee814d6552) { +TEST_F(GenEmitterTest, testf6c71199cd45b5b8e7e0) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -7151,7 +7327,7 @@ TEST_F(GenEmitterTest, teste0b8302185ee814d6552) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test66793e09aa910bd924ca) { +TEST_F(GenEmitterTest, test865b02b69742e5513963) { Emitter out; out << Comment("comment"); out << BeginMap; @@ -7180,7 +7356,7 @@ TEST_F(GenEmitterTest, test66793e09aa910bd924ca) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test9beaa5ceb1fcfef2a897) { +TEST_F(GenEmitterTest, test86eb8783dc4367cda931) { Emitter out; out << BeginMap; out << Comment("comment"); @@ -7209,7 +7385,7 @@ TEST_F(GenEmitterTest, test9beaa5ceb1fcfef2a897) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test8ccc36c941ec6aa59536) { +TEST_F(GenEmitterTest, test7f6604058a9d8e2e1219) { Emitter out; out << BeginMap; out << BeginMap; @@ -7238,7 +7414,7 @@ TEST_F(GenEmitterTest, test8ccc36c941ec6aa59536) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test3c8ea05243d098395929) { +TEST_F(GenEmitterTest, test676b4abcb3cf0530e4da) { Emitter out; out << BeginMap; out << BeginMap; @@ -7267,7 +7443,7 @@ TEST_F(GenEmitterTest, test3c8ea05243d098395929) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testd819abb35a3ff74e764a) { +TEST_F(GenEmitterTest, teste7e52980e73d442a602b) { Emitter out; out << BeginMap; out << BeginMap; @@ -7296,7 +7472,7 @@ TEST_F(GenEmitterTest, testd819abb35a3ff74e764a) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test416c49d00378b626ad21) { +TEST_F(GenEmitterTest, testc3d6f480087db4bcd3a1) { Emitter out; out << BeginMap; out << BeginMap; @@ -7325,7 +7501,7 @@ TEST_F(GenEmitterTest, test416c49d00378b626ad21) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test5cd5ecef5b2a297afe21) { +TEST_F(GenEmitterTest, test6943516ed43da6944e96) { Emitter out; out << BeginMap; out << BeginMap; @@ -7354,7 +7530,7 @@ TEST_F(GenEmitterTest, test5cd5ecef5b2a297afe21) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test9d8ea78df40a20f07e96) { +TEST_F(GenEmitterTest, testb7e880522d0778ae6e6f) { Emitter out; out << BeginMap; out << BeginMap; @@ -7383,7 +7559,7 @@ TEST_F(GenEmitterTest, test9d8ea78df40a20f07e96) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste7bdb2f35bec40c207ee) { +TEST_F(GenEmitterTest, testec39ee51992618c7b154) { Emitter out; out << BeginMap; out << BeginMap; @@ -7412,7 +7588,7 @@ TEST_F(GenEmitterTest, teste7bdb2f35bec40c207ee) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste6d6da3a612849d32b79) { +TEST_F(GenEmitterTest, test39f768713a9b3aaffe0d) { Emitter out; out << BeginMap; out << BeginMap; @@ -7441,7 +7617,7 @@ TEST_F(GenEmitterTest, teste6d6da3a612849d32b79) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test9af66f2efca487828902) { +TEST_F(GenEmitterTest, testf287a68abc5b8ff7784d) { Emitter out; out << BeginMap; out << BeginMap; @@ -7470,7 +7646,7 @@ TEST_F(GenEmitterTest, test9af66f2efca487828902) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testb05b2fc716f368b6bdfc) { +TEST_F(GenEmitterTest, testc36154aa87842ba9699f) { Emitter out; out << BeginMap; out << BeginMap; @@ -7499,7 +7675,7 @@ TEST_F(GenEmitterTest, testb05b2fc716f368b6bdfc) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testd0713381b33b72abdb58) { +TEST_F(GenEmitterTest, testa75da84dfc8ee5507157) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -7516,7 +7692,7 @@ TEST_F(GenEmitterTest, testd0713381b33b72abdb58) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testc6739cb3a9de4a5c41a7) { +TEST_F(GenEmitterTest, testc54a03d1735615f7bd60) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -7533,7 +7709,7 @@ TEST_F(GenEmitterTest, testc6739cb3a9de4a5c41a7) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test2b4fa669c6b56cd6a117) { +TEST_F(GenEmitterTest, testf5d72aba828875527d6f) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -7550,7 +7726,7 @@ TEST_F(GenEmitterTest, test2b4fa669c6b56cd6a117) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test29ae2ef656132c069d22) { +TEST_F(GenEmitterTest, test9e8681a1b27a8524ec5e) { Emitter out; out << BeginSeq; out << "foo"; @@ -7567,7 +7743,7 @@ TEST_F(GenEmitterTest, test29ae2ef656132c069d22) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testd3e2ad21ab7d0890c412) { +TEST_F(GenEmitterTest, test34678928e79e6eb160f4) { Emitter out; out << BeginSeq; out << "foo"; @@ -7584,7 +7760,7 @@ TEST_F(GenEmitterTest, testd3e2ad21ab7d0890c412) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test632b0fb6570fa3b1b682) { +TEST_F(GenEmitterTest, test07c6d6b9e133553d4532) { Emitter out; out << BeginSeq; out << "foo"; @@ -7601,7 +7777,7 @@ TEST_F(GenEmitterTest, test632b0fb6570fa3b1b682) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testc9bcfd496ae3382d546b) { +TEST_F(GenEmitterTest, test1531642db71e1aa8dd1c) { Emitter out; out << BeginSeq; out << "foo"; @@ -7618,7 +7794,7 @@ TEST_F(GenEmitterTest, testc9bcfd496ae3382d546b) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test43fd860d560c9137add4) { +TEST_F(GenEmitterTest, test22fde02c0bd0ecb8a527) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -7639,7 +7815,7 @@ TEST_F(GenEmitterTest, test43fd860d560c9137add4) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test0e47183ab4a56c3a6d36) { +TEST_F(GenEmitterTest, test72430574ba42559cf917) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -7660,7 +7836,7 @@ TEST_F(GenEmitterTest, test0e47183ab4a56c3a6d36) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testf165d91c1dce024c9774) { +TEST_F(GenEmitterTest, test067bce5d8aa6281a3e6f) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -7681,7 +7857,7 @@ TEST_F(GenEmitterTest, testf165d91c1dce024c9774) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7592a1f019ddb2b9c3f4) { +TEST_F(GenEmitterTest, testb1839ee8ced911bb1ed1) { Emitter out; out << BeginSeq; out << "foo"; @@ -7702,7 +7878,7 @@ TEST_F(GenEmitterTest, test7592a1f019ddb2b9c3f4) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test758d285e89a9de8070a7) { +TEST_F(GenEmitterTest, test5899c9cd7e5a40077178) { Emitter out; out << BeginSeq; out << "foo"; @@ -7723,7 +7899,7 @@ TEST_F(GenEmitterTest, test758d285e89a9de8070a7) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test5888499c52285a1b61de) { +TEST_F(GenEmitterTest, test834f4e4a74c0ac6cd011) { Emitter out; out << BeginSeq; out << "foo"; @@ -7744,7 +7920,7 @@ TEST_F(GenEmitterTest, test5888499c52285a1b61de) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test0115edbe7dd05e84f108) { +TEST_F(GenEmitterTest, testd3aeee7524918cf227e7) { Emitter out; out << BeginSeq; out << "foo"; @@ -7765,7 +7941,7 @@ TEST_F(GenEmitterTest, test0115edbe7dd05e84f108) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testcbbbde92f35597a9e476) { +TEST_F(GenEmitterTest, test7c587549aa0bbd6e2d53) { Emitter out; out << BeginSeq; out << "foo"; @@ -7786,7 +7962,7 @@ TEST_F(GenEmitterTest, testcbbbde92f35597a9e476) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa74ec451d449e2a89442) { +TEST_F(GenEmitterTest, testc684ba00d512b6009b02) { Emitter out; out << BeginSeq; out << "foo"; @@ -7807,7 +7983,7 @@ TEST_F(GenEmitterTest, testa74ec451d449e2a89442) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test60faf9f5ac584b2d5a5f) { +TEST_F(GenEmitterTest, testbe39189b638b9e0214dd) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -7830,7 +8006,7 @@ TEST_F(GenEmitterTest, test60faf9f5ac584b2d5a5f) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa34103141c1aec5e8fa8) { +TEST_F(GenEmitterTest, test80326240018ececfa606) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -7853,7 +8029,7 @@ TEST_F(GenEmitterTest, testa34103141c1aec5e8fa8) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa2a2b83cb72c22fc4ac2) { +TEST_F(GenEmitterTest, test8a74653a376d02a2b6db) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -7876,7 +8052,7 @@ TEST_F(GenEmitterTest, testa2a2b83cb72c22fc4ac2) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test1f7ddcc3e5263ec983c5) { +TEST_F(GenEmitterTest, testaa82cace20492eb66f60) { Emitter out; out << BeginSeq; out << "foo"; @@ -7899,7 +8075,7 @@ TEST_F(GenEmitterTest, test1f7ddcc3e5263ec983c5) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test638672d9ee378d2b59ec) { +TEST_F(GenEmitterTest, testcd4a1cdb4e2a24cae5c1) { Emitter out; out << BeginSeq; out << "foo"; @@ -7922,7 +8098,7 @@ TEST_F(GenEmitterTest, test638672d9ee378d2b59ec) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testffa1014d27bcb4821993) { +TEST_F(GenEmitterTest, testa9ef5ab0eada79175f6a) { Emitter out; out << BeginSeq; out << "foo"; @@ -7945,7 +8121,7 @@ TEST_F(GenEmitterTest, testffa1014d27bcb4821993) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, tested2f908c978d8908cde2) { +TEST_F(GenEmitterTest, test4060ba4b4f9b8193dcc4) { Emitter out; out << BeginSeq; out << "foo"; @@ -7968,7 +8144,7 @@ TEST_F(GenEmitterTest, tested2f908c978d8908cde2) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test75c9a342b4ff9dcddd76) { +TEST_F(GenEmitterTest, test6cd2fc4be08857654fa0) { Emitter out; out << BeginSeq; out << "foo"; @@ -7991,7 +8167,7 @@ TEST_F(GenEmitterTest, test75c9a342b4ff9dcddd76) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testb3cf7afef788a5168172) { +TEST_F(GenEmitterTest, testadb892f6183cde28d9cc) { Emitter out; out << BeginSeq; out << "foo"; @@ -8014,7 +8190,7 @@ TEST_F(GenEmitterTest, testb3cf7afef788a5168172) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test32c5731914c4f623f8cb) { +TEST_F(GenEmitterTest, test5e830445d6cafe856b09) { Emitter out; out << BeginSeq; out << "foo"; @@ -8037,7 +8213,7 @@ TEST_F(GenEmitterTest, test32c5731914c4f623f8cb) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testc4e4b895f5a3615e6c92) { +TEST_F(GenEmitterTest, test16a7d875f6358bdd36ee) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -8058,7 +8234,7 @@ TEST_F(GenEmitterTest, testc4e4b895f5a3615e6c92) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test024f81ab1e1f375d06c8) { +TEST_F(GenEmitterTest, test75b4342605739c88bc3f) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -8079,7 +8255,7 @@ TEST_F(GenEmitterTest, test024f81ab1e1f375d06c8) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testf73efa1189e8e9bab50c) { +TEST_F(GenEmitterTest, test7d42488f1a02d045d278) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -8100,7 +8276,7 @@ TEST_F(GenEmitterTest, testf73efa1189e8e9bab50c) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test074882061d59e9381988) { +TEST_F(GenEmitterTest, test9ce404764c03c6644c98) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8121,7 +8297,7 @@ TEST_F(GenEmitterTest, test074882061d59e9381988) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testb81b19396e93a0e29157) { +TEST_F(GenEmitterTest, testf9e413cd5405efcbd432) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8142,7 +8318,7 @@ TEST_F(GenEmitterTest, testb81b19396e93a0e29157) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testd4776155c00bb794aec9) { +TEST_F(GenEmitterTest, test757c82faa95e2e507ee9) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8163,7 +8339,7 @@ TEST_F(GenEmitterTest, testd4776155c00bb794aec9) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test0d3813f2674c45d54be7) { +TEST_F(GenEmitterTest, testb73d72bf5de11964969f) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8184,7 +8360,7 @@ TEST_F(GenEmitterTest, test0d3813f2674c45d54be7) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testaee95b4f9b1161f6fd14) { +TEST_F(GenEmitterTest, test3926f169b9dce6db913f) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8205,7 +8381,7 @@ TEST_F(GenEmitterTest, testaee95b4f9b1161f6fd14) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test3f7b4338eae92e7a575f) { +TEST_F(GenEmitterTest, test77b0cc7e618a09e0556d) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8226,7 +8402,7 @@ TEST_F(GenEmitterTest, test3f7b4338eae92e7a575f) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test13a3de779d0756db2635) { +TEST_F(GenEmitterTest, test6817f3e5da2ad8823025) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -8251,7 +8427,7 @@ TEST_F(GenEmitterTest, test13a3de779d0756db2635) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test6cc39fc73a32cb816c15) { +TEST_F(GenEmitterTest, test817ae48b78359d60888b) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -8276,7 +8452,7 @@ TEST_F(GenEmitterTest, test6cc39fc73a32cb816c15) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test33c4f4a8854d92180427) { +TEST_F(GenEmitterTest, test9db1bf6278dd7de937e6) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -8301,7 +8477,7 @@ TEST_F(GenEmitterTest, test33c4f4a8854d92180427) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test1e5612a63642939843fc) { +TEST_F(GenEmitterTest, test4d5ca5c891442ddf7e84) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8326,7 +8502,7 @@ TEST_F(GenEmitterTest, test1e5612a63642939843fc) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test774fccdfa9e9ea982df2) { +TEST_F(GenEmitterTest, testfb6eb22f4bf080b9ac8b) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8351,7 +8527,7 @@ TEST_F(GenEmitterTest, test774fccdfa9e9ea982df2) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testecdd8159ca0150ac9084) { +TEST_F(GenEmitterTest, test3ce4b4ec89282d701502) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8376,7 +8552,7 @@ TEST_F(GenEmitterTest, testecdd8159ca0150ac9084) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test8081bb348b980caf237e) { +TEST_F(GenEmitterTest, testaf53ae415739a8812200) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8401,7 +8577,7 @@ TEST_F(GenEmitterTest, test8081bb348b980caf237e) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test5dd9e7d23a6868f8da14) { +TEST_F(GenEmitterTest, test72d3de78c6508500cb00) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8426,7 +8602,7 @@ TEST_F(GenEmitterTest, test5dd9e7d23a6868f8da14) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test5cfe1848cf1771ee5a62) { +TEST_F(GenEmitterTest, test6dd3d3703718b37fa2a4) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8451,7 +8627,7 @@ TEST_F(GenEmitterTest, test5cfe1848cf1771ee5a62) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test1a78787fd377fecaa98a) { +TEST_F(GenEmitterTest, testc0beca9064d8081d45c1) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8476,7 +8652,7 @@ TEST_F(GenEmitterTest, test1a78787fd377fecaa98a) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test3659c5e006def41d781a) { +TEST_F(GenEmitterTest, test14c55f7cd295d89763ca) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8501,7 +8677,7 @@ TEST_F(GenEmitterTest, test3659c5e006def41d781a) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testcffd2b80f823bc7b88bc) { +TEST_F(GenEmitterTest, test72a93f054d9296607dff) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -8528,7 +8704,7 @@ TEST_F(GenEmitterTest, testcffd2b80f823bc7b88bc) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test3646d0fd40876cdc7d90) { +TEST_F(GenEmitterTest, testf0ac164fe5c38cc36922) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -8555,7 +8731,7 @@ TEST_F(GenEmitterTest, test3646d0fd40876cdc7d90) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testce3c9ef9e0c642d65146) { +TEST_F(GenEmitterTest, test74efb7c560fd057d25ba) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -8582,7 +8758,7 @@ TEST_F(GenEmitterTest, testce3c9ef9e0c642d65146) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test666f93032b0297bd6f81) { +TEST_F(GenEmitterTest, test43adceaba606a7f5013f) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8609,7 +8785,7 @@ TEST_F(GenEmitterTest, test666f93032b0297bd6f81) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7939e2697c6f4d8b91e9) { +TEST_F(GenEmitterTest, test94160894abf5f0650ec9) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8636,7 +8812,7 @@ TEST_F(GenEmitterTest, test7939e2697c6f4d8b91e9) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test3c153927514f7330e37d) { +TEST_F(GenEmitterTest, testb77f1131af63dae91031) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8663,7 +8839,7 @@ TEST_F(GenEmitterTest, test3c153927514f7330e37d) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test59b085e35e59562026da) { +TEST_F(GenEmitterTest, test296aa575c385013e91f0) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8690,7 +8866,7 @@ TEST_F(GenEmitterTest, test59b085e35e59562026da) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test367f38cb15951f58f294) { +TEST_F(GenEmitterTest, test339bddce4b70064141c4) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8717,7 +8893,7 @@ TEST_F(GenEmitterTest, test367f38cb15951f58f294) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testbb3feccd2d65d126c9e4) { +TEST_F(GenEmitterTest, test991a70285cf143adb7fe) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8744,7 +8920,7 @@ TEST_F(GenEmitterTest, testbb3feccd2d65d126c9e4) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test4c5079959ae8b908aee3) { +TEST_F(GenEmitterTest, test1b1ae70c1b5e7a1a2502) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8771,7 +8947,7 @@ TEST_F(GenEmitterTest, test4c5079959ae8b908aee3) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testfa82743c73819854df98) { +TEST_F(GenEmitterTest, test02e58fb30f5a5b3616ec) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8798,7 +8974,7 @@ TEST_F(GenEmitterTest, testfa82743c73819854df98) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste354627da20a33a0ec48) { +TEST_F(GenEmitterTest, testbdc3952445cad78094e2) { Emitter out; out << BeginSeq; out << BeginSeq; @@ -8825,7 +9001,7 @@ TEST_F(GenEmitterTest, teste354627da20a33a0ec48) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test202a2c088ee50d08f182) { +TEST_F(GenEmitterTest, test5d24f2ab8e24cb71d6c9) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -8848,7 +9024,7 @@ TEST_F(GenEmitterTest, test202a2c088ee50d08f182) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testc7277e5979e7eaf4d016) { +TEST_F(GenEmitterTest, test1ca2c58583cb7dd8a765) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -8871,7 +9047,7 @@ TEST_F(GenEmitterTest, testc7277e5979e7eaf4d016) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, teste2b7015fc02e6a5cb416) { +TEST_F(GenEmitterTest, test6086aee45faab48750ad) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -8894,7 +9070,7 @@ TEST_F(GenEmitterTest, teste2b7015fc02e6a5cb416) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test30e30b89df20ef693d7b) { +TEST_F(GenEmitterTest, testdac42de03b96b1207ec4) { Emitter out; out << BeginSeq; out << BeginMap; @@ -8917,7 +9093,7 @@ TEST_F(GenEmitterTest, test30e30b89df20ef693d7b) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test5cab866f8818d65f5cfe) { +TEST_F(GenEmitterTest, test10d18ea5e198359e218b) { Emitter out; out << BeginSeq; out << BeginMap; @@ -8940,7 +9116,7 @@ TEST_F(GenEmitterTest, test5cab866f8818d65f5cfe) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test6c2133597d99c14720d0) { +TEST_F(GenEmitterTest, test56218e461d6be3a18500) { Emitter out; out << BeginSeq; out << BeginMap; @@ -8963,7 +9139,7 @@ TEST_F(GenEmitterTest, test6c2133597d99c14720d0) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test243b3bb00a830d4d7c5c) { +TEST_F(GenEmitterTest, test9acfd124b72471e34bbd) { Emitter out; out << BeginSeq; out << BeginMap; @@ -8986,7 +9162,7 @@ TEST_F(GenEmitterTest, test243b3bb00a830d4d7c5c) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7fcdb9d71a9717069b9f) { +TEST_F(GenEmitterTest, test2a1c3780a4dfaa43646e) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9009,7 +9185,7 @@ TEST_F(GenEmitterTest, test7fcdb9d71a9717069b9f) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test0ce9909c470ae5b1d3ae) { +TEST_F(GenEmitterTest, test91e4c547fdab9e8b1c67) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9032,7 +9208,7 @@ TEST_F(GenEmitterTest, test0ce9909c470ae5b1d3ae) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testc077fd929177c75e3072) { +TEST_F(GenEmitterTest, test3d7e8318208742fe4358) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9055,7 +9231,7 @@ TEST_F(GenEmitterTest, testc077fd929177c75e3072) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test3b500af23a2b660e0330) { +TEST_F(GenEmitterTest, test2e4a92f93d5f9d8c5fed) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -9082,7 +9258,7 @@ TEST_F(GenEmitterTest, test3b500af23a2b660e0330) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test6d037fb77412a7b06f24) { +TEST_F(GenEmitterTest, test9abf5d48ef7c6f2ed8a0) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -9109,7 +9285,7 @@ TEST_F(GenEmitterTest, test6d037fb77412a7b06f24) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testa153abd07d892e352889) { +TEST_F(GenEmitterTest, testc3428819fe7cfe88cf10) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -9136,7 +9312,7 @@ TEST_F(GenEmitterTest, testa153abd07d892e352889) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testf328e682c5d872fbb7fa) { +TEST_F(GenEmitterTest, test8007ba3728b0fdbb0cb8) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9163,7 +9339,7 @@ TEST_F(GenEmitterTest, testf328e682c5d872fbb7fa) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testb59b29e1f0612f8333bf) { +TEST_F(GenEmitterTest, test6eedc1e3db4ceee9caf6) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9190,7 +9366,7 @@ TEST_F(GenEmitterTest, testb59b29e1f0612f8333bf) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test0d2de653c36fff7e875f) { +TEST_F(GenEmitterTest, testd892f2048c7066c74b7e) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9217,7 +9393,7 @@ TEST_F(GenEmitterTest, test0d2de653c36fff7e875f) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test18454002edb2d8ce5dff) { +TEST_F(GenEmitterTest, test736430339c2a221b6d89) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9244,7 +9420,7 @@ TEST_F(GenEmitterTest, test18454002edb2d8ce5dff) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test3869b95fb927574c1cfa) { +TEST_F(GenEmitterTest, test6d51f33adb9324f438d1) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9271,7 +9447,7 @@ TEST_F(GenEmitterTest, test3869b95fb927574c1cfa) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test5f9d2836779171944bd5) { +TEST_F(GenEmitterTest, test00d50067643ed73a3f7f) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9298,7 +9474,7 @@ TEST_F(GenEmitterTest, test5f9d2836779171944bd5) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test00ca741ed5db71e7197c) { +TEST_F(GenEmitterTest, test5fc029e9d46151d31a80) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9325,7 +9501,7 @@ TEST_F(GenEmitterTest, test00ca741ed5db71e7197c) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test63b2dee62c4656039c0d) { +TEST_F(GenEmitterTest, test328542a5a4b65371d2c6) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9352,7 +9528,7 @@ TEST_F(GenEmitterTest, test63b2dee62c4656039c0d) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test6fca12b5bf897f3b933f) { +TEST_F(GenEmitterTest, testf791a97db1c96e9f16c7) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9379,7 +9555,7 @@ TEST_F(GenEmitterTest, test6fca12b5bf897f3b933f) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testf047a3a7cd147dc69553) { +TEST_F(GenEmitterTest, test44ac18a00d604391a169) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -9408,7 +9584,7 @@ TEST_F(GenEmitterTest, testf047a3a7cd147dc69553) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testf191f92a0c15e5624272) { +TEST_F(GenEmitterTest, teste7ff269f6d95faa06abe) { Emitter out; out << Comment("comment"); out << BeginSeq; @@ -9437,7 +9613,7 @@ TEST_F(GenEmitterTest, testf191f92a0c15e5624272) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test874f18e2970f54d92f34) { +TEST_F(GenEmitterTest, test8d056d159803415c2c85) { Emitter out; out << BeginSeq; out << Comment("comment"); @@ -9466,7 +9642,7 @@ TEST_F(GenEmitterTest, test874f18e2970f54d92f34) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7e94b62bc08fb63b7062) { +TEST_F(GenEmitterTest, test47ef0ff3da945fda8680) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9495,7 +9671,7 @@ TEST_F(GenEmitterTest, test7e94b62bc08fb63b7062) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test50d40871122b935a2937) { +TEST_F(GenEmitterTest, test1f981851e5a72a91614b) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9524,7 +9700,7 @@ TEST_F(GenEmitterTest, test50d40871122b935a2937) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testb6a8d9eb931455caa603) { +TEST_F(GenEmitterTest, test783be6c196784ca7ff30) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9553,7 +9729,7 @@ TEST_F(GenEmitterTest, testb6a8d9eb931455caa603) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test2f23bfff4a1d201b1f37) { +TEST_F(GenEmitterTest, test217dcab50ef45ac6d344) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9582,7 +9758,7 @@ TEST_F(GenEmitterTest, test2f23bfff4a1d201b1f37) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test41ef23e040f0db2c06c2) { +TEST_F(GenEmitterTest, testec71f98bc646a34c9327) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9611,7 +9787,7 @@ TEST_F(GenEmitterTest, test41ef23e040f0db2c06c2) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, testb8c7b55b5607df008fbe) { +TEST_F(GenEmitterTest, test04595ac13c58c0740048) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9640,7 +9816,7 @@ TEST_F(GenEmitterTest, testb8c7b55b5607df008fbe) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test21daf188179c0c0c7bef) { +TEST_F(GenEmitterTest, test18d724e2ff0f869e9947) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9669,7 +9845,7 @@ TEST_F(GenEmitterTest, test21daf188179c0c0c7bef) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test8ca560e6b97325079e8f) { +TEST_F(GenEmitterTest, test9f80798acafd4cfec0aa) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9698,7 +9874,7 @@ TEST_F(GenEmitterTest, test8ca560e6b97325079e8f) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test7fe0ce86b72c7c1ed7de) { +TEST_F(GenEmitterTest, testeabc051f6366e0275232) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9727,7 +9903,7 @@ TEST_F(GenEmitterTest, test7fe0ce86b72c7c1ed7de) { Parse(out.c_str()); } -TEST_F(GenEmitterTest, test8cc25a6c1aea65ad7de1) { +TEST_F(GenEmitterTest, teste33a98fb01ea45cc91dc) { Emitter out; out << BeginSeq; out << BeginMap; @@ -9755,5 +9931,6 @@ TEST_F(GenEmitterTest, test8cc25a6c1aea65ad7de1) { EXPECT_CALL(handler, OnDocumentEnd()); Parse(out.c_str()); } -} -} + +} // namespace +} // namespace YAML diff --git a/lib/yamlcpp/test/integration/handler_spec_test.cpp b/lib/yamlcpp/test/integration/handler_spec_test.cpp index d142a0d302e..fcb76d583cc 100644 --- a/lib/yamlcpp/test/integration/handler_spec_test.cpp +++ b/lib/yamlcpp/test/integration/handler_spec_test.cpp @@ -199,6 +199,7 @@ TEST_F(HandlerSpecTest, Ex2_10_SimpleAnchor) { EXPECT_CALL(handler, OnScalar(_, "?", 0, "hr")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Mark McGwire")); + EXPECT_CALL(handler, OnAnchor(_, "SS")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "Sammy Sosa")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnScalar(_, "?", 0, "rbi")); @@ -376,6 +377,7 @@ TEST_F(HandlerSpecTest, Ex2_24_GlobalTags) { EXPECT_CALL(handler, OnMapStart(_, "tag:clarkevans.com,2002:circle", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "center")); + EXPECT_CALL(handler, OnAnchor(_, "ORIGIN")); EXPECT_CALL(handler, OnMapStart(_, "?", 1, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "x")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "73")); @@ -456,6 +458,7 @@ TEST_F(HandlerSpecTest, Ex2_27_Invoice) { EXPECT_CALL(handler, OnScalar(_, "?", 0, "date")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "2001-01-23")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "bill-to")); + EXPECT_CALL(handler, OnAnchor(_, "id001")); EXPECT_CALL(handler, OnMapStart(_, "?", 1, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "given")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Chris")); @@ -616,6 +619,7 @@ TEST_F(HandlerSpecTest, Ex5_6_NodePropertyIndicators) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "anchored")); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "!local", 1, "value")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "alias")); EXPECT_CALL(handler, OnAlias(_, 1)); @@ -909,8 +913,10 @@ TEST_F(HandlerSpecTest, Ex6_22_GlobalTagPrefix) { TEST_F(HandlerSpecTest, Ex6_23_NodeProperties) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); + EXPECT_CALL(handler, OnAnchor(_, "a1")); EXPECT_CALL(handler, OnScalar(_, "tag:yaml.org,2002:str", 1, "foo")); EXPECT_CALL(handler, OnScalar(_, "tag:yaml.org,2002:str", 0, "bar")); + EXPECT_CALL(handler, OnAnchor(_, "a2")); EXPECT_CALL(handler, OnScalar(_, "?", 2, "baz")); EXPECT_CALL(handler, OnAlias(_, 1)); EXPECT_CALL(handler, OnMapEnd()); @@ -972,6 +978,7 @@ TEST_F(HandlerSpecTest, Ex6_29_NodeAnchors) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "First occurrence")); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "Value")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Second occurrence")); EXPECT_CALL(handler, OnAlias(_, 1)); @@ -984,10 +991,12 @@ TEST_F(HandlerSpecTest, Ex7_1_AliasNodes) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "First occurrence")); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "Foo")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Second occurrence")); EXPECT_CALL(handler, OnAlias(_, 1)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Override anchor")); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 2, "Bar")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Reuse anchor")); EXPECT_CALL(handler, OnAlias(_, 2)); @@ -1307,6 +1316,7 @@ TEST_F(HandlerSpecTest, Ex7_24_FlowNodes) { EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "tag:yaml.org,2002:str", 0, "a")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "b")); + EXPECT_CALL(handler, OnAnchor(_, "anchor")); EXPECT_CALL(handler, OnScalar(_, "!", 1, "c")); EXPECT_CALL(handler, OnAlias(_, 1)); EXPECT_CALL(handler, OnScalar(_, "tag:yaml.org,2002:str", 0, "")); @@ -1607,5 +1617,5 @@ TEST_F(HandlerSpecTest, Ex8_22_BlockCollectionNodes) { EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_22); } -} -} +} // namespace +} // namespace YAML diff --git a/lib/yamlcpp/test/integration/load_node_test.cpp b/lib/yamlcpp/test/integration/load_node_test.cpp index 28850847604..4f4f28e8e20 100644 --- a/lib/yamlcpp/test/integration/load_node_test.cpp +++ b/lib/yamlcpp/test/integration/load_node_test.cpp @@ -55,6 +55,26 @@ TEST(LoadNodeTest, Binary) { node[1].as()); } +TEST(LoadNodeTest, BinaryWithWhitespaces) { + Node node = Load( + "binaryText: !binary |-\n" + " TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieS\n" + " B0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIG\n" + " x1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbi\n" + " B0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZG\n" + " dlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS\n" + " 4K"); + EXPECT_EQ(Binary(reinterpret_cast( + "Man is distinguished, not only by his reason, " + "but by this singular passion from other " + "animals, which is a lust of the mind, that by " + "a perseverance of delight in the continued and " + "indefatigable generation of knowledge, exceeds " + "the short vehemence of any carnal pleasure.\n"), + 270), + node["binaryText"].as()); +} + TEST(LoadNodeTest, IterateSequence) { Node node = Load("[1, 3, 5, 7]"); int seq[] = {1, 3, 5, 7}; @@ -230,7 +250,7 @@ TEST(NodeTest, LoadTildeAsNull) { Node node = Load("~"); ASSERT_TRUE(node.IsNull()); } - + TEST(NodeTest, LoadTagWithParenthesis) { Node node = Load("!Complex(Tag) foo"); EXPECT_EQ(node.Tag(), "!Complex(Tag)"); diff --git a/lib/yamlcpp/test/mock_event_handler.h b/lib/yamlcpp/test/mock_event_handler.h index 49d1f0c3342..2c1d15a4b80 100644 --- a/lib/yamlcpp/test/mock_event_handler.h +++ b/lib/yamlcpp/test/mock_event_handler.h @@ -22,5 +22,6 @@ class MockEventHandler : public EventHandler { MOCK_METHOD4(OnMapStart, void(const Mark&, const std::string&, anchor_t, EmitterStyle::value)); MOCK_METHOD0(OnMapEnd, void()); + MOCK_METHOD2(OnAnchor, void(const Mark&, const std::string&)); }; -} +} // namespace YAML diff --git a/lib/yamlcpp/test/node/node_test.cpp b/lib/yamlcpp/test/node/node_test.cpp index 485ad09e1ae..18234dbde01 100644 --- a/lib/yamlcpp/test/node/node_test.cpp +++ b/lib/yamlcpp/test/node/node_test.cpp @@ -1,10 +1,10 @@ +#include "yaml-cpp/node/node.h" #include "yaml-cpp/emitter.h" +#include "yaml-cpp/node/convert.h" +#include "yaml-cpp/node/detail/impl.h" #include "yaml-cpp/node/emit.h" -#include "yaml-cpp/node/node.h" #include "yaml-cpp/node/impl.h" -#include "yaml-cpp/node/convert.h" #include "yaml-cpp/node/iterator.h" -#include "yaml-cpp/node/detail/impl.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -47,6 +47,30 @@ TEST(NodeTest, SimpleAppendSequence) { EXPECT_TRUE(node.IsSequence()); } +TEST(NodeTest, SequenceElementRemoval) { + Node node; + node[0] = "a"; + node[1] = "b"; + node[2] = "c"; + node.remove(1); + EXPECT_TRUE(node.IsSequence()); + EXPECT_EQ(2, node.size()); + EXPECT_EQ("a", node[0].as()); + EXPECT_EQ("c", node[1].as()); +} + +TEST(NodeTest, SequenceLastElementRemoval) { + Node node; + node[0] = "a"; + node[1] = "b"; + node[2] = "c"; + node.remove(2); + EXPECT_TRUE(node.IsSequence()); + EXPECT_EQ(2, node.size()); + EXPECT_EQ("a", node[0].as()); + EXPECT_EQ("b", node[1].as()); +} + TEST(NodeTest, MapElementRemoval) { Node node; node["foo"] = "bar"; @@ -54,6 +78,16 @@ TEST(NodeTest, MapElementRemoval) { EXPECT_TRUE(!node["foo"]); } +TEST(NodeTest, MapIntegerElementRemoval) { + Node node; + node[1] = "hello"; + node[2] = 'c'; + node["foo"] = "bar"; + EXPECT_TRUE(node.IsMap()); + node.remove(1); + EXPECT_TRUE(node.IsMap()); +} + TEST(NodeTest, SimpleAssignSequence) { Node node; node[0] = 10; @@ -106,6 +140,14 @@ TEST(NodeTest, RemoveUnassignedNode) { EXPECT_EQ(0, node.size()); } +TEST(NodeTest, RemoveUnassignedNodeFromMap) { + Node node(NodeType::Map); + Node n; + node[n]; + node.remove(n); + EXPECT_EQ(0, node.size()); +} + TEST(NodeTest, MapForceInsert) { Node node; Node k1("k1"); @@ -349,7 +391,13 @@ TEST(NodeTest, AutoBoolConversion) { EXPECT_TRUE(!!node["foo"]); } -TEST(NodeTest, FloatingPrecision) { +TEST(NodeTest, FloatingPrecisionFloat) { + const float x = 0.123456789; + Node node = Node(x); + EXPECT_EQ(x, node.as()); +} + +TEST(NodeTest, FloatingPrecisionDouble) { const double x = 0.123456789; Node node = Node(x); EXPECT_EQ(x, node.as()); @@ -410,108 +458,108 @@ class NodeEmitterTest : public ::testing::Test { TEST_F(NodeEmitterTest, SimpleFlowSeqNode) { Node node; node.SetStyle(EmitterStyle::Flow); - node.push_back(1.01); - node.push_back(2.01); - node.push_back(3.01); + node.push_back(1.5); + node.push_back(2.25); + node.push_back(3.125); - ExpectOutput("[1.01, 2.01, 3.01]", node); + ExpectOutput("[1.5, 2.25, 3.125]", node); } TEST_F(NodeEmitterTest, NestFlowSeqNode) { Node node, cell0, cell1; - cell0.push_back(1.01); - cell0.push_back(2.01); - cell0.push_back(3.01); + cell0.push_back(1.5); + cell0.push_back(2.25); + cell0.push_back(3.125); - cell1.push_back(4.01); - cell1.push_back(5.01); - cell1.push_back(6.01); + cell1.push_back(4.5); + cell1.push_back(5.25); + cell1.push_back(6.125); node.SetStyle(EmitterStyle::Flow); node.push_back(cell0); node.push_back(cell1); - ExpectOutput("[[1.01, 2.01, 3.01], [4.01, 5.01, 6.01]]", node); + ExpectOutput("[[1.5, 2.25, 3.125], [4.5, 5.25, 6.125]]", node); } TEST_F(NodeEmitterTest, MixBlockFlowSeqNode) { Node node, cell0, cell1; cell0.SetStyle(EmitterStyle::Flow); - cell0.push_back(1.01); - cell0.push_back(2.01); - cell0.push_back(3.01); + cell0.push_back(1.5); + cell0.push_back(2.25); + cell0.push_back(3.125); - cell1.push_back(4.01); - cell1.push_back(5.01); - cell1.push_back(6.01); + cell1.push_back(4.5); + cell1.push_back(5.25); + cell1.push_back(6.125); node.SetStyle(EmitterStyle::Block); node.push_back(cell0); node.push_back(cell1); - ExpectOutput("- [1.01, 2.01, 3.01]\n-\n - 4.01\n - 5.01\n - 6.01", node); + ExpectOutput("- [1.5, 2.25, 3.125]\n-\n - 4.5\n - 5.25\n - 6.125", node); } TEST_F(NodeEmitterTest, NestBlockFlowMapListNode) { Node node, mapNode, blockNode; - node.push_back(1.01); - node.push_back(2.01); - node.push_back(3.01); + node.push_back(1.5); + node.push_back(2.25); + node.push_back(3.125); mapNode.SetStyle(EmitterStyle::Flow); mapNode["position"] = node; - blockNode.push_back(1.01); + blockNode.push_back(1.0625); blockNode.push_back(mapNode); - ExpectOutput("- 1.01\n- {position: [1.01, 2.01, 3.01]}", blockNode); + ExpectOutput("- 1.0625\n- {position: [1.5, 2.25, 3.125]}", blockNode); } TEST_F(NodeEmitterTest, NestBlockMixMapListNode) { Node node, mapNode, blockNode; - node.push_back(1.01); - node.push_back(2.01); - node.push_back(3.01); + node.push_back(1.5); + node.push_back(2.25); + node.push_back(3.125); mapNode.SetStyle(EmitterStyle::Flow); mapNode["position"] = node; - blockNode["scalar"] = 1.01; + blockNode["scalar"] = 1.0625; blockNode["object"] = mapNode; ExpectAnyOutput(blockNode, - "scalar: 1.01\nobject: {position: [1.01, 2.01, 3.01]}", - "object: {position: [1.01, 2.01, 3.01]}\nscalar: 1.01"); + "scalar: 1.0625\nobject: {position: [1.5, 2.25, 3.125]}", + "object: {position: [1.5, 2.25, 3.125]}\nscalar: 1.5"); } TEST_F(NodeEmitterTest, NestBlockMapListNode) { Node node, mapNode; - node.push_back(1.01); - node.push_back(2.01); - node.push_back(3.01); + node.push_back(1.5); + node.push_back(2.25); + node.push_back(3.125); mapNode.SetStyle(EmitterStyle::Block); mapNode["position"] = node; - ExpectOutput("position:\n - 1.01\n - 2.01\n - 3.01", mapNode); + ExpectOutput("position:\n - 1.5\n - 2.25\n - 3.125", mapNode); } TEST_F(NodeEmitterTest, NestFlowMapListNode) { Node node, mapNode; - node.push_back(1.01); - node.push_back(2.01); - node.push_back(3.01); + node.push_back(1.5); + node.push_back(2.25); + node.push_back(3.125); mapNode.SetStyle(EmitterStyle::Flow); mapNode["position"] = node; - ExpectOutput("{position: [1.01, 2.01, 3.01]}", mapNode); + ExpectOutput("{position: [1.5, 2.25, 3.125]}", mapNode); } } } diff --git a/lib/yamlcpp/test/regex_test.cpp b/lib/yamlcpp/test/regex_test.cpp index 7589d2e4bf8..658db9e64dc 100644 --- a/lib/yamlcpp/test/regex_test.cpp +++ b/lib/yamlcpp/test/regex_test.cpp @@ -1,6 +1,6 @@ -#include "gtest/gtest.h" #include "regex_yaml.h" #include "stream.h" +#include "gtest/gtest.h" using YAML::RegEx; using YAML::Stream; @@ -106,8 +106,8 @@ TEST(RegExTest, OperatorOr) { for (int j = i + 1; j < 128; ++j) { auto iStr = std::string(1, char(i)); auto jStr = std::string(1, char(j)); - RegEx ex1 = RegEx(iStr) || RegEx(jStr); - RegEx ex2 = RegEx(jStr) || RegEx(iStr); + RegEx ex1 = RegEx(iStr) | RegEx(jStr); + RegEx ex2 = RegEx(jStr) | RegEx(iStr); for (int k = MIN_CHAR; k < 128; ++k) { auto str = std::string(1, char(k)); @@ -128,8 +128,8 @@ TEST(RegExTest, OperatorOr) { } TEST(RegExTest, OperatorOrShortCircuits) { - RegEx ex1 = RegEx(std::string("aaaa")) || RegEx(std::string("aa")); - RegEx ex2 = RegEx(std::string("aa")) || RegEx(std::string("aaaa")); + RegEx ex1 = RegEx(std::string("aaaa")) | RegEx(std::string("aa")); + RegEx ex2 = RegEx(std::string("aa")) | RegEx(std::string("aaaa")); EXPECT_TRUE(ex1.Matches(std::string("aaaaa"))); EXPECT_EQ(4, ex1.Match(std::string("aaaaa"))); @@ -139,13 +139,13 @@ TEST(RegExTest, OperatorOrShortCircuits) { } TEST(RegExTest, OperatorAnd) { - RegEx emptySet = RegEx('a') && RegEx(); + RegEx emptySet = RegEx('a') & RegEx(); EXPECT_FALSE(emptySet.Matches(std::string("a"))); } TEST(RegExTest, OperatorAndShortCircuits) { - RegEx ex1 = RegEx(std::string("aaaa")) && RegEx(std::string("aa")); - RegEx ex2 = RegEx(std::string("aa")) && RegEx(std::string("aaaa")); + RegEx ex1 = RegEx(std::string("aaaa")) & RegEx(std::string("aa")); + RegEx ex2 = RegEx(std::string("aa")) & RegEx(std::string("aaaa")); EXPECT_TRUE(ex1.Matches(std::string("aaaaa"))); EXPECT_EQ(4, ex1.Match(std::string("aaaaa"))); @@ -174,4 +174,4 @@ TEST(RegExTest, StringOr) { EXPECT_EQ(1, ex.Match(str)); } -} +} // namespace diff --git a/lib/yamlcpp/util/CMakeLists.txt b/lib/yamlcpp/util/CMakeLists.txt index 22866273c74..09dafa24c90 100644 --- a/lib/yamlcpp/util/CMakeLists.txt +++ b/lib/yamlcpp/util/CMakeLists.txt @@ -1,14 +1,26 @@ +cmake_minimum_required(VERSION 3.5) + add_sources(parse.cpp) add_executable(parse parse.cpp) +set_target_properties(parse PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED ON +) target_link_libraries(parse yaml-cpp) -set_target_properties(parse PROPERTIES COMPILE_FLAGS "-std=c++11") add_sources(sandbox.cpp) add_executable(sandbox sandbox.cpp) +set_target_properties(sandbox PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED ON +) target_link_libraries(sandbox yaml-cpp) -set_target_properties(sandbox PROPERTIES COMPILE_FLAGS "-std=c++11") add_sources(read.cpp) add_executable(read read.cpp) +set_target_properties(read PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED ON +) target_link_libraries(read yaml-cpp) -set_target_properties(read PROPERTIES COMPILE_FLAGS "-std=c++11") + From 73a6ecefd105b6113a0f9e968b01de0d1e541049 Mon Sep 17 00:00:00 2001 From: Bryan Call Date: Wed, 13 Nov 2019 15:43:46 -0800 Subject: [PATCH 156/718] Fixed gcc7 issue with yaml-cpp 0.6.3 (cherry picked from commit 8857fa37f2cb1d985eff34535bd5eac4e0f91a01) --- plugins/experimental/cookie_remap/cookie_remap.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/experimental/cookie_remap/cookie_remap.cc b/plugins/experimental/cookie_remap/cookie_remap.cc index b5eff3e06be..9fb6991e6b9 100644 --- a/plugins/experimental/cookie_remap/cookie_remap.cc +++ b/plugins/experimental/cookie_remap/cookie_remap.cc @@ -873,10 +873,10 @@ TSRemapNewInstance(int argc, char *argv[], void **ih, char *errbuf, int errbuf_s } for (YAML::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) { - const YAML::Node &first = it2->first; - const YAML::Node &second = it2->second; + const YAML::Node first = it2->first; + const YAML::Node second = it2->second; - if (second.Type() != YAML::NodeType::Scalar) { + if (second.IsScalar() == false) { const string reason = "All op nodes must be of type scalar"; TSError("Invalid YAML Configuration format for cookie_remap: %s, reason: %s", filename.c_str(), reason.c_str()); return TS_ERROR; From eed5cd8d21564325402769fce5f8e4d9d777bf89 Mon Sep 17 00:00:00 2001 From: Bryan Call Date: Fri, 8 Nov 2019 11:37:23 -0800 Subject: [PATCH 157/718] Fixed build issues with hwloc 2.x API changes (cherry picked from commit e655af7faeaaadd182ce17fd5bd617cafc95aff7) --- iocore/aio/AIO.cc | 5 +++++ iocore/eventsystem/UnixEventProcessor.cc | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/iocore/aio/AIO.cc b/iocore/aio/AIO.cc index 07eb8ae7439..5543919f817 100644 --- a/iocore/aio/AIO.cc +++ b/iocore/aio/AIO.cc @@ -192,8 +192,13 @@ struct AIOThreadInfo : public Continuation { (void)event; (void)e; #if TS_USE_HWLOC +#if HWLOC_API_VERSION >= 0x20000 + hwloc_set_membind(ink_get_topology(), hwloc_topology_get_topology_nodeset(ink_get_topology()), HWLOC_MEMBIND_INTERLEAVE, + HWLOC_MEMBIND_THREAD | HWLOC_MEMBIND_BYNODESET); +#else hwloc_set_membind_nodeset(ink_get_topology(), hwloc_topology_get_topology_nodeset(ink_get_topology()), HWLOC_MEMBIND_INTERLEAVE, HWLOC_MEMBIND_THREAD); +#endif #endif aio_thread_main(this); delete this; diff --git a/iocore/eventsystem/UnixEventProcessor.cc b/iocore/eventsystem/UnixEventProcessor.cc index 2661b678f58..c2f7fade8ba 100644 --- a/iocore/eventsystem/UnixEventProcessor.cc +++ b/iocore/eventsystem/UnixEventProcessor.cc @@ -230,7 +230,11 @@ ThreadAffinityInitializer::alloc_numa_stack(EThread *t, size_t stacksize) if (mem_policy != HWLOC_MEMBIND_DEFAULT) { // Let's temporarily set the memory binding to our destination NUMA node +#if HWLOC_API_VERSION >= 0x20000 + hwloc_set_membind(ink_get_topology(), nodeset, mem_policy, HWLOC_MEMBIND_THREAD | HWLOC_MEMBIND_BYNODESET); +#else hwloc_set_membind_nodeset(ink_get_topology(), nodeset, mem_policy, HWLOC_MEMBIND_THREAD); +#endif } // Alloc our stack @@ -238,8 +242,13 @@ ThreadAffinityInitializer::alloc_numa_stack(EThread *t, size_t stacksize) if (mem_policy != HWLOC_MEMBIND_DEFAULT) { // Now let's set it back to default for this thread. +#if HWLOC_API_VERSION >= 0x20000 + hwloc_set_membind(ink_get_topology(), hwloc_topology_get_topology_nodeset(ink_get_topology()), HWLOC_MEMBIND_DEFAULT, + HWLOC_MEMBIND_THREAD | HWLOC_MEMBIND_BYNODESET); +#else hwloc_set_membind_nodeset(ink_get_topology(), hwloc_topology_get_topology_nodeset(ink_get_topology()), HWLOC_MEMBIND_DEFAULT, HWLOC_MEMBIND_THREAD); +#endif } hwloc_bitmap_free(nodeset); From c6e9cc918eeafd7a450a3dda11ff80cce643bbf1 Mon Sep 17 00:00:00 2001 From: Randall Meyer Date: Thu, 14 Nov 2019 10:21:46 +0800 Subject: [PATCH 158/718] Fixes cppcheck issues for cookie_remap plugin (cherry picked from commit e2c4d72b090d75c0f2ea5be6b6910d96cc9cb94e) --- plugins/experimental/cookie_remap/cookie_remap.cc | 3 --- plugins/experimental/cookie_remap/cookiejar.cc | 5 ++--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/plugins/experimental/cookie_remap/cookie_remap.cc b/plugins/experimental/cookie_remap/cookie_remap.cc index 9fb6991e6b9..421c52d6c04 100644 --- a/plugins/experimental/cookie_remap/cookie_remap.cc +++ b/plugins/experimental/cookie_remap/cookie_remap.cc @@ -178,7 +178,6 @@ void urlencode(std::string &str) { size_t pos = 0; - std::string replacement; for (; pos < str.length(); pos++) { if (!isalnum(str[pos])) { char dec[2]; @@ -765,8 +764,6 @@ using OpMap = std::vector; static bool build_op(op &o, OpMap const &q) { - StringPair m; - subop *sub = new subop(); // loop through the array of key->value pairs diff --git a/plugins/experimental/cookie_remap/cookiejar.cc b/plugins/experimental/cookie_remap/cookiejar.cc index 0b3a05a41dc..1f7d5d33dbe 100644 --- a/plugins/experimental/cookie_remap/cookiejar.cc +++ b/plugins/experimental/cookie_remap/cookiejar.cc @@ -82,14 +82,13 @@ CookieJar::parse(const string &arg, const char *sepstr, bool val_check, bool mai cp = arg_copy; char empty[] = ""; for (key = strsep(&cp, sepstr); key != nullptr; key = strsep(&cp, sepstr)) { - int val_len; char *val = strchr(key, '='); char *addme = nullptr; if (val) { /* split key and value */ - *val++ = '\0'; - val_len = strlen(val); + *val++ = '\0'; + int val_len = strlen(val); if (val_len > 0) { /* if we have DQUOTES around our value then drop them */ From 9e5a07ae87297487a4d9aa7482729ac043944099 Mon Sep 17 00:00:00 2001 From: Randall Meyer Date: Thu, 14 Nov 2019 16:44:37 +0800 Subject: [PATCH 159/718] Fixes misc. spelling and whitespace (#6160) (cherry picked from commit 6ef4db40f24f707bbd05d5ef05cb2e4b5d35f91b) Conflicts: doc/admin-guide/files/records.config.en.rst doc/release-notes/upgrading.en.rst doc/release-notes/whats-new.en.rst --- doc/admin-guide/files/records.config.en.rst | 2 +- doc/developer-guide/api/functions/TSRemap.en.rst | 2 +- doc/developer-guide/plugins/remap-plugins.en.rst | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst index c11ce440de9..d9999df335a 100644 --- a/doc/admin-guide/files/records.config.en.rst +++ b/doc/admin-guide/files/records.config.en.rst @@ -319,7 +319,7 @@ Thread Variables .. ts:cv:: CONFIG proxy.config.exec_thread.listen INT 0 - If enabled (``1``) all the exex_threads listen for incoming connections. `proxy.config.accept_threads` + If enabled (``1``) all the exec_threads listen for incoming connections. `proxy.config.accept_threads` should be disabled to enable this variable. .. ts:cv:: CONFIG proxy.config.accept_threads INT 1 diff --git a/doc/developer-guide/api/functions/TSRemap.en.rst b/doc/developer-guide/api/functions/TSRemap.en.rst index 89df430907d..c541f2054fc 100644 --- a/doc/developer-guide/api/functions/TSRemap.en.rst +++ b/doc/developer-guide/api/functions/TSRemap.en.rst @@ -74,7 +74,7 @@ invoked by current and all previous still used configurations. This is an option :func:`TSRemapPostConfigReload` is called to indicate the end of the the new remap configuration load. It is called on the newly and previously loaded plugins, invoked by the new, current and -previous still used configurations. It also indicates wheather the configuration reload was successful +previous still used configurations. It also indicates whether the configuration reload was successful by passing :macro:`TSREMAP_CONFIG_RELOAD_FAILURE` in case of failure and to notify the plugins if they are going to be part of the new configuration by passing :macro:`TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED` or :macro:`TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED`. This is an optional entry point. diff --git a/doc/developer-guide/plugins/remap-plugins.en.rst b/doc/developer-guide/plugins/remap-plugins.en.rst index 9884834c575..b70a8ee17ab 100644 --- a/doc/developer-guide/plugins/remap-plugins.en.rst +++ b/doc/developer-guide/plugins/remap-plugins.en.rst @@ -53,7 +53,7 @@ should be placed in :arg:`errbuff`, taking note of the maximum size of the buffe :macro:`TS_SUCCESS`. If :func:`TSRemapInit` returns :macro:`TS_ERROR` then the remap configuration loading -is aborted immediatelly. +is aborted immediately. This function should perform any plugin global initialization, such as setting up static data tables. It only be called immediately after the dynamic library is loaded from disk. @@ -94,7 +94,7 @@ If there is an error then the callback should return :macro:`TS_ERROR` and fill :macro:`TS_SUCCESS`. If :func:`TSRemapNewInstance` returns :macro:`TS_ERROR` then the remap configuration loading -is aborted immediatelly. +is aborted immediately. Configuration reload notifications @@ -102,12 +102,12 @@ Configuration reload notifications Most of the plugins is assumed to use per-plugin-instance data-structures when reloading their configs and only a few of them that wish to optimize performance or deal with the complexities -of using a per-plugin DSO "global" data-structures would use pluging configuration reload +of using a per-plugin DSO "global" data-structures would use plugin configuration reload notifications like :func:`TSRemapPreConfigReload` and :func:`TSRemapPostConfigReload`. Instead of trying to foresee the needs or the expectations of each use-case, a more "open-ended" and straight-forward design was chosen for the configuration reload notifications. -The notifications are broadcasted to all loaded plugins at the moments before and after +The notifications are broadcast to all loaded plugins at the moments before and after the reload attempt, regardless of whether a plugin is part of the new configuration or not. :func:`TSRemapPreConfigReload` is called *before* the parsing of a new remap configuration starts @@ -116,13 +116,13 @@ invoked by current and all previous still used configurations. This is an option :func:`TSRemapPostConfigReload` is called to indicate the end of the the new remap configuration load. It is called on the newly and previously loaded plugins, invoked by the new, current and -previous still used configurations. It also indicates wheather the configuration reload was successful +previous still used configurations. It also indicates whether the configuration reload was successful by passing :macro:`TSREMAP_CONFIG_RELOAD_FAILURE` in case of failure and to notify the plugins if they are going to be part of the new configuration by passing :macro:`TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED` or :macro:`TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED`. This is an optional entry point. These calls are called per *plugin*, not per invocation of the plugin in :file:`remap.config` -and only will be called if the plugin was instantianted by at least one configuration loaded +and only will be called if the plugin was instantiated by at least one configuration loaded after the traffic server started and at least one configuration using it is still loaded. :func:`TSRemapPreConfigReload` will be called serially for all loaded plugins From 174a814e94226f58869b000cd9173266df601d9f Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Mon, 18 Nov 2019 11:36:42 +0800 Subject: [PATCH 160/718] Fix compile warnings in Catch checks for TextView (#6186) (cherry picked from commit e32814144f6f251074eb0ba567860e64e5f30edd) --- src/tscpp/util/unit_tests/test_TextView.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tscpp/util/unit_tests/test_TextView.cc b/src/tscpp/util/unit_tests/test_TextView.cc index d9ce540b1c8..869c278b0b6 100644 --- a/src/tscpp/util/unit_tests/test_TextView.cc +++ b/src/tscpp/util/unit_tests/test_TextView.cc @@ -36,10 +36,8 @@ TEST_CASE("TextView Constructor", "[libts][TextView]") { static std::string base = "Evil Dave Rulez!"; TextView tv(base); - TextView a{"Evil Dave Rulez"}; TextView b{base.data(), base.size()}; TextView c{std::string_view(base)}; - constexpr TextView d{"Grigor!"sv}; } TEST_CASE("TextView Operations", "[libts][TextView]") @@ -111,6 +109,8 @@ TEST_CASE("TextView Affixes", "[libts][TextView]") left = tv3; right = left.split_suffix_at(";:,"); TextView pre{tv3}, post{pre.split_suffix_at(7)}; + + REQUIRE(post.size() == 7); REQUIRE(right.size() == 7); REQUIRE(left.size() == 7); REQUIRE(left == "abcdefg"); From 8daecc8273dfda4f8a1c8d556bcd18be0c5776c4 Mon Sep 17 00:00:00 2001 From: "Alan M. Carroll" Date: Sat, 16 Nov 2019 14:23:49 -0600 Subject: [PATCH 161/718] RBTree - fix potential nullptr dereference (cherry picked from commit d2b0bacd0aeacaf3d813f2251847052c99f1a37e) --- src/tscore/RbTree.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tscore/RbTree.cc b/src/tscore/RbTree.cc index 156899725a4..23bb41741de 100644 --- a/src/tscore/RbTree.cc +++ b/src/tscore/RbTree.cc @@ -301,7 +301,7 @@ namespace detail parent = n->_parent; d = NONE; // Cancel any leaf node logic } else { - if (wfc->_color == BLACK) { + if (wfc == BLACK) { w->getChild(near)->_color = BLACK; w->_color = RED; w->rotate(far); From f6c79dd6d88eb0df074ce600a8f6ebd33429f3ae Mon Sep 17 00:00:00 2001 From: Randall Meyer Date: Sun, 17 Nov 2019 10:38:32 +0800 Subject: [PATCH 162/718] tslua: Exposes set/get version for server request objects (cherry picked from commit ddb6e33ae5067262b8df5a1ac0663649308a6ca7) --- doc/admin-guide/plugins/lua.en.rst | 37 ++++++++++++++++++- plugins/lua/ts_lua_server_request.c | 56 +++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/doc/admin-guide/plugins/lua.en.rst b/doc/admin-guide/plugins/lua.en.rst index 53624350cd0..9f526927388 100644 --- a/doc/admin-guide/plugins/lua.en.rst +++ b/doc/admin-guide/plugins/lua.en.rst @@ -1940,11 +1940,46 @@ ts.server_request.set_method **description:** This function can be used to override the current server request's method with METHOD_NAME. :: - ts.server_request.set_method('HEAD') :ref:`TOP ` +ts.server_request_get_version +------------------------------ +**syntax:** *ver = ts.server_request.get_version()* + +**context:** function @ TS_LUA_HOOK_SEND_REQUEST_HDR hook point or later. + +**description:** Return the http version string of the server request. + +Current possible values are 1.0, 1.1, and 0.9. +:: + function send_request() + local version = ts.server_request.get_version() + ts.debug(version) + end + + function do_remap() + ts.hook(TS_LUA_HOOK_SEND_REQUEST_HDR, send_request) + return 0 + end + +:ref:`TOP ` + +ts.server_request.set_version +------------------------------ +**syntax:** *ts.server_request.set_version(VERSION_STR)* + +**context:** function @ TS_LUA_HOOK_READ_RESPONSE_HDR hook point + +**description:** Set the http version of the server request with the VERSION_STR + +:: + + ts.server_request.set_version('1.0') + +:ref:`TOP ` + ts.server_response.get_status ----------------------------- **syntax:** *status = ts.server_response.get_status()* diff --git a/plugins/lua/ts_lua_server_request.c b/plugins/lua/ts_lua_server_request.c index 2aa7e459358..8e65fe3b84d 100644 --- a/plugins/lua/ts_lua_server_request.c +++ b/plugins/lua/ts_lua_server_request.c @@ -70,6 +70,8 @@ static int ts_lua_server_request_get_url_host(lua_State *L); static int ts_lua_server_request_set_url_host(lua_State *L); static int ts_lua_server_request_get_url_scheme(lua_State *L); static int ts_lua_server_request_set_url_scheme(lua_State *L); +static int ts_lua_server_request_get_version(lua_State *L); +static int ts_lua_server_request_set_version(lua_State *L); static int ts_lua_server_request_server_addr_get_ip(lua_State *L); static int ts_lua_server_request_server_addr_get_port(lua_State *L); @@ -566,6 +568,11 @@ ts_lua_inject_server_request_url_api(lua_State *L) lua_setfield(L, -2, "get_url_scheme"); lua_pushcfunction(L, ts_lua_server_request_set_url_scheme); lua_setfield(L, -2, "set_url_scheme"); + + lua_pushcfunction(L, ts_lua_server_request_get_version); + lua_setfield(L, -2, "get_version"); + lua_pushcfunction(L, ts_lua_server_request_set_version); + lua_setfield(L, -2, "set_version"); } static int @@ -662,6 +669,55 @@ ts_lua_server_request_set_url_scheme(lua_State *L) return 0; } +static int +ts_lua_server_request_get_version(lua_State *L) +{ + int version; + char buf[32]; + int n; + + ts_lua_http_ctx *http_ctx; + + GET_HTTP_CONTEXT(http_ctx, L); + TS_LUA_CHECK_SERVER_REQUEST_HDR(http_ctx); + + version = TSHttpHdrVersionGet(http_ctx->server_request_bufp, http_ctx->server_request_hdrp); + + n = snprintf(buf, sizeof(buf), "%d.%d", TS_HTTP_MAJOR(version), TS_HTTP_MINOR(version)); + + if (n >= (int)sizeof(buf)) { + lua_pushlstring(L, buf, sizeof(buf) - 1); + } else if (n > 0) { + lua_pushlstring(L, buf, n); + } + + return 1; +} + +static int +ts_lua_server_request_set_version(lua_State *L) +{ + const char *version; + size_t len; + int major, minor; + + ts_lua_http_ctx *http_ctx; + + GET_HTTP_CONTEXT(http_ctx, L); + + TS_LUA_CHECK_SERVER_REQUEST_HDR(http_ctx); + + version = luaL_checklstring(L, 1, &len); + + if (sscanf(version, "%2u.%2u", &major, &minor) != 2) { + return luaL_error(L, "failed to set version. Format must be X.Y"); + } + + TSHttpHdrVersionSet(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, TS_HTTP_VERSION(major, minor)); + + return 0; +} + static int ts_lua_server_request_server_addr_get_ip(lua_State *L) { From 97db8184b9a9b3c8852a182c976cef8085476a66 Mon Sep 17 00:00:00 2001 From: Randall Meyer Date: Fri, 15 Nov 2019 12:52:15 +0800 Subject: [PATCH 163/718] Remove HttpTransact::build_upgrade_response The code that called this was removed in 2a42c0ed8d4b8967f42b215bbb39e7f2319b8745 (cherry picked from commit 26f7f0af1725da9f0537da29bc4944cd6a4c44ba) --- proxy/http/HttpTransact.cc | 18 ------------------ proxy/http/HttpTransact.h | 1 - 2 files changed, 19 deletions(-) diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc index 6c673fcae63..59d8f2b145b 100644 --- a/proxy/http/HttpTransact.cc +++ b/proxy/http/HttpTransact.cc @@ -7962,24 +7962,6 @@ HttpTransact::build_redirect_response(State *s) s->arena.str_free(to_free); } -void -HttpTransact::build_upgrade_response(State *s) -{ - TxnDebug("http_upgrade", "[HttpTransact::build_upgrade_response]"); - - // 101 Switching Protocols - HTTPStatus status_code = HTTP_STATUS_SWITCHING_PROTOCOL; - const char *reason_phrase = http_hdr_reason_lookup(status_code); - build_response(s, &s->hdr_info.client_response, s->client_info.http_version, status_code, reason_phrase); - - ////////////////////////// - // set upgrade headers // - ////////////////////////// - HTTPHdr *h = &s->hdr_info.client_response; - h->value_set(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION, "Upgrade", strlen("Upgrade")); - h->value_set(MIME_FIELD_UPGRADE, MIME_LEN_UPGRADE, MIME_UPGRADE_H2C_TOKEN, strlen(MIME_UPGRADE_H2C_TOKEN)); -} - const char * HttpTransact::get_error_string(int erno) { diff --git a/proxy/http/HttpTransact.h b/proxy/http/HttpTransact.h index 59948c7f133..093cba1103d 100644 --- a/proxy/http/HttpTransact.h +++ b/proxy/http/HttpTransact.h @@ -1057,7 +1057,6 @@ class HttpTransact static void build_error_response(State *s, HTTPStatus status_code, const char *reason_phrase_or_null, const char *error_body_type); static void build_redirect_response(State *s); - static void build_upgrade_response(State *s); static const char *get_error_string(int erno); // the stat functions From e8ca3ed21bf531a56a15a824da330e3001dfc2cb Mon Sep 17 00:00:00 2001 From: Brian Olsen Date: Fri, 12 Jul 2019 14:17:38 +0000 Subject: [PATCH 164/718] slice plugin add support for using effective url with remap host. (cherry picked from commit 2f24fca3b901444a6b63901cd816445d2c9418d6) --- doc/admin-guide/plugins/slice.en.rst | 61 +++++++++++--- plugins/experimental/slice/Config.cc | 44 ++++++---- plugins/experimental/slice/Config.h | 3 +- plugins/experimental/slice/Data.h | 12 +-- plugins/experimental/slice/README.md | 84 ++++++++++++------- plugins/experimental/slice/client.cc | 2 +- plugins/experimental/slice/slice.cc | 81 +++++++++++++----- .../gold_tests/pluginTest/slice/slice.test.py | 2 +- .../pluginTest/slice/slice_error.test.py | 2 +- 9 files changed, 201 insertions(+), 90 deletions(-) diff --git a/doc/admin-guide/plugins/slice.en.rst b/doc/admin-guide/plugins/slice.en.rst index 06ae34e564c..f928fa13ea3 100644 --- a/doc/admin-guide/plugins/slice.en.rst +++ b/doc/admin-guide/plugins/slice.en.rst @@ -69,17 +69,25 @@ The slice plugin supports the following options:: Suffix k,m,g supported Limited to 32k and 32m inclusive. - --test-blockbytes= (optional) + --blockbytes-test= (optional) Suffix k,m,g supported -t for short. Limited to any positive number. Ignored if --blockbytes provided. + --remap-host= (optional) + Uses effective url with given hostname for remapping. + Requires setting up an intermediate loopback remap rule. + -r for short + --pace-errorlog= (optional) Limit stitching error logs to every 'n' second(s) + -p for short --disable-errorlog (optional) Disable writing block stitch errors to the error log. + -d for short + Examples:: @@ -95,10 +103,10 @@ Byte suffix examples:: slice.so -b 512k slice.so --blockbytes=32m -For testing and extreme purposes the parameter ``test-blockbytes`` may +For testing and extreme purposes the parameter ``blockbytes-test`` may be used instead which is unchecked:: - slice.so --test-blockbytes=1G + slice.so --blockbytes-test=1G slice.so -t 13 Because the slice plugin is susceptible to errors during block stitching @@ -128,9 +136,11 @@ Under normal logging these slice block errors tend to show up as:: crc value ERR_READ_ERROR By default more detailed stitching errors are written to ``diags.log``. -An example is as follows:: +Examples are as follows:: -[Apr 19 20:26:13.639] [ET_NET 17] ERROR: [slice] 1555705573.639 reason="Non 206 internal block response" uri="http://localhost:18080/%7Ep.tex/%7Es.50M/%7Eui.20000/" uas="curl/7.29.0" req_range="bytes=1000000-" norm_range="bytes 1000000-52428799/52428800" etag_exp="%221603934496%22" lm_exp="Fri, 19 Apr 2019 18:53:20 GMT" blk_range="21000000-21999999" status_got="400" cr_got="" etag_got="" lm_got="" cc="no-store" via="" +ERROR: [slice.cc: 288] logSliceError(): 1555705573.639 reason="Non 206 internal block response" uri="http://ats_ep/someasset.mp4" uas="curl" req_range="bytes=1000000-" norm_range="bytes 1000000-52428799/52428800" etag_exp="%221603934496%22" lm_exp="Fri, 19 Apr 2019 18:53:20 GMT" blk_range="21000000-21999999" status_got="206" cr_got="" etag_got="%221603934496%22" lm_got="" cc="no-store" via="" + +ERROR: [server.cc: 288] logSliceError(): 1572370000.219 reason="Mismatch block Etag" uri="http://ats_ep/someasset.mp4" uas="curl" req_range="bytes=1092779033-1096299354" norm_range="bytes 1092779033-1096299354/2147483648" etag_exp="%223719843648%22" lm_exp="Tue, 29 Oct 2019 14:40:00 GMT" blk_range="1095000000-1095999999" status_got="206" cr_got="bytes 1095000000-1095999999/2147483648" etag_got="%223719853648%22" lm_got="Tue, 29 Oct 2019 17:26:40 GMT" cc="max-age=10000" via="" Whether or how often these detailed log entries are written are configurable plugin options. @@ -204,14 +214,43 @@ by cache_range_requests. The parent will trim those requests to account for the asset Content-Length so only the appropriate number of bytes are actually transferred and cached. -Current Limitations +Effective URL remap =================== -By restoring the pristine Url the plugin as it works today reuses the -same remap rule for each slice block. This is wasteful in that it reruns +By default the plugin restores the Pristine Url which reuses the same +remap rule for each slice block. This is wasteful in that it reruns the previous remap rules, and those remap rules must be smart enough to -check for the existence of any headers they may have created the -first time they have were visited. +check for the existence of any headers they may have created the first +time they have were visited. + +To get around this the '--remap-host=' or '-r ' option may +be used. This requires an intermediate loopback remap to be defined which +handles each slice block request. + +This works well with any remap rules that use the url_sig or uri_signing +plugins. As the client remap rule is not caching any plugins that +manipulate the cache key would need to go into the loopback to parent +remap rule. + +NOTE: Requests NOT handled by the slice plugin (ie: HEAD requests) are +handled as with a typical remap rule. GET requests intercepted by the +slice plugin are virtually reissued into ATS and are proxied through +another remap rule which must contain the ``cache_range_requests`` plugin + +Examples:: + + map http://ats/ http://parent/ @plugin=slice.so @pparam=--remap-host=loopback + map http://loopback/ http://parent/ @plugin=cache_range_requests.so + +Alternatively:: + + map http://ats/ http://parent/ @plugin=slice.so @pparam=-r @pparam=loopback + map http://loopback/ http://parent/ @plugin=cache_range_requests.so + +Current Limitations +=================== Since the Slice plugin is written as an intercept handler it loses the -ability to use normal state machine hooks and transaction states. +ability to use normal state machine hooks and transaction states. This +functionality is handled by using the ``cache_range_requests`` plugin +to interact with ATS. diff --git a/plugins/experimental/slice/Config.cc b/plugins/experimental/slice/Config.cc index 2198011d0e4..6d27089dbe4 100644 --- a/plugins/experimental/slice/Config.cc +++ b/plugins/experimental/slice/Config.cc @@ -29,21 +29,22 @@ int64_t Config::bytesFrom(char const *const valstr) { - char *endptr = nullptr; - int64_t blockbytes = strtoll(valstr, &endptr, 10); + char *endptr = nullptr; + int64_t blockbytes = strtoll(valstr, &endptr, 10); + constexpr int64_t kib = 1024; if (nullptr != endptr && valstr < endptr) { size_t const dist = endptr - valstr; if (dist < strlen(valstr) && 0 <= blockbytes) { switch (tolower(*endptr)) { case 'g': - blockbytes *= (static_cast(1024) * static_cast(1024) * static_cast(1024)); + blockbytes *= (kib * kib * kib); break; case 'm': - blockbytes *= (static_cast(1024) * static_cast(1024)); + blockbytes *= (kib * kib); break; case 'k': - blockbytes *= static_cast(1024); + blockbytes *= kib; break; default: break; @@ -66,7 +67,7 @@ Config::fromArgs(int const argc, char const *const argv[]) DEBUG_LOG("args[%d] = %s", index, argv[index]); } - // current "best" blockbytes from configuration + // look for lowest priority deprecated blockbytes int64_t blockbytes = 0; // backwards compat: look for blockbytes @@ -91,9 +92,10 @@ Config::fromArgs(int const argc, char const *const argv[]) } // standard parsing - constexpr const struct option longopts[] = { + constexpr struct option longopts[] = { {const_cast("blockbytes"), required_argument, nullptr, 'b'}, - {const_cast("test-blockbytes"), required_argument, nullptr, 't'}, + {const_cast("blockbytes-test"), required_argument, nullptr, 't'}, + {const_cast("remap-host"), required_argument, nullptr, 'r'}, {const_cast("pace-errorlog"), required_argument, nullptr, 'p'}, {const_cast("disable-errorlog"), no_argument, nullptr, 'd'}, {nullptr, 0, nullptr, 0}, @@ -101,9 +103,8 @@ Config::fromArgs(int const argc, char const *const argv[]) // getopt assumes args start at '1' so this hack is needed char *const *argvp = (const_cast(argv) - 1); - for (;;) { - int const opt = getopt_long(argc + 1, argvp, "b:t:p:d", longopts, nullptr); + int const opt = getopt_long(argc + 1, argvp, "b:t:r:p:d", longopts, nullptr); if (-1 == opt) { break; } @@ -120,25 +121,29 @@ Config::fromArgs(int const argc, char const *const argv[]) ERROR_LOG("Invalid blockbytes: %s", optarg); } } break; - case 't': + case 't': { if (0 == blockbytes) { int64_t const bytesread = bytesFrom(optarg); if (0 < bytesread) { - DEBUG_LOG("Using blockbytestest %" PRId64, bytesread); + DEBUG_LOG("Using blockbytes-test %" PRId64, bytesread); blockbytes = bytesread; } else { - ERROR_LOG("Invalid blockbytestest: %s", optarg); + ERROR_LOG("Invalid blockbytes-test: %s", optarg); } } else { - DEBUG_LOG("Skipping blockbytestest in favor of blockbytes"); + DEBUG_LOG("Skipping blockbytes-test in favor of blockbytes"); } + } break; + case 'r': + m_remaphost = optarg; + DEBUG_LOG("Using loopback remap host override: %s", m_remaphost.c_str()); break; case 'p': { int const secsread = atoi(optarg); if (0 < secsread) { m_paceerrsecs = std::min(secsread, 60); } else { - DEBUG_LOG("Ignoring pace-errlog argument"); + ERROR_LOG("Ignoring pace-errlog argument"); } } break; case 'd': @@ -170,8 +175,6 @@ Config::fromArgs(int const argc, char const *const argv[]) bool Config::canLogError() { - std::lock_guard const guard(m_mutex); - if (m_paceerrsecs < 0) { return false; } else if (0 == m_paceerrsecs) { @@ -180,13 +183,18 @@ Config::canLogError() #if !defined(UNITTEST) TSHRTime const timenow = TShrtime(); +#endif + + std::lock_guard const guard(m_mutex); + +#if !defined(UNITTEST) if (timenow < m_nextlogtime) { return false; } m_nextlogtime = timenow + TS_HRTIME_SECONDS(m_paceerrsecs); #else - m_nextlogtime = 0; // thanks clang + m_nextlogtime = 0; // needed by clang #endif return true; diff --git a/plugins/experimental/slice/Config.h b/plugins/experimental/slice/Config.h index 8c4ab2498fa..8c191b06c0c 100644 --- a/plugins/experimental/slice/Config.h +++ b/plugins/experimental/slice/Config.h @@ -29,7 +29,8 @@ struct Config { static constexpr int64_t const blockbytesdefault = 1024 * 1024; // 1MB int64_t m_blockbytes{blockbytesdefault}; - int m_paceerrsecs{0}; // -1 disable logging, 0 no pacing, max 60s + std::string m_remaphost; // remap host to use for loopback slice GET + int m_paceerrsecs{0}; // -1 disable logging, 0 no pacing, max 60s // Convert optarg to bytes static int64_t bytesFrom(char const *const valstr); diff --git a/plugins/experimental/slice/Data.h b/plugins/experimental/slice/Data.h index 45383522103..30996438c31 100644 --- a/plugins/experimental/slice/Data.h +++ b/plugins/experimental/slice/Data.h @@ -39,8 +39,8 @@ struct Data { sockaddr_storage m_client_ip; - // for pristine url coming in - TSMBuffer m_urlbuffer{nullptr}; + // for pristine/effective url coming in + TSMBuffer m_urlbuf{nullptr}; TSMLoc m_urlloc{nullptr}; char m_hostname[8192]; @@ -80,7 +80,7 @@ struct Data { explicit Data(Config *const config) : m_config(config), m_client_ip(), - m_urlbuffer(nullptr), + m_urlbuf(nullptr), m_urlloc(nullptr), m_hostlen(0), m_etaglen(0), @@ -113,11 +113,11 @@ struct Data { ~Data() { // decrData(); - if (nullptr != m_urlbuffer) { + if (nullptr != m_urlbuf) { if (nullptr != m_urlloc) { - TSHandleMLocRelease(m_urlbuffer, TS_NULL_MLOC, m_urlloc); + TSHandleMLocRelease(m_urlbuf, TS_NULL_MLOC, m_urlloc); } - TSMBufferDestroy(m_urlbuffer); + TSMBufferDestroy(m_urlbuf); } if (nullptr != m_http_parser) { TSHttpParserDestroy(m_http_parser); diff --git a/plugins/experimental/slice/README.md b/plugins/experimental/slice/README.md index ec3d1bc420f..31746ffda45 100644 --- a/plugins/experimental/slice/README.md +++ b/plugins/experimental/slice/README.md @@ -15,66 +15,86 @@ The plugin uses TSHttpConnect to delegate each block request to cache_range_requests.so which handles all cache and parent interaction. To enable the plugin, specify the plugin library via @plugin at the end -of a remap line as follows (2MB slice in this example): +of a remap line as follows (default 1MB slice in this example): ``` -map http://ats-cache/ http://parent/ @plugin=slice.so @pparam=--blockbytes=2M @plugin=cache_range_requests.so +map http://ats-cache/ http://parent/ @plugin=slice.so @plugin=cache_range_requests.so +map https://ats-cache/ http://parent/ @plugin=slice.so @plugin=cache_range_requests.so ``` -alternatively +alternatively (2MB slice block) ``` map http://ats-cache/ http://parent/ @plugin=slice.so @pparam=-b @pparam=2M @plugin=cache_range_requests.so -``` - -for global plugins. - -``` -slice.so --blockbytes=2097152 -cache_range_requests.so -``` - -alternatively: - -``` -slice.so -b 2M -cache_range_requests.so +map https://ats-cache/ http://parent/ @plugin=slice.so @pparam=--blockbytes=2M @plugin=cache_range_requests.so ``` Options for the slice plugin (typically last one wins): ``` --blockbytes= (optional) Slice block size. - Default is 1m or 1048576 bytes. + Default is 1m or 1048576 bytes. also -b - Suffix k,m,g supported. - Limited to 32k and 32m inclusive. - For backwards compatibility blockbytes: is also supported. + Suffix k,m,g supported. + Limited to 32k and 32m inclusive. + For backwards compatibility blockbytes: is also supported. ---test-blockbytes= (optional) +--blockbytes-test= (optional) Slice block size for testing. also -t - Suffix k,m,g supported. - Limited to any positive number. - Ignored if --blockbytes is provided. + Suffix k,m,g supported. + Limited to any positive number. + Ignored if --blockbytes is provided. + +--remap-host= (optional) + Uses effective url with given host and port 0 for remapping. + Requires setting up an intermediate loopback remap rule. + -r for short --pace-errorlog= (optional) Limit stitching error logs to every 'n' second(s) Default is to log all errors (no pacing). - also -p + also -e --disable-errorlog (optional) Disable writing stitching errors to the error log. also -d ``` -**Note**: cache_range_requests **MUST** follow slice.so Put these plugins -at the end of the plugin list +By default the plugin uses the pristine url to loopback call back +into the same rule as each range slice is issued. The effective url +with loopback remap host may be used by adding the '-r ' or +'--remap-host=' plugin option. + +Using the `--remap-host` option splits the plugin chain into 2 remap rules. +One remap rule for all the incoming requests and the other for just the block +range requests. This allows for easier trouble shooting via logs and +also allows for more effecient plugin rules. The default pristine method +runs the remap plugins twice, one for the incoming request and one for +eace slice. Splitting the rules allows for plugins like URI signing to +be done on the client request only. + +NOTE: Requests NOT handled by the slice plugin (ie: HEAD requests) are +handled as with a typical remap rule. GET requests intercepted by the +slice plugin are virtually reissued into ATS and are forward proxied +through the cache_range_requests plugin. + +``` +map http://ats/ http://parent/ @plugin=slice.so @pparam=--blockbytes=512k @pparam=--remap-host=loopback +map https://ats/ https://parent/ @plugin=slice.so @pparam=--blockbytes=512k @pparam=--remap-host=loopback + +# Virtual forward proxy for slice range blocks +map http://loopback/ http://parent/ @plugin=cache_range_requests.so +map https://loopback/ http://parent/ @plugin=cache_range_requests.so +``` + +**Note**: For default pristine behavior cache_range_requests **MUST** +follow slice.so Put these plugins at the end of the plugin list **Note**: blockbytes is defined in bytes. Postfix for 'K', 'M' and 'G' may be used. 1048576 (1MB) is the default. -For testing purposes an unchecked value of "bytesover" is also available. +For testing purposes an unchecked value of "blockbytes-test" is also available. Debug output can be enable by setting the debug tag: **slice**. If debug is enabled all block stitch errors will log to diags.log @@ -90,9 +110,9 @@ provided to help with debugging. Below is a sample error log entry:: Current error types logged: ``` Mismatch block Etag - Mismatch block Last-Modified - Non 206 internal block response - Mismatch/Bad block Content-Range + Mismatch block Last-Modified + Non 206 internal block response + Mismatch/Bad block Content-Range ``` diff --git a/plugins/experimental/slice/client.cc b/plugins/experimental/slice/client.cc index 47ac4e3383c..adf0a4a0fa6 100644 --- a/plugins/experimental/slice/client.cc +++ b/plugins/experimental/slice/client.cc @@ -106,7 +106,7 @@ handle_client_req(TSCont contp, TSEvent event, Data *const data) HttpHeader header(data->m_req_hdrmgr.m_buffer, data->m_req_hdrmgr.m_lochdr); // set the request url back to pristine in case of plugin stacking - header.setUrl(data->m_urlbuffer, data->m_urlloc); + header.setUrl(data->m_urlbuf, data->m_urlloc); header.setKeyVal(TS_MIME_FIELD_HOST, TS_MIME_LEN_HOST, data->m_hostname, data->m_hostlen); diff --git a/plugins/experimental/slice/slice.cc b/plugins/experimental/slice/slice.cc index 5b5c90b48d9..432e119a966 100644 --- a/plugins/experimental/slice/slice.cc +++ b/plugins/experimental/slice/slice.cc @@ -76,32 +76,75 @@ read_request(TSHttpTxn txnp, Config *const config) return false; } - // need the pristine url, especially for global plugins - TSMBuffer urlbuf; - TSMLoc urlloc; - TSReturnCode rcode = TSHttpTxnPristineUrlGet(txnp, &urlbuf, &urlloc); - - if (TS_SUCCESS == rcode) { - TSMBuffer const newbuf = TSMBufferCreate(); - TSMLoc newloc = nullptr; - rcode = TSUrlClone(newbuf, urlbuf, urlloc, &newloc); - TSHandleMLocRelease(urlbuf, TS_NULL_MLOC, urlloc); - - if (TS_SUCCESS != rcode) { - ERROR_LOG("Error cloning pristine url"); - delete data; - TSMBufferDestroy(newbuf); - return false; + // is the plugin configured to use a remap host? + std::string const &newhost = config->m_remaphost; + if (newhost.empty()) { + TSMBuffer urlbuf; + TSMLoc urlloc; + TSReturnCode rcode = TSHttpTxnPristineUrlGet(txnp, &urlbuf, &urlloc); + + if (TS_SUCCESS == rcode) { + TSMBuffer const newbuf = TSMBufferCreate(); + TSMLoc newloc = nullptr; + rcode = TSUrlClone(newbuf, urlbuf, urlloc, &newloc); + TSHandleMLocRelease(urlbuf, TS_NULL_MLOC, urlloc); + + if (TS_SUCCESS != rcode) { + ERROR_LOG("Error cloning pristine url"); + TSMBufferDestroy(newbuf); + delete data; + return false; + } + + data->m_urlbuf = newbuf; + data->m_urlloc = newloc; } + } else { // grab the effective url, swap out the host and zero the port + int len = 0; + char *const effstr = TSHttpTxnEffectiveUrlStringGet(txnp, &len); + + if (nullptr != effstr) { + TSMBuffer const newbuf = TSMBufferCreate(); + TSMLoc newloc = nullptr; + bool okay = false; + + if (TS_SUCCESS == TSUrlCreate(newbuf, &newloc)) { + char const *start = effstr; + if (TS_PARSE_DONE == TSUrlParse(newbuf, newloc, &start, start + len)) { + if (TS_SUCCESS == TSUrlHostSet(newbuf, newloc, newhost.c_str(), newhost.size()) && + TS_SUCCESS == TSUrlPortSet(newbuf, newloc, 0)) { + okay = true; + } + } + } + + TSfree(effstr); + + if (!okay) { + ERROR_LOG("Error cloning effective url"); + if (nullptr != newloc) { + TSHandleMLocRelease(newbuf, nullptr, newloc); + } + TSMBufferDestroy(newbuf); + delete data; + return false; + } + + data->m_urlbuf = newbuf; + data->m_urlloc = newloc; + } + } - data->m_urlbuffer = newbuf; - data->m_urlloc = newloc; + if (TSIsDebugTagSet(PLUGIN_NAME)) { + int len = 0; + char *const urlstr = TSUrlStringGet(data->m_urlbuf, data->m_urlloc, &len); + DEBUG_LOG("slice url: %.*s", len, urlstr); + TSfree(urlstr); } // we'll intercept this GET and do it ourselves TSCont const icontp(TSContCreate(intercept_hook, TSMutexCreate())); TSContDataSet(icontp, (void *)data); - // TSHttpTxnHookAdd(txnp, TS_HTTP_TXN_CLOSE_HOOK, icontp); TSHttpTxnIntercept(icontp, txnp); return true; } else { diff --git a/tests/gold_tests/pluginTest/slice/slice.test.py b/tests/gold_tests/pluginTest/slice/slice.test.py index eafaef8b755..81e1f563f5b 100644 --- a/tests/gold_tests/pluginTest/slice/slice.test.py +++ b/tests/gold_tests/pluginTest/slice/slice.test.py @@ -113,7 +113,7 @@ remap_config_path = ts.Disk.remap_config.Name tr.Disk.File(remap_config_path, typename="ats:config").AddLines([ 'map / http://127.0.0.1:{}'.format(server.Variables.Port) + - ' @plugin=slice.so @pparam=--test-blockbytes={}'.format(block_bytes) + ' @plugin=slice.so @pparam=--blockbytes-test={}'.format(block_bytes) ]) tr.StillRunningAfter = ts diff --git a/tests/gold_tests/pluginTest/slice/slice_error.test.py b/tests/gold_tests/pluginTest/slice/slice_error.test.py index 830ecaad945..0ae06f1f23c 100644 --- a/tests/gold_tests/pluginTest/slice/slice_error.test.py +++ b/tests/gold_tests/pluginTest/slice/slice_error.test.py @@ -242,7 +242,7 @@ # set up whole asset fetch into cache ts.Disk.remap_config.AddLine( 'map / http://127.0.0.1:{}'.format(server.Variables.Port) + - ' @plugin=slice.so @pparam=--test-blockbytes={}'.format(blockbytes) + ' @plugin=slice.so @pparam=--blockbytes-test={}'.format(blockbytes) ) # minimal configuration From 95ce78ee99781adc7edc236eaf70ba99217e1d64 Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Mon, 18 Nov 2019 14:56:49 +0800 Subject: [PATCH 165/718] Replaces Python -> Python3 in a few utilities (#6187) (cherry picked from commit ae62e8a120eb4ea6d5925917fe9db11b8d5d0bf0) --- contrib/python/compare_RecordsConfigcc.py | 36 +++++++++++------------ contrib/python/compare_records_config.py | 4 +-- tools/check-unused-dependencies | 2 +- 3 files changed, 21 insertions(+), 21 deletions(-) mode change 100644 => 100755 contrib/python/compare_RecordsConfigcc.py mode change 100644 => 100755 contrib/python/compare_records_config.py diff --git a/contrib/python/compare_RecordsConfigcc.py b/contrib/python/compare_RecordsConfigcc.py old mode 100644 new mode 100755 index 90835c97fb5..a2d9b948562 --- a/contrib/python/compare_RecordsConfigcc.py +++ b/contrib/python/compare_RecordsConfigcc.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file @@ -23,8 +23,8 @@ try: src_dir = sys.argv[1] except IndexError: - print "Usage: %s [trafficserver_source_dir]" % sys.argv[0] - print "Compares values in RecordsConfig.cc with the default records.config file" + print("Usage: %s [trafficserver_source_dir]" % sys.argv[0]) + print("Compares values in RecordsConfig.cc with the default records.config file") sys.exit(1) # We expect these keys to differ between files, so ignore them @@ -52,12 +52,12 @@ m = cc_re.search(line) if m: value = m.group(3) - value = string.lstrip(value, '"') - value = string.rstrip(value, '"') + value = value.lstrip('"') + value = value.rstrip('"') rc_cc[m.group(1)] = (m.group(2), value) # Process records.config.default.in -with open("%s/proxy/config/records.config.default.in" % src_dir) as fh: +with open("%s/configs/records.config.default.in" % src_dir) as fh: in_re = re.compile(r'(?:CONFIG|LOCAL) (\S+)\s+(\S+)\s+(\S+)') for line in fh: m = in_re.match(line) @@ -77,37 +77,37 @@ # Compare the two # If a value is in RecordsConfig.cc and not records.config.default.in, it is # ignored right now. -print "# Comparing RecordsConfig.cc -> records.config.default.in" +print("# Comparing RecordsConfig.cc -> records.config.default.in") for key in rc_in: if key in ignore_keys: continue if key not in rc_cc: - print "%s missing -> %s" % (key, "%s %s" % rc_in[key]) + print("%s missing -> %s" % (key, "%s %s" % rc_in[key])) continue if rc_cc[key] != rc_in[key]: - print "%s : %s -> %s" % (key, "%s %s" % rc_cc[key], "%s %s" % rc_in[key]) + print("%s : %s -> %s" % (key, "%s %s" % rc_cc[key], "%s %s" % rc_in[key])) # Search for undocumented variables ... missing = [k for k in rc_cc if k not in rc_doc] if len(missing) > 0: - print - print "Undocumented configuration variables:" + print() + print("Undocumented configuration variables:") for m in sorted(missing): - print "\t%s %s" % (m, "%s %s" % rc_cc[m]) + print("\t%s %s" % (m, "%s %s" % rc_cc[m])) # Search for incorrectly documented default values ... defaults = [k for k in rc_cc if k in rc_doc and rc_cc[k] != rc_doc[k]] if len(defaults) > 0: - print - print "Incorrectly documented defaults:" + print() + print("Incorrectly documented defaults:") for d in sorted(defaults): - print "\t%s %s -> %s" % (d, "%s %s" % rc_cc[d], "%s %s" % rc_doc[d]) + print("\t%s %s -> %s" % (d, "%s %s" % rc_cc[d], "%s %s" % rc_doc[d])) # Search for stale documentation ... stale = [k for k in rc_doc if k not in rc_cc] if (len(stale) > 0): - print - print "Stale documentation:" + print() + print("Stale documentation:") for s in sorted(stale): - print "\t%s" % (s) + print("\t%s" % (s)) diff --git a/contrib/python/compare_records_config.py b/contrib/python/compare_records_config.py old mode 100644 new mode 100755 index acde26ae0e1..bd610a9b5d1 --- a/contrib/python/compare_records_config.py +++ b/contrib/python/compare_records_config.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file @@ -61,7 +61,7 @@ def compare_settings(old, new): # Skip predefined values continue if old[key] != new[key]: - print "%s %s -> %s" % (key, old[key], new[key]) + print("%s %s -> %s" % (key, old[key], new[key])) if __name__ == '__main__': diff --git a/tools/check-unused-dependencies b/tools/check-unused-dependencies index 431d1846df9..45ee5262882 100755 --- a/tools/check-unused-dependencies +++ b/tools/check-unused-dependencies @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with From f88173e670a3760618e35e519c233006b0d58dad Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Mon, 18 Nov 2019 18:56:51 +0800 Subject: [PATCH 166/718] Limit this check to Linux, where ldd always works (#6191) (cherry picked from commit 4520de9091fd3427146d2ab319622e0387f7a2cf) --- Makefile.am | 4 +++- configure.ac | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 889be94abc9..abcc9710f9d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -104,7 +104,9 @@ if BUILD_DOCS @cd doc && $(MAKE) $(AM_MAKEFLAGS) install-man endif -TESTS = tools/check-unused-dependencies +if OS_LINUX + TESTS = tools/check-unused-dependencies +endif rat: java -jar $(top_srcdir)/ci/apache-rat-0.13-SNAPSHOT.jar -E $(top_srcdir)/ci/rat-regex.txt -d $(top_srcdir) diff --git a/configure.ac b/configure.ac index ac20103d639..8a9bb9358f5 100644 --- a/configure.ac +++ b/configure.ac @@ -738,6 +738,7 @@ case $host_os in esac TS_ADDTO(AM_CPPFLAGS, [-D$host_os_def]) +AM_CONDITIONAL([OS_LINUX], [test "x$host_os_def" = "xlinux"]) dnl AM_PROG_AR is not always available, but it doesn't seem to be needed in older versions. ifdef([AM_PROG_AR], From eaa23ac8b0508f917ac2d432c8ce9c9006c8a929 Mon Sep 17 00:00:00 2001 From: Bryan Call Date: Mon, 18 Nov 2019 18:38:34 +0800 Subject: [PATCH 167/718] Fixed issue with macOS Catalina and pcre 8.43 enabling pcre-jit (#6189) (cherry picked from commit 093317c808b01304abf0a6b4aaf9c34791e3e08e) --- src/tscore/Regex.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tscore/Regex.cc b/src/tscore/Regex.cc index 33487d18349..9d93c8d5247 100644 --- a/src/tscore/Regex.cc +++ b/src/tscore/Regex.cc @@ -28,7 +28,7 @@ #include "tscore/ink_memory.h" #include "tscore/Regex.h" -#ifdef PCRE_CONFIG_JIT +#if defined(PCRE_CONFIG_JIT) && !defined(darwin) // issue with macOS Catalina and pcre 8.43 struct RegexThreadKey { RegexThreadKey() { ink_thread_key_create(&this->key, reinterpret_cast(&pcre_jit_stack_free)); } ink_thread_key key; @@ -82,13 +82,13 @@ Regex::compile(const char *pattern, const unsigned flags) return false; } -#ifdef PCRE_CONFIG_JIT +#if defined(PCRE_CONFIG_JIT) && !defined(darwin) // issue with macOS Catalina and pcre 8.43 study_opts |= PCRE_STUDY_JIT_COMPILE; #endif regex_extra = pcre_study(regex, study_opts, &error); -#ifdef PCRE_CONFIG_JIT +#if defined(PCRE_CONFIG_JIT) && !defined(darwin) // issue with macOS Catalina and pcre 8.43 if (regex_extra) { pcre_assign_jit_stack(regex_extra, &get_jit_stack, nullptr); } @@ -127,7 +127,7 @@ Regex::exec(std::string_view const &str, int *ovector, int ovecsize) Regex::~Regex() { if (regex_extra) { -#ifdef PCRE_CONFIG_JIT +#if defined(PCRE_CONFIG_JIT) && !defined(darwin) // issue with macOS Catalina and pcre 8.43 pcre_free_study(regex_extra); #else pcre_free(regex_extra); From 23592961db957861dfc91496753cedaef4ed5713 Mon Sep 17 00:00:00 2001 From: scw00 Date: Fri, 15 Nov 2019 14:46:51 +0800 Subject: [PATCH 168/718] Remove unimplement UDP function (cherry picked from commit e93da34cb76c4a4c6b826ea9c257e6ca0eba094a) --- iocore/net/P_UDPPacket.h | 69 ---------------------------------------- 1 file changed, 69 deletions(-) diff --git a/iocore/net/P_UDPPacket.h b/iocore/net/P_UDPPacket.h index d6473aa068f..a9f015b9af3 100644 --- a/iocore/net/P_UDPPacket.h +++ b/iocore/net/P_UDPPacket.h @@ -38,8 +38,6 @@ class UDPPacketInternal : public UDPPacket UDPPacketInternal(); ~UDPPacketInternal() override; - void append_block_internal(IOBufferBlock *block); - void free() override; SLINK(UDPPacketInternal, alink); // atomic link @@ -163,47 +161,6 @@ UDPPacket::getConnection() return static_cast(this)->conn; } -TS_INLINE UDPPacket * -new_UDPPacket(struct sockaddr const *to, ink_hrtime when, char *buf, int len) -{ - UDPPacketInternal *p = udpPacketAllocator.alloc(); - - p->in_the_priority_queue = 0; - p->in_heap = 0; - p->delivery_time = when; - ats_ip_copy(&p->to, to); - - if (buf) { - IOBufferBlock *body = new_IOBufferBlock(); - body->alloc(iobuffer_size_to_index(len)); - memcpy(body->end(), buf, len); - body->fill(len); - p->append_block(body); - } - - return p; -} - -TS_INLINE UDPPacket * -new_UDPPacket(struct sockaddr const *to, ink_hrtime when, IOBufferBlock *buf, int len) -{ - (void)len; - UDPPacketInternal *p = udpPacketAllocator.alloc(); - - p->in_the_priority_queue = 0; - p->in_heap = 0; - p->delivery_time = when; - ats_ip_copy(&p->to, to); - - while (buf) { - IOBufferBlock *body = buf->clone(); - p->append_block(body); - buf = buf->next.get(); - } - - return p; -} - TS_INLINE UDPPacket * new_UDPPacket(struct sockaddr const *to, ink_hrtime when, Ptr &buf) { @@ -218,32 +175,6 @@ new_UDPPacket(struct sockaddr const *to, ink_hrtime when, Ptr &bu return p; } -TS_INLINE UDPPacket * -new_UDPPacket(ink_hrtime when, Ptr buf) -{ - return new_UDPPacket(nullptr, when, buf); -} - -TS_INLINE UDPPacket * -new_incoming_UDPPacket(struct sockaddr *from, struct sockaddr *to, char *buf, int len) -{ - UDPPacketInternal *p = udpPacketAllocator.alloc(); - - p->in_the_priority_queue = 0; - p->in_heap = 0; - p->delivery_time = 0; - ats_ip_copy(&p->from, from); - ats_ip_copy(&p->to, to); - - IOBufferBlock *body = new_IOBufferBlock(); - body->alloc(iobuffer_size_to_index(len)); - memcpy(body->end(), buf, len); - body->fill(len); - p->append_block(body); - - return p; -} - TS_INLINE UDPPacket * new_incoming_UDPPacket(struct sockaddr *from, struct sockaddr *to, Ptr &block) { From d490b5a68ff9e9ee190cf93dde0b200c53b013ca Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Sun, 17 Nov 2019 13:49:03 +0800 Subject: [PATCH 169/718] Removes the ssn_close hook, it can never work (#6175) (cherry picked from commit a711c465c68243da290952512be704b715575d60) --- doc/admin-guide/plugins/tcpinfo.en.rst | 1 - .../admin-guide/plugins/tcpinfo.en.po | 4 ---- plugins/tcpinfo/tcpinfo.cc | 17 +++++------------ 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/doc/admin-guide/plugins/tcpinfo.en.rst b/doc/admin-guide/plugins/tcpinfo.en.rst index 28ca98758d7..6c806e8b9ee 100644 --- a/doc/admin-guide/plugins/tcpinfo.en.rst +++ b/doc/admin-guide/plugins/tcpinfo.en.rst @@ -45,7 +45,6 @@ The following options may be specified in :file:`plugin.config`: Event Name Triggered when ============== =============================================== send_resp_hdr The server begins sending an HTTP response. - ssn_close The TCP connection closes. ssn_start A new TCP connection is accepted. txn_close A HTTP transaction is completed. txn_start A HTTP transaction is initiated. diff --git a/doc/locale/ja/LC_MESSAGES/admin-guide/plugins/tcpinfo.en.po b/doc/locale/ja/LC_MESSAGES/admin-guide/plugins/tcpinfo.en.po index 0b180032772..88ae2c51245 100644 --- a/doc/locale/ja/LC_MESSAGES/admin-guide/plugins/tcpinfo.en.po +++ b/doc/locale/ja/LC_MESSAGES/admin-guide/plugins/tcpinfo.en.po @@ -232,10 +232,6 @@ msgstr "" msgid "snd_ssthresh" msgstr "" -#: ../../admin-guide/plugins/tcpinfo.en.rst:48 -msgid "ssn_close" -msgstr "" - #: ../../admin-guide/plugins/tcpinfo.en.rst:69 #: ../../admin-guide/plugins/tcpinfo.en.rst:81 msgid "timestamp" diff --git a/plugins/tcpinfo/tcpinfo.cc b/plugins/tcpinfo/tcpinfo.cc index cb8a82043ba..0c9d07fd250 100644 --- a/plugins/tcpinfo/tcpinfo.cc +++ b/plugins/tcpinfo/tcpinfo.cc @@ -54,7 +54,6 @@ #define TCPI_HOOK_SSN_START 0x01u #define TCPI_HOOK_TXN_START 0x02u #define TCPI_HOOK_SEND_RESPONSE 0x04u -#define TCPI_HOOK_SSN_CLOSE 0x08u #define TCPI_HOOK_TXN_CLOSE 0x10u // Log format headers. These are emitted once at the start of a log file. Note that we @@ -215,10 +214,6 @@ tcp_info_hook(TSCont contp, TSEvent event, void *edata) ssnp = TSHttpTxnSsnGet(txnp); event_name = "send_resp_hdr"; break; - case TS_EVENT_HTTP_SSN_CLOSE: - ssnp = static_cast(edata); - event_name = "ssn_close"; - break; default: return 0; } @@ -291,8 +286,11 @@ parse_hook_list(const char *hook_list) const struct hookmask { const char *name; unsigned mask; - } hooks[] = {{"ssn_start", TCPI_HOOK_SSN_START}, {"txn_start", TCPI_HOOK_TXN_START}, {"send_resp_hdr", TCPI_HOOK_SEND_RESPONSE}, - {"ssn_close", TCPI_HOOK_SSN_CLOSE}, {"txn_close", TCPI_HOOK_TXN_CLOSE}, {nullptr, 0u}}; + } hooks[] = {{"ssn_start", TCPI_HOOK_SSN_START}, + {"txn_start", TCPI_HOOK_TXN_START}, + {"send_resp_hdr", TCPI_HOOK_SEND_RESPONSE}, + {"txn_close", TCPI_HOOK_TXN_CLOSE}, + {nullptr, 0u}}; str = TSstrdup(hook_list); @@ -461,11 +459,6 @@ TSPluginInit(int argc, const char *argv[]) TSDebug("tcpinfo", "added hook to the sending of the headers"); } - if (hooks & TCPI_HOOK_SSN_CLOSE) { - TSHttpHookAdd(TS_HTTP_SSN_CLOSE_HOOK, cont); - TSDebug("tcpinfo", "added hook to the close of the TCP connection"); - } - if (hooks & TCPI_HOOK_TXN_CLOSE) { TSHttpHookAdd(TS_HTTP_TXN_CLOSE_HOOK, cont); TSDebug("tcpinfo", "added hook to the close of the transaction"); From 386d33ea11ef95ee33654dcf651a8c20c36bf7d2 Mon Sep 17 00:00:00 2001 From: Fei Deng Date: Fri, 20 Sep 2019 11:44:43 -0500 Subject: [PATCH 170/718] Add base64 encoding/decoding to encryption/decryption, and general code cleanup. (cherry picked from commit af2988b468f26d76fde118c6fb6d7b1e38b27ae4) --- .../ssl_session_reuse/Makefile.inc | 26 +-- .../ssl_session_reuse/example_config.config | 2 +- .../ssl_session_reuse/src/ats_ssl_plugin.cc | 10 +- .../ssl_session_reuse/src/common.cc | 182 +++++++++++++++ .../ssl_session_reuse/src/common.h | 55 +++++ .../ssl_session_reuse/src/config.cc | 6 +- .../ssl_session_reuse/src/message.h | 1 + .../ssl_session_reuse/src/openssl_utils.cc | 22 +- .../ssl_session_reuse/src/publish.cc | 89 ++++--- .../ssl_session_reuse/src/publisher.h | 1 + .../ssl_session_reuse/src/redis_endpoint.h | 1 + .../ssl_session_reuse/src/session_process.cc | 218 +++++++----------- .../ssl_session_reuse/src/session_process.h | 9 +- .../ssl_session_reuse/src/simple_pool.h | 3 +- .../ssl_session_reuse/src/ssl_init.cc | 38 +-- .../ssl_session_reuse/src/ssl_key_utils.cc | 141 ++++------- .../ssl_session_reuse/src/ssl_utils.h | 39 +--- .../ssl_session_reuse/src/subscriber.cc | 53 ++--- .../ssl_session_reuse/src/subscriber.h | 1 + 19 files changed, 501 insertions(+), 396 deletions(-) create mode 100644 plugins/experimental/ssl_session_reuse/src/common.cc diff --git a/plugins/experimental/ssl_session_reuse/Makefile.inc b/plugins/experimental/ssl_session_reuse/Makefile.inc index 5e5a95607c2..8984463e7b5 100644 --- a/plugins/experimental/ssl_session_reuse/Makefile.inc +++ b/plugins/experimental/ssl_session_reuse/Makefile.inc @@ -18,17 +18,17 @@ pkglib_LTLIBRARIES += experimental/ssl_session_reuse/ssl_session_reuse.la experimental_ssl_session_reuse_ssl_session_reuse_la_SOURCES = \ - experimental/ssl_session_reuse/src/openssl_utils.cc \ - experimental/ssl_session_reuse/src/session_process.cc \ - experimental/ssl_session_reuse/src/ssl_init.cc \ - experimental/ssl_session_reuse/src/config.cc \ - experimental/ssl_session_reuse/src/redis_endpoint.cc \ - experimental/ssl_session_reuse/src/simple_pool.cc \ - experimental/ssl_session_reuse/src/ssl_key_utils.cc \ - experimental/ssl_session_reuse/src/connection.cc \ - experimental/ssl_session_reuse/src/publish.cc \ - experimental/ssl_session_reuse/src/subscriber.cc \ - experimental/ssl_session_reuse/src/ats_ssl_plugin.cc - -experimental_ssl_session_reuse_ssl_session_reuse_la_LIBADD = @LIB_HIREDIS@ + experimental/ssl_session_reuse/src/ats_ssl_plugin.cc \ + experimental/ssl_session_reuse/src/common.cc \ + experimental/ssl_session_reuse/src/config.cc \ + experimental/ssl_session_reuse/src/connection.cc \ + experimental/ssl_session_reuse/src/openssl_utils.cc \ + experimental/ssl_session_reuse/src/publish.cc \ + experimental/ssl_session_reuse/src/redis_endpoint.cc \ + experimental/ssl_session_reuse/src/session_process.cc \ + experimental/ssl_session_reuse/src/simple_pool.cc \ + experimental/ssl_session_reuse/src/ssl_init.cc \ + experimental/ssl_session_reuse/src/ssl_key_utils.cc \ + experimental/ssl_session_reuse/src/subscriber.cc +experimental_ssl_session_reuse_ssl_session_reuse_la_LIBADD = @LIB_HIREDIS@ diff --git a/plugins/experimental/ssl_session_reuse/example_config.config b/plugins/experimental/ssl_session_reuse/example_config.config index e74ab0292ea..55d96a50716 100644 --- a/plugins/experimental/ssl_session_reuse/example_config.config +++ b/plugins/experimental/ssl_session_reuse/example_config.config @@ -21,7 +21,7 @@ redis.RedisEndpoints=host1.com:6379,host2.com:6379 # in milliseconds redis.RedisConnectTimeout=20000 # in milliseconds -resis.RedisRetryDelay=5000000 +redis.RedisRetryDelay=5000000 ## end generic redis config parameters ## start pub config settings diff --git a/plugins/experimental/ssl_session_reuse/src/ats_ssl_plugin.cc b/plugins/experimental/ssl_session_reuse/src/ats_ssl_plugin.cc index 81be94ae71b..64b03dfbdf3 100644 --- a/plugins/experimental/ssl_session_reuse/src/ats_ssl_plugin.cc +++ b/plugins/experimental/ssl_session_reuse/src/ats_ssl_plugin.cc @@ -23,16 +23,15 @@ */ #include +#include #include #include -#include +#include "common.h" #include "ssl_utils.h" PluginThreads plugin_threads; -int SSL_session_callback(TSCont contp, TSEvent event, void *edata); - static int shutdown_handler(TSCont contp, TSEvent event, void *edata) { @@ -49,7 +48,7 @@ TSPluginInit(int argc, const char *argv[]) info.plugin_name = (char *)("ats_session_reuse"); info.vendor_name = (char *)("ats"); - info.support_email = (char *)("ats-devel@oath.com"); + info.support_email = (char *)("ats-devel@verizonmedia.com"); TSLifecycleHookAdd(TS_LIFECYCLE_SHUTDOWN_HOOK, TSContCreate(shutdown_handler, nullptr)); @@ -63,10 +62,11 @@ TSPluginInit(int argc, const char *argv[]) } #endif if (argc < 2) { - TSError("Must specify config file"); + TSError("Must specify config file."); } else if (!init_ssl_params(argv[1])) { init_subscriber(); TSCont cont = TSContCreate(SSL_session_callback, nullptr); + TSDebug(PLUGIN, "TSPluginInit adding TS_SSL_SESSION_HOOK."); TSHttpHookAdd(TS_SSL_SESSION_HOOK, cont); } else { TSError("init_ssl_params failed."); diff --git a/plugins/experimental/ssl_session_reuse/src/common.cc b/plugins/experimental/ssl_session_reuse/src/common.cc new file mode 100644 index 00000000000..e552c5a2b0d --- /dev/null +++ b/plugins/experimental/ssl_session_reuse/src/common.cc @@ -0,0 +1,182 @@ +/** @file + + common.cc - Some common functions everyone needs + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + */ + +#include +#include +#include +#include +#include + +#include "common.h" + +const unsigned char salt[] = {115, 97, 108, 117, 0, 85, 137, 229}; + +std::string +hex_str(std::string str) +{ + std::string hex_str = ""; + for (char &c : str) { + std::stringstream stream; + stream << std::hex << std::setfill('0') << std::setw(2) << (0xFF & static_cast(c)); + hex_str += stream.str(); + } + return hex_str; +} + +int +encrypt_encode64(const unsigned char *key, int key_length, const unsigned char *in_data, int in_data_len, char *out_data, + size_t out_data_size, size_t *out_data_len) +{ + if (!key || !in_data || !out_data || !out_data_len) { + return -1; + } + + int cipher_block_size = 0; + unsigned char *encrypted = nullptr; + int encrypted_len = 0; + int encrypted_len_extra = 0; + int ret = -1; + + // Initialize context + EVP_CIPHER_CTX *context = EVP_CIPHER_CTX_new(); + unsigned char iv[EVP_MAX_IV_LENGTH]; + unsigned char gen_key[EVP_MAX_KEY_LENGTH]; + + // generate key and iv + if (EVP_BytesToKey(EVP_aes_256_cbc(), EVP_md5(), salt, key, key_length, 1, gen_key, iv) <= 0) { + TSDebug(PLUGIN, "Error generating key."); + } + + // Set context AES128 with the generated key and iv + if (1 != EVP_EncryptInit_ex(context, EVP_aes_256_cbc(), nullptr, gen_key, iv)) { + TSDebug(PLUGIN, "EVP_EncryptInit_ex failed."); + goto Cleanup; + } + + // https://www.openssl.org/docs/manmaster/man3/EVP_EncryptUpdate.html + // EVP_EncryptUpdate() needs (inl + cipher_block_size - 1) bytes. + // EVP_EncryptFinal_ex needs (inl + cipher_block_size) bytes. + cipher_block_size = EVP_CIPHER_CTX_block_size(context); + encrypted = new unsigned char[in_data_len + cipher_block_size * 2]; + if (1 != EVP_EncryptUpdate(context, encrypted, &encrypted_len, in_data, in_data_len)) { + TSDebug(PLUGIN, "EVP_EncryptUpdate failed."); + goto Cleanup; + } + + if (1 != EVP_EncryptFinal_ex(context, encrypted + encrypted_len, &encrypted_len_extra)) { + TSDebug(PLUGIN, "EVP_EncryptFinal_ex failed."); + goto Cleanup; + } + + // We must encode it to base64 here, since the encryption doesn't guarantee that there are no + // null bytes in the output. Which will cause a problem when sending it through redis since + // the redis command needs to be formatted to a C string. + if (TSBase64Encode(reinterpret_cast(encrypted), encrypted_len + encrypted_len_extra, out_data, out_data_size, + out_data_len) != 0) { + TSDebug(PLUGIN, "Base 64 encoding failed."); + goto Cleanup; + } + + TSDebug(PLUGIN, "Encrypted buffer of size %d to buffer of size %lu.", in_data_len, *out_data_len); + ret = 0; + +Cleanup: + + if (encrypted) { + delete[] encrypted; + } + + if (context) { + EVP_CIPHER_CTX_free(context); + } + + return ret; +} + +int +decrypt_decode64(const unsigned char *key, int key_length, const char *in_data, int in_data_len, unsigned char *out_data, + size_t out_data_size, size_t *out_data_len) +{ + if (!key || !in_data || !out_data || !out_data_len) { + return -1; + } + + size_t decoded_size = DECODED_LEN(in_data_len); + size_t decoded_len = 0; + unsigned char *decoded = new unsigned char[decoded_size]; + int decrypted_len = 0; + int decrypted_len_extra = 0; + int ret = -1; + + // Initialize context + EVP_CIPHER_CTX *context = EVP_CIPHER_CTX_new(); + unsigned char iv[EVP_MAX_IV_LENGTH]; + unsigned char gen_key[EVP_MAX_KEY_LENGTH]; + + // Decode base64 + std::memset(decoded, 0, decoded_size); + if (TSBase64Decode(in_data, in_data_len, decoded, decoded_size, &decoded_len) != 0) { + TSDebug(PLUGIN, "Base 64 decoding failed."); + goto Cleanup; + } + + // generate key and iv + if (EVP_BytesToKey(EVP_aes_256_cbc(), EVP_md5(), salt, key, key_length, 1, gen_key, iv) <= 0) { + TSDebug(PLUGIN, "Error generating key."); + } + // set context with the generated key and iv + if (1 != EVP_DecryptInit_ex(context, EVP_aes_256_cbc(), nullptr, gen_key, iv)) { + TSDebug(PLUGIN, "EVP_DecryptInit_ex failed."); + goto Cleanup; + } + + // https://www.openssl.org/docs/manmaster/man3/EVP_DecryptUpdate.html + // EVP_DecryptUpdate() and EVP_DecryptFinal_ex() have the exact same requirements as their encrypt counterparts. + if (1 != EVP_DecryptUpdate(context, out_data, &decrypted_len, decoded, decoded_len)) { + TSDebug(PLUGIN, "EVP_DecryptUpdate failed."); + goto Cleanup; + } + + if (1 != EVP_DecryptFinal_ex(context, out_data + decrypted_len, &decrypted_len_extra)) { + TSDebug(PLUGIN, "EVP_DecryptFinal_ex failed."); + goto Cleanup; + } + + *out_data_len = decrypted_len + decrypted_len_extra; + + TSDebug(PLUGIN, "Decrypted buffer of size %d to buffer of size %lu.", in_data_len, *out_data_len); + ret = 0; + +Cleanup: + + if (decoded) { + delete[] decoded; + } + + if (context) { + EVP_CIPHER_CTX_free(context); + } + + return ret; +} diff --git a/plugins/experimental/ssl_session_reuse/src/common.h b/plugins/experimental/ssl_session_reuse/src/common.h index 86b158e8027..bcec00b0669 100644 --- a/plugins/experimental/ssl_session_reuse/src/common.h +++ b/plugins/experimental/ssl_session_reuse/src/common.h @@ -23,6 +23,61 @@ */ #pragma once +#include +#include +#include +#include +#include +#include +#include +#include + #define PLUGIN "ssl_session_reuse" +// Base 64 encoding takes 4*(ceil(n/3)) bytes +#define ENCODED_LEN(len) (((int)ceil(1.34 * (len) + 5)) + 1) +#define DECODED_LEN(len) (((int)ceil(0.75 * (len))) + 1) +// 3DES encryption will take at most 8 extra bytes. Plus we base 64 encode the result +#define ENCRYPT_LEN(len) ((int)ceil(1.34 * ((len) + 8) + 5) + 1) +#define DECRYPT_LEN(len) ((int)ceil(1.34 * ((len) + 8) + 5) + 1) + +class PluginThreads +{ +public: + void + store(const pthread_t &th) + { + std::lock_guard lock(threads_mutex); + threads_queue.push_back(th); + } + + void + terminate() + { + std::lock_guard lock(threads_mutex); + for (pthread_t th : threads_queue) { + ::pthread_cancel(th); + } + while (!threads_queue.empty()) { + pthread_t th = threads_queue.front(); + ::pthread_join(th, nullptr); + threads_queue.pop_front(); + } + } + +private: + std::deque threads_queue; + std::mutex threads_mutex; +}; + +std::string hex_str(std::string str); + +int encrypt_encode64(const unsigned char *key, int key_length, const unsigned char *in_data, int in_data_len, char *out_data, + size_t out_data_size, size_t *out_data_len); + +int decrypt_decode64(const unsigned char *key, int key_length, const char *in_data, int in_data_len, unsigned char *out_data, + size_t out_data_size, size_t *out_data_len); + extern const unsigned char salt[]; + +extern PluginThreads plugin_threads; diff --git a/plugins/experimental/ssl_session_reuse/src/config.cc b/plugins/experimental/ssl_session_reuse/src/config.cc index 7f3927150d5..65f81a5604c 100644 --- a/plugins/experimental/ssl_session_reuse/src/config.cc +++ b/plugins/experimental/ssl_session_reuse/src/config.cc @@ -22,17 +22,17 @@ */ -#include -#include #include #include #include #include #include -#include "tscpp/util/TextView.h" +#include +#include #include "Config.h" #include "common.h" +#include "tscpp/util/TextView.h" Config::Config() { diff --git a/plugins/experimental/ssl_session_reuse/src/message.h b/plugins/experimental/ssl_session_reuse/src/message.h index 41e94c052eb..9196085b5ab 100644 --- a/plugins/experimental/ssl_session_reuse/src/message.h +++ b/plugins/experimental/ssl_session_reuse/src/message.h @@ -25,6 +25,7 @@ #include #include + #include "redis_endpoint.h" typedef struct message { diff --git a/plugins/experimental/ssl_session_reuse/src/openssl_utils.cc b/plugins/experimental/ssl_session_reuse/src/openssl_utils.cc index 2909e728591..0cff9cab0a5 100644 --- a/plugins/experimental/ssl_session_reuse/src/openssl_utils.cc +++ b/plugins/experimental/ssl_session_reuse/src/openssl_utils.cc @@ -22,16 +22,15 @@ */ -#include -#include -#include -#include #include -#include #include #include -#include +#include +#include #include +#include +#include +#include #include #include #include @@ -48,28 +47,28 @@ ssl_new_session(TSSslSessionID &sid) std::string encoded_id; int ret = encode_id(sid.bytes, sid.len, encoded_id); if (ret < 0) { - TSError("encoded id failed."); + TSError("Encoded id failed."); return 0; } int session_ret_len = SSL_SESSION_MAX_DER; char session_data[SSL_SESSION_MAX_DER]; if (!TSSslSessionGetBuffer(&sid, session_data, &session_ret_len)) { - TSError("session data is too large. %d", session_ret_len); + TSError("Session data is too large: %d", session_ret_len); return 0; } std::string encrypted_data; ret = encrypt_session(session_data, session_ret_len, (unsigned char *)get_key_ptr(), get_key_length(), encrypted_data); if (ret < 0) { - TSError("encrypt_session failed."); + TSError("Encrypt_session failed."); return 0; } std::string redis_channel = ssl_param.cluster_name + "." + encoded_id; ssl_param.pub->publish(redis_channel, encrypted_data); - TSDebug(PLUGIN, "create new session id: %s encoded: \"%s\" channel: %s", encoded_id.c_str(), encrypted_data.c_str(), + TSDebug(PLUGIN, "Create new session id: %s encoded: %s channel: %s", encoded_id.c_str(), encrypted_data.c_str(), redis_channel.c_str()); return 0; @@ -88,7 +87,7 @@ ssl_del_session(TSSslSessionID &sid) int ret = encode_id(sid.bytes, sid.len, encoded_id); if (!ret) { - TSDebug(PLUGIN, "session is deleted. id: \"%s\"", encoded_id.c_str()); + TSDebug(PLUGIN, "Session is deleted. id: %s", encoded_id.c_str()); } return 0; @@ -97,6 +96,7 @@ ssl_del_session(TSSslSessionID &sid) int SSL_session_callback(TSCont contp, TSEvent event, void *edata) { + TSDebug(PLUGIN, "SSL_session_callback event: %d", event); TSSslSessionID *sessionid = reinterpret_cast(edata); switch (event) { diff --git a/plugins/experimental/ssl_session_reuse/src/publish.cc b/plugins/experimental/ssl_session_reuse/src/publish.cc index 794260611e3..0877155be25 100644 --- a/plugins/experimental/ssl_session_reuse/src/publish.cc +++ b/plugins/experimental/ssl_session_reuse/src/publish.cc @@ -22,13 +22,14 @@ */ -#include -#include #include #include #include #include +#include +#include #include + #include "common.h" #include "publisher.h" #include "Config.h" @@ -49,14 +50,12 @@ RedisPublisher::start_worker_thread(void *arg) RedisPublisher::RedisPublisher(const std::string &conf) : m_redisEndpointsStr(cDefaultRedisEndpoint), - m_numWorkers(cPubNumWorkerThreads), m_redisConnectTimeout(cDefaultRedisConnectTimeout), m_redisConnectTries(cDefaultRedisConnectTries), m_redisPublishTries(cDefaultRedisPublishTries), m_redisRetryDelay(cDefaultRedisRetryDelay), m_maxQueuedMessages(cDefaultMaxQueuedMessages) - { if (Config::getSingleton().loadConfig(conf)) { Config::getSingleton().getValue("pubconfig", "PubNumWorkers", m_numWorkers); @@ -73,7 +72,7 @@ RedisPublisher::RedisPublisher(const std::string &conf) char redis_auth_key[MAX_REDIS_KEYSIZE]; if (!(get_redis_auth_key(redis_auth_key, MAX_REDIS_KEYSIZE))) { err = true; - TSError("RedisPublisher::RedisPublisher.Cannot get redis AUTH password."); + TSError("RedisPublisher::RedisPublisher: Cannot get redis AUTH password."); redis_passwd.clear(); } else { redis_passwd = redis_auth_key; @@ -82,25 +81,24 @@ RedisPublisher::RedisPublisher(const std::string &conf) addto_endpoint_vector(m_redisEndpoints, m_redisEndpointsStr); - TSDebug(PLUGIN, "RedisPublisher::RedisPublisher.NumWorkers= %d RedisConnectTimeout=%d", m_numWorkers, m_redisConnectTimeout); + TSDebug(PLUGIN, "RedisPublisher::RedisPublisher: NumWorkers: %d RedisConnectTimeout: %d", m_numWorkers, m_redisConnectTimeout); TSDebug(PLUGIN, - "RedisPublisher::RedisPublisher.RedisPublishTries= %d RedisConnectTries=%d RedisRetryDelay=%d MaxQueuedMessages=%d", + "RedisPublisher::RedisPublisher: RedisPublishTries: %d RedisConnectTries: %d RedisRetryDelay: %d MaxQueuedMessages: %d", m_redisPublishTries, m_redisConnectTries, m_redisRetryDelay, m_maxQueuedMessages); - TSDebug(PLUGIN, "RedisPublisher::RedisPublisher.Redis Publish endpoints are as follows:"); + TSDebug(PLUGIN, "RedisPublisher::RedisPublisher: Redis Publish endpoints are as follows:"); for (std::vector::iterator it = m_redisEndpoints.begin(); it != m_redisEndpoints.end(); ++it) { - // LOGDEBUG(PUB, *it); simple_pool *pool = simple_pool::create(it->m_hostname, it->m_port, m_poolRedisConnectTimeout); pools.push_back(pool); } - TSDebug(PLUGIN, "RedisPublisher::RedisPublisher.PoolRedisConnectTimeout= %d", m_poolRedisConnectTimeout); + TSDebug(PLUGIN, "RedisPublisher::RedisPublisher: PoolRedisConnectTimeout: %d", m_poolRedisConnectTimeout); ::sem_init(&m_workerSem, 0, 0); if (m_redisEndpoints.size() > m_numWorkers) { err = true; - TSError("RedisPublisher::RedisPublisher.Number of threads in the thread pool less than the number of redis endpoints"); + TSError("RedisPublisher::RedisPublisher: Number of threads in the thread pool less than the number of redis endpoints."); } if (!err) { @@ -120,7 +118,7 @@ ::redisContext * RedisPublisher::setup_connection(const RedisEndpoint &re) { ::pthread_t my_id = ::pthread_self(); - TSDebug(PLUGIN, "RedisPublisher::setup_connection.called by threadId: %d", static_cast(my_id)); + TSDebug(PLUGIN, "RedisPublisher::setup_connection: Called by threadId: %lx", my_id); RedisContextPtr my_context; struct ::timeval timeout; @@ -130,33 +128,32 @@ RedisPublisher::setup_connection(const RedisEndpoint &re) for (int i = 0; i < static_cast(m_redisConnectTries); ++i) { my_context.reset(::redisConnectWithTimeout(re.m_hostname.c_str(), re.m_port, timeout)); if (!my_context) { - TSError("RedisPublisher::setup_connection.connect to host: %s and port: %d fail count: %d threadId: %d", - re.m_hostname.c_str(), re.m_port, i + 1, static_cast(my_id)); + TSError("RedisPublisher::setup_connection: Connect to host: %s port: %d fail count: %d threadId: %lx", re.m_hostname.c_str(), + re.m_port, i + 1, my_id); } else if (my_context->err) { - TSError("RedisPublisher::setup_connection.connect to host: %s port: %d fail count: %d and threadId: %d", - re.m_hostname.c_str(), re.m_port, i + 1, static_cast(my_id)); + TSError("RedisPublisher::setup_connection: Connect to host: %s port: %d fail count: %d threadId: %lx", re.m_hostname.c_str(), + re.m_port, i + 1, my_id); my_context.reset(nullptr); } else { - TSDebug(PLUGIN, "RedisPublisher::setup_connection.threadId: %d successfully connected to the redis instance", - static_cast(my_id)); + TSDebug(PLUGIN, "RedisPublisher::setup_connection: threadId: %lx Successfully connected to the redis instance.", my_id); redisReply *reply = static_cast(redisCommand(my_context.get(), "AUTH %s", redis_passwd.c_str())); if (reply == nullptr) { - TSError("RedisPublisher::setup_connection. Cannot AUTH redis server, no reply."); + TSError("RedisPublisher::setup_connection: Cannot AUTH redis server, no reply."); my_context.reset(nullptr); } else if (reply->type == REDIS_REPLY_ERROR) { - TSError("RedisPublisher::setup_connection. Cannot AUTH redis server, error reply."); + TSError("RedisPublisher::setup_connection: Cannot AUTH redis server, error reply."); freeReplyObject(reply); my_context.reset(nullptr); } else { - TSDebug(PLUGIN, "RedisPublisher::setup_connection. Successfully AUTH redis server."); + TSDebug(PLUGIN, "RedisPublisher::setup_connection: Successfully AUTH redis server."); freeReplyObject(reply); } break; } - TSError("RedisPublisher::setup_connection.connect failed.will wait for: %d microseconds and try again.", m_redisRetryDelay); + TSError("RedisPublisher::setup_connection: Connect failed, will wait for: %d microseconds and try again.", m_redisRetryDelay); ::usleep(m_redisRetryDelay); } @@ -167,7 +164,7 @@ ::redisReply * RedisPublisher::send_publish(RedisContextPtr &ctx, const RedisEndpoint &re, const Message &msg) { ::pthread_t my_id = ::pthread_self(); - TSDebug(PLUGIN, "RedisPublisher::send_publish.called by threadId: %d", static_cast(my_id)); + TSDebug(PLUGIN, "RedisPublisher::send_publish: Called by threadId: %lx", my_id); ::redisReply *current_reply(nullptr); @@ -176,21 +173,20 @@ RedisPublisher::send_publish(RedisContextPtr &ctx, const RedisEndpoint &re, cons ctx.reset(setup_connection(re)); if (!ctx) { - TSError("RedisPublisher::send_publish.Unable to setup a connection to the redis server: %s:%d .ThreadId: %d Try: %d", - re.m_hostname.c_str(), re.m_port, static_cast(my_id), (i + 1)); + TSError("RedisPublisher::send_publish: Unable to setup a connection to the redis server: %s:%d threadId: %lx try: %d", + re.m_hostname.c_str(), re.m_port, my_id, (i + 1)); continue; } } current_reply = static_cast(::redisCommand(ctx.get(), "PUBLISH %s %s", msg.channel.c_str(), msg.data.c_str())); if (!current_reply) { - TSError("RedisPublisher::send_publish.Unable to get a reply from the server for publish.ThreadId: %d Try: %d", - static_cast(my_id), (i + 1)); + TSError("RedisPublisher::send_publish: Unable to get a reply from the server for publish. threadId: %lx try: %d", my_id, + (i + 1)); ctx.reset(nullptr); // Clean up previous attempt } else if (REDIS_REPLY_ERROR == current_reply->type) { - TSError("RedisPublisher::send_publish.Server responded with error for publish.ThreadId: %d Try: %d", static_cast(my_id), - i + 1); + TSError("RedisPublisher::send_publish: Server responded with error for publish. threadId: %lx try: %d", my_id, i + 1); clear_reply(current_reply); current_reply = nullptr; ctx.reset(nullptr); // Clean up previous attempt @@ -243,7 +239,8 @@ RedisPublisher::runWorker() continue; } - Message ¤t_message(m_messageQueue.front()); + // Can't do reference here, since we pop it off the queue, the reference will be invalid. + Message current_message(m_messageQueue.front()); if (!current_message.cleanup) { m_messageQueue.pop_front(); } @@ -252,7 +249,7 @@ RedisPublisher::runWorker() ::sem_wait(&m_workerSem); if (current_message.cleanup) { - TSDebug(PLUGIN, "RedisPublisher::runWorker.Thread id: %d received the cleanup message. exiting!", static_cast(my_id)); + TSDebug(PLUGIN, "RedisPublisher::runWorker: threadId: %lx received the cleanup message. Exiting!", my_id); break; } current_reply = send_publish(my_context, my_endpoint, current_message); @@ -284,8 +281,8 @@ RedisPublisher::runWorker() int RedisPublisher::publish(const std::string &channel, const std::string &data) { - TSDebug(PLUGIN, "RedisPublisher::publish.Publish request for channel: %s and message: \"%s\" received", channel.c_str(), - data.c_str()); + TSDebug(PLUGIN, "RedisPublisher::publish: Publish request for channel: %s and message: \"%s\" received.", channel.c_str(), + hex_str(data).c_str()); m_messageQueueMutex.lock(); @@ -302,7 +299,7 @@ RedisPublisher::publish(const std::string &channel, const std::string &data) int RedisPublisher::signal_cleanup() { - TSDebug(PLUGIN, "RedisPublisher::signal_cleanup.called"); + TSDebug(PLUGIN, "RedisPublisher::signal_cleanup: Called."); Message cleanup_message("", "", true); m_messageQueueMutex.lock(); @@ -316,7 +313,7 @@ RedisPublisher::signal_cleanup() RedisPublisher::~RedisPublisher() { - TSDebug(PLUGIN, "RedisPublisher::~RedisPublisher.called"); + TSDebug(PLUGIN, "RedisPublisher::~RedisPublisher: Called."); RedisPublisher::signal_cleanup(); ::sem_destroy(&m_workerSem); @@ -325,18 +322,18 @@ RedisPublisher::~RedisPublisher() std::string RedisPublisher::get_session(const std::string &channel) { - TSDebug(PLUGIN, "RedisPublisher::get_session. Called by threadId: %d", static_cast(pthread_self())); + TSDebug(PLUGIN, "RedisPublisher::get_session: Called by threadId: %lx", ::pthread_self()); std::string ret; uint32_t index = get_hash_index(channel); redisReply *reply = nullptr; - TSDebug(PLUGIN, "RedisPublisher::get_session. Start to try to get session."); + TSDebug(PLUGIN, "RedisPublisher::get_session: Start to try to get session."); for (uint32_t i = 0; i < m_redisEndpoints.size(); i++) { connection *conn = pools[index]->get(); if (conn) { reply = static_cast(redisCommand(conn->c_ptr(), "GET %s", channel.c_str())); if (reply && reply->type == REDIS_REPLY_STRING) { - TSDebug(PLUGIN, "RedisPublisher::get_session. Success to GET a value from redis server index: %d", index); + TSDebug(PLUGIN, "RedisPublisher::get_session: Success to GET a value from redis server index: %d", index); pools[index]->put(conn); ret = reply->str; clear_reply(reply); @@ -345,19 +342,19 @@ RedisPublisher::get_session(const std::string &channel) pools[index]->put(conn); clear_reply(reply); } - TSError("RedisPublisher::get_session. Fail to GET a value from this redis server index: %d", index); + TSError("RedisPublisher::get_session: Fail to GET a value from this redis server index: %d", index); index = get_next_index(index); - TSDebug(PLUGIN, "RedisPublisher::get_session. Will try the next redis server: %d", index); + TSDebug(PLUGIN, "RedisPublisher::get_session: Will try the next redis server: %d", index); } - TSError("RedisPublisher::get_session. Fail to GET a value from all redis servers!"); + TSError("RedisPublisher::get_session: Fail to GET a value from all redis servers!"); return ret; } redisReply * RedisPublisher::set_session(const Message &msg) { - TSDebug(PLUGIN, "RedisPublisher::set_session. Called by threadId: %d", static_cast(pthread_self())); + TSDebug(PLUGIN, "RedisPublisher::set_session: Called by threadId: %lx", ::pthread_self()); uint32_t index = get_hash_index(msg.channel); redisReply *reply = nullptr; for (uint32_t i = 0; i < m_redisEndpoints.size(); i++) { @@ -366,7 +363,7 @@ RedisPublisher::set_session(const Message &msg) if (conn) { reply = static_cast(redisCommand(conn->c_ptr(), "SET %s %s", msg.channel.c_str(), msg.data.c_str())); if (reply && reply->type == REDIS_REPLY_STATUS && strcasecmp(reply->str, "OK") == 0) { - TSDebug(PLUGIN, "RedisPublisher::set_session. Success to SET a value to redis server: %s:%d", + TSDebug(PLUGIN, "RedisPublisher::set_session: Success to SET a value to redis server: %s:%d", m_redisEndpoints[index].m_hostname.c_str(), m_redisEndpoints[index].m_port); pools[index]->put(conn); return reply; @@ -374,14 +371,14 @@ RedisPublisher::set_session(const Message &msg) pools[index]->put(conn); clear_reply(reply); } - TSError("RedisPublisher::set_session. Fail to SET a value to this redis server %s:%d", + TSError("RedisPublisher::set_session: Fail to SET a value to this redis server %s:%d", m_redisEndpoints[index].m_hostname.c_str(), m_redisEndpoints[index].m_port); index = get_next_index(index); - TSDebug(PLUGIN, "RedisPublisher::set_session. Will try the next redis server: %s:%d", + TSDebug(PLUGIN, "RedisPublisher::set_session: Will try the next redis server: %s:%d", m_redisEndpoints[index].m_hostname.c_str(), m_redisEndpoints[index].m_port); } - TSError("RedisPublisher::set_session. Fail to SET a value to all redis servers!"); + TSError("RedisPublisher::set_session: Fail to SET a value to all redis servers!"); return nullptr; } diff --git a/plugins/experimental/ssl_session_reuse/src/publisher.h b/plugins/experimental/ssl_session_reuse/src/publisher.h index 82fec012efd..a76880c9cbb 100644 --- a/plugins/experimental/ssl_session_reuse/src/publisher.h +++ b/plugins/experimental/ssl_session_reuse/src/publisher.h @@ -30,6 +30,7 @@ #include #include #include + #include "message.h" #include "globals.h" #include "redis_endpoint.h" diff --git a/plugins/experimental/ssl_session_reuse/src/redis_endpoint.h b/plugins/experimental/ssl_session_reuse/src/redis_endpoint.h index 2762d9b80fc..55ff737745a 100644 --- a/plugins/experimental/ssl_session_reuse/src/redis_endpoint.h +++ b/plugins/experimental/ssl_session_reuse/src/redis_endpoint.h @@ -25,6 +25,7 @@ #include #include + #include "globals.h" typedef struct redis_endpoint { diff --git a/plugins/experimental/ssl_session_reuse/src/session_process.cc b/plugins/experimental/ssl_session_reuse/src/session_process.cc index be6e029d222..1d843f4b451 100644 --- a/plugins/experimental/ssl_session_reuse/src/session_process.cc +++ b/plugins/experimental/ssl_session_reuse/src/session_process.cc @@ -32,88 +32,45 @@ #include "session_process.h" #include "ssl_utils.h" - #include "common.h" -const unsigned char salt[] = {115, 97, 108, 117, 0, 85, 137, 229}; +const uint64_t protocol_version = 2; int encrypt_session(const char *session_data, int32_t session_data_len, const unsigned char *key, int key_length, std::string &encrypted_data) { - size_t len_all = 0; - size_t offset = 0; - char *pBuf = nullptr; - - int encrypted_buffer_size = 0; - int encrypted_msg_len = 0; - unsigned char *encrypted_msg = nullptr; - int ret = 0; - - offset = 0; - len_all = sizeof(int64_t) + sizeof(int32_t) + session_data_len; + if (!key || !session_data) { + return -1; + } - pBuf = new char[len_all]; + int data_len = sizeof(int64_t) + sizeof(int32_t) + session_data_len; + unsigned char *data = new unsigned char[data_len]; + int offset = 0; + size_t encrypted_size = ENCODED_LEN(data_len + EVP_MAX_BLOCK_LENGTH * 2); + size_t encrypted_len = 0; + char *encrypted = new char[encrypted_size]; + int ret = 0; - // Put in a fixed experation time of 7 hours, just to have communication consistency with the original - // protocol - int64_t expire_time = time(nullptr) + 2 * 3600; - memcpy(pBuf + offset, &expire_time, sizeof(expire_time)); + // Transition the expiration time into a protocol version field. + // Keeping it unnecessarily long at 64 bits to have consistency with previous version + // Version 1, had a fixed expiration time of 2*3600 seconds + std::memcpy(data + offset, &protocol_version, sizeof(int64_t)); offset += sizeof(int64_t); - - memcpy(pBuf + offset, &session_data_len, sizeof(int32_t)); + std::memcpy(data + offset, &session_data_len, sizeof(int32_t)); offset += sizeof(session_data_len); - memcpy(pBuf + offset, session_data, session_data_len); - - // Initialize context - EVP_CIPHER_CTX *context = EVP_CIPHER_CTX_new(); - unsigned char iv[EVP_MAX_IV_LENGTH]; - unsigned char gen_key[EVP_MAX_KEY_LENGTH]; - - // generate key and iv - int generated_key_len = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_md5(), (unsigned char *)salt, key, key_length, 1, gen_key, iv); - if (generated_key_len <= 0) { - TSDebug(PLUGIN, "Error generating key"); - } - - // Set context AES128 with the generated key and iv - if (1 != EVP_EncryptInit_ex(context, EVP_aes_256_cbc(), nullptr, gen_key, iv)) { - TSDebug(PLUGIN, "Encryption of session data failed"); - ret = -1; - goto Cleanup; - } + std::memcpy(data + offset, session_data, session_data_len); - int elen; - encrypted_buffer_size = ENCRYPT_LEN(len_all); - encrypted_msg = new unsigned char[encrypted_buffer_size]; - if (1 != EVP_EncryptUpdate(context, encrypted_msg, &elen, reinterpret_cast(pBuf), len_all)) { - TSDebug(PLUGIN, "Encryption of session data failed"); - ret = -1; - goto Cleanup; - } - encrypted_msg_len = elen; - if (1 != EVP_EncryptFinal_ex(context, encrypted_msg + elen, &elen)) { - TSDebug(PLUGIN, "Encryption of session data failed"); - ret = -1; - goto Cleanup; + std::memset(encrypted, 0, encrypted_size); + ret = encrypt_encode64(key, key_length, data, data_len, encrypted, encrypted_size, &encrypted_len); + if (ret == 0) { + encrypted_data.assign(encrypted, encrypted_len); + } else { + TSDebug(PLUGIN, "Session data encryption failed."); } - encrypted_msg_len += elen; - TSDebug(PLUGIN, "Encrypted buffer of size %d to buffer of size %d\n", session_data_len, encrypted_msg_len); - - encrypted_data.assign(reinterpret_cast(encrypted_msg), encrypted_msg_len); - -Cleanup: - - if (pBuf) { - delete[] pBuf; - } - if (encrypted_msg) { - delete[] encrypted_msg; - } - if (context) { - EVP_CIPHER_CTX_free(context); - } + delete[] data; + delete[] encrypted; return ret; } @@ -128,85 +85,53 @@ int decrypt_session(const std::string &encrypted_data, const unsigned char *key, int key_length, char *session_data, int32_t &session_data_len) { - unsigned char *ssl_sess_ptr = nullptr; - int decrypted_buffer_size = 0; - int decrypted_msg_len = 0; - unsigned char *decrypted_msg = nullptr; - int ret = 0; - - // Initialize context - // Initialize context - EVP_CIPHER_CTX *context = EVP_CIPHER_CTX_new(); - unsigned char iv[EVP_MAX_IV_LENGTH]; - unsigned char gen_key[EVP_MAX_KEY_LENGTH]; - - // generate key and iv - int generated_key_len = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_md5(), (unsigned char *)salt, key, key_length, 1, gen_key, iv); - - if (generated_key_len <= 0) { - TSDebug(PLUGIN, "Error generating key"); - } - // set context with the generated key and iv - if (1 != EVP_DecryptInit_ex(context, EVP_aes_256_cbc(), nullptr, gen_key, iv)) { - TSDebug(PLUGIN, "Decryption of encrypted session data failed"); - goto Cleanup; + if (!key || !session_data) { + return -1; } - decrypted_buffer_size = DECRYPT_LEN(encrypted_data.length()); - decrypted_msg = reinterpret_cast(new char[decrypted_buffer_size + 1]); - decrypted_msg_len = decrypted_buffer_size + 1; - if (decrypted_msg == nullptr) { - TSError("decrypted_msg allocate failure"); - } - if (1 != EVP_DecryptUpdate(context, decrypted_msg, &decrypted_msg_len, (unsigned char *)encrypted_data.c_str(), - encrypted_data.length())) { - TSDebug(PLUGIN, "Decryption of encrypted session data failed"); - goto Cleanup; - } + unsigned char *ssl_sess_ptr = nullptr; + size_t decrypted_size = DECODED_LEN(encrypted_data.length()) + EVP_MAX_BLOCK_LENGTH * 2; + size_t decrypted_len = 0; + unsigned char *decrypted = new unsigned char[decrypted_size]; + int ret = -1; + size_t len_all = 0; - // Retrieve ssl_session - ssl_sess_ptr = decrypted_msg; + std::memset(decrypted, 0, decrypted_size); + decrypt_decode64(key, key_length, encrypted_data.c_str(), encrypted_data.length(), decrypted, decrypted_size, &decrypted_len); - // Skip the expiration time. Just a place holder to interact with the old version - ssl_sess_ptr += sizeof(int64_t); + // Retrieve ssl_session + ssl_sess_ptr = decrypted; + + // The first 64 bits are now the protocol version. Make sure it matches what we expect + if (protocol_version == *(reinterpret_cast(ssl_sess_ptr))) { + // Move beyond the protocol version + ssl_sess_ptr += sizeof(int64_t); + + // Length + ret = *(int32_t *)ssl_sess_ptr; + ssl_sess_ptr += sizeof(int32_t); + + len_all = ret + sizeof(int64_t) + sizeof(int32_t); + if (decrypted_len < len_all) { + TSDebug(PLUGIN, "Session data length mismatch, got %lu, should be %lu.", decrypted_len, len_all); + ret = -1; + goto Cleanup; + } - // Length - ret = *reinterpret_cast(ssl_sess_ptr); - ssl_sess_ptr += sizeof(int32_t); - TSDebug(PLUGIN, "Decrypted buffer of size %d from buffer of size %d\n", ret, session_data_len); - // If there is less data than the maxiumum buffer size, reduce accordingly - if (ret < session_data_len) { - session_data_len = ret; + // If there is less data than the maxiumum buffer size, reduce accordingly + if (ret < session_data_len) { + session_data_len = ret; + } + std::memcpy(session_data, ssl_sess_ptr, session_data_len); } - memcpy(session_data, ssl_sess_ptr, session_data_len); Cleanup: - if (decrypted_msg) { - delete[] decrypted_msg; - } - - if (context) { - EVP_CIPHER_CTX_free(context); - } + delete[] decrypted; return ret; } -int -decode_id(const std::string &encoded_id, char *decoded_data, int &decoded_data_len) -{ - size_t decode_len = 0; - memset(decoded_data, 0, decoded_data_len); - if (TSBase64Decode(static_cast(encoded_id.c_str()), encoded_id.length(), - reinterpret_cast(decoded_data), decoded_data_len, &decode_len) != 0) { - TSError("Base 64 decoding failed."); - return -1; - } - decoded_data_len = decode_len; - return 0; -} - int encode_id(const char *id, int idlen, std::string &encoded_data) { @@ -229,19 +154,36 @@ encode_id(const char *id, int idlen, std::string &encoded_data) return 0; } +int +decode_id(const std::string &encoded_id, char *decoded_data, int &decoded_data_len) +{ + size_t decode_len = 0; + memset(decoded_data, 0, decoded_data_len); + if (TSBase64Decode(static_cast(encoded_id.c_str()), encoded_id.length(), + reinterpret_cast(decoded_data), decoded_data_len, &decode_len) != 0) { + TSError("Base 64 decoding failed."); + return -1; + } + decoded_data_len = decode_len; + return 0; +} + int add_session(char *session_id, int session_id_len, const std::string &encrypted_session) { + std::string session(session_id, session_id_len); + TSDebug(PLUGIN, "add_session session_id: %s", hex_str(session).c_str()); char session_data[SSL_SESSION_MAX_DER]; int32_t session_data_len = SSL_SESSION_MAX_DER; - if (decrypt_session(encrypted_session, (unsigned char *)get_key_ptr(), get_key_length(), session_data, session_data_len) < 0) { - TSError("Failed to decrypt session %.*s", session_id_len, session_id); - return -1; + int ret = decrypt_session(encrypted_session, (unsigned char *)get_key_ptr(), get_key_length(), session_data, session_data_len); + if (ret < 0) { + TSError("Failed to decrypt session %.*s, error: %d", session_id_len, hex_str(session).c_str(), ret); + return ret; } const unsigned char *loc = reinterpret_cast(session_data); SSL_SESSION *sess = d2i_SSL_SESSION(nullptr, &loc, session_data_len); if (nullptr == sess) { - TSError("Failed to transform session buffer %.*s", session_id_len, session_id); + TSError("Failed to transform session buffer %.*s", session_id_len, hex_str(session).c_str()); } TSSslSessionID sid; memcpy(reinterpret_cast(sid.bytes), session_id, session_id_len); diff --git a/plugins/experimental/ssl_session_reuse/src/session_process.h b/plugins/experimental/ssl_session_reuse/src/session_process.h index a676db2b3ab..f987787f94d 100644 --- a/plugins/experimental/ssl_session_reuse/src/session_process.h +++ b/plugins/experimental/ssl_session_reuse/src/session_process.h @@ -26,14 +26,7 @@ #include #include -#define SSL_SESSION_MAX_DER 1024 * 10 - -// Base 64 encoding takes 4*(floor(n/3)) bytes -#define ENCODED_LEN(len) ((int)ceil(1.34 * len + 5)) + 1 -#define DECODED_LEN(len) ((int)ceil(0.75 * len)) + 1 -// 3DES encryption will take at most 8 extra bytes. Plus we base 64 encode the result -#define ENCRYPT_LEN(len) (int)ceil(1.34 * (len + 8) + 5) + 1 -#define DECRYPT_LEN(len) (int)ceil(1.34 * (len + 8) + 5) + 1 +#define SSL_SESSION_MAX_DER (1024 * 10) int encrypt_session(const char *session_data, int32_t session_data_len, const unsigned char *key, int key_length, std::string &encrypted_data); diff --git a/plugins/experimental/ssl_session_reuse/src/simple_pool.h b/plugins/experimental/ssl_session_reuse/src/simple_pool.h index 1931e8ac9c1..2977e356a38 100644 --- a/plugins/experimental/ssl_session_reuse/src/simple_pool.h +++ b/plugins/experimental/ssl_session_reuse/src/simple_pool.h @@ -23,10 +23,11 @@ */ #pragma once -#include "connection.h" #include #include +#include "connection.h" + /** * @brief Manages a pool of connections to a single Redis server */ diff --git a/plugins/experimental/ssl_session_reuse/src/ssl_init.cc b/plugins/experimental/ssl_session_reuse/src/ssl_init.cc index fd0c456a966..afc88fffeb0 100644 --- a/plugins/experimental/ssl_session_reuse/src/ssl_init.cc +++ b/plugins/experimental/ssl_session_reuse/src/ssl_init.cc @@ -24,13 +24,14 @@ #include #include -#include "ssl_utils.h" -#include "Config.h" -#include "common.h" #include #include #include +#include "ssl_utils.h" +#include "Config.h" +#include "common.h" + ssl_session_param ssl_param; // <- global containing all operational info std::string conf_file; @@ -60,26 +61,27 @@ init_ssl_params(const std::string &conf) if (ssl_param.key_update_interval > STEK_MAX_LIFETIME) { ssl_param.key_update_interval = STEK_MAX_LIFETIME; - TSDebug(PLUGIN, "KeyUpdateInterval too high, resetting session ticket key rotation to %d seconds", + TSDebug(PLUGIN, "KeyUpdateInterval too high, resetting session ticket key rotation to %d seconds.", ssl_param.key_update_interval); } - TSDebug(PLUGIN, "init_ssl_params: I %s been configured to initially be stek_master", + TSDebug(PLUGIN, "init_ssl_params: I %s been configured to initially be stek_master.", ((ssl_param.stek_master) ? "HAVE" : "HAVE NOT")); - TSDebug(PLUGIN, "init_ssl_params: Rotation interval (ssl_param.key_update_interval)set to %d\n", ssl_param.key_update_interval); + TSDebug(PLUGIN, "init_ssl_params: Rotation interval (ssl_param.key_update_interval) set to %d", ssl_param.key_update_interval); TSDebug(PLUGIN, "init_ssl_params: cluster_name set to %s", ssl_param.cluster_name.c_str()); - int ret = STEK_init_keys(); - if (ret < 0) { - TSError("init keys failure. %s", conf.c_str()); - return -1; - } - ssl_param.pub = new RedisPublisher(conf); if ((!ssl_param.pub) || (!ssl_param.pub->is_good())) { TSError("Construct RedisPublisher error."); return -1; } + + int ret = STEK_init_keys(); + if (ret < 0) { + TSError("STEK_init_keys failure: %s", conf.c_str()); + return -1; + } + return 0; } @@ -93,12 +95,13 @@ ssl_session_param::~ssl_session_param() } /* - Read the redis auth key from file ssl_param.redis_auth_key_file in retKeyBuff - + Read the redis auth key from file ssl_param.redis_auth_key_file in retKeyBuff + Return length of key read. */ int get_redis_auth_key(char *retKeyBuff, int buffSize) { + int retval = 0; // Get the Key if (ssl_param.redis_auth_key_file.length()) { int fd = open(ssl_param.redis_auth_key_file.c_str(), O_RDONLY); @@ -112,12 +115,13 @@ get_redis_auth_key(char *retKeyBuff, int buffSize) while (read_len > 1 && key_data[read_len - 1] == '\n') { --read_len; } + memset(retKeyBuff, 0, buffSize); strncpy(retKeyBuff, key_data.c_str(), read_len); + retval = key_data.length(); } } else { - TSError("can not get redis auth key"); - return 0; /* error */ + TSError("Can not get redis auth key."); } - return 1; /* ok */ + return retval; } diff --git a/plugins/experimental/ssl_session_reuse/src/ssl_key_utils.cc b/plugins/experimental/ssl_session_reuse/src/ssl_key_utils.cc index 7c53020450a..77ba4171724 100644 --- a/plugins/experimental/ssl_session_reuse/src/ssl_key_utils.cc +++ b/plugins/experimental/ssl_session_reuse/src/ssl_key_utils.cc @@ -22,15 +22,15 @@ */ -#include #include #include +#include +#include #include -#include #include +#include #include "ssl_utils.h" -#include #include "redis_auth.h" #include "stek.h" #include "common.h" @@ -157,103 +157,59 @@ STEK_CreateNew(struct ssl_ticket_key_t *returnSTEK, int globalkey, int entropyEn } static int -STEK_encrypt(struct ssl_ticket_key_t *stek, const char *key, int key_length, char *retEncrypted, int *retLength) +STEK_encrypt(struct ssl_ticket_key_t *stek, const char *key, int key_length, char *ret_encrypted, int *ret_len) { - EVP_CIPHER_CTX *context = EVP_CIPHER_CTX_new(); - unsigned char iv[EVP_MAX_IV_LENGTH]; - unsigned char gen_key[EVP_MAX_KEY_LENGTH]; - int retval = 0; - - /* Encrypted stek will be placed in caller allocated retEncrypted buffer */ - /* NOTE: retLength must initially contain the size of the retEncrypted buffer */ + /* Encrypted stek will be placed in caller allocated ret_encrypted buffer */ + /* NOTE: ret_len must initially contain the size of the ret_encrypted buffer */ /* return 1 on success, 0 on failure */ - - int stek_len = sizeof(struct ssl_ticket_key_t); - int stek_enc_len = 0; - - // generate key and iv - int generated_key_len = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_md5(), (const unsigned char *)salt, - reinterpret_cast(key), key_length, 1, gen_key, iv); - if (generated_key_len <= 0) { - TSDebug(PLUGIN, "Key setup for encryption of session ticket failed"); - goto cleanup; - } - - if (1 != EVP_EncryptInit_ex(context, EVP_aes_256_cbc(), nullptr, (const unsigned char *)gen_key, iv)) { - TSDebug(PLUGIN, "Encryption init of session ticket failed"); - goto cleanup; - } - - if (1 != EVP_EncryptUpdate(context, reinterpret_cast(retEncrypted), &stek_enc_len, - reinterpret_cast(stek), stek_len)) { - TSDebug(PLUGIN, "Encryption of session ticket failed"); - goto cleanup; - } - *retLength = stek_enc_len; - if (1 != EVP_EncryptFinal_ex(context, reinterpret_cast(retEncrypted) + stek_enc_len, &stek_enc_len)) { - TSDebug(PLUGIN, "Final encryption of session ticket failed"); - goto cleanup; + int stek_len = sizeof(struct ssl_ticket_key_t); + size_t encrypted_size = *ret_len; + size_t encrypted_len = 0; + + if (encrypt_encode64(reinterpret_cast(key), key_length, reinterpret_cast(stek), stek_len, + ret_encrypted, encrypted_size, &encrypted_len) == 0) { + *ret_len = encrypted_len; + return 1; // success + } else { + TSDebug(PLUGIN, "STEK encryption failed."); + return 0; } - *retLength += stek_enc_len; - - retval = 1; -cleanup: - EVP_CIPHER_CTX_free(context); - return retval; // success } static int -STEK_decrypt(const std::string &encrypted_data, const char *key, int key_length, struct ssl_ticket_key_t *retSTEK) +STEK_decrypt(const std::string &encrypted_data, const char *key, int key_length, struct ssl_ticket_key_t *ret_STEK) { - if (!retSTEK) { + if (!ret_STEK) { return 0; } - EVP_CIPHER_CTX *context = EVP_CIPHER_CTX_new(); - unsigned char iv[EVP_MAX_IV_LENGTH]; - unsigned char gen_key[EVP_MAX_KEY_LENGTH]; - unsigned char decryptBuff[4 * sizeof(struct ssl_ticket_key_t)] = { - 0, - }; - int decryptLength = sizeof(decryptBuff); - int retval = 0; - - TSDebug(PLUGIN, "STEK_decrypt(): requested to decrypt %d bytes", static_cast(encrypted_data.length())); + TSDebug(PLUGIN, "STEK_decrypt: requested to decrypt %lu bytes", encrypted_data.length()); - // generate key and iv - int generated_key_len = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_md5(), (const unsigned char *)salt, - reinterpret_cast(key), key_length, 1, gen_key, iv); - if (generated_key_len <= 0) { - TSDebug(PLUGIN, "Key setup for decryption of session ticket failed"); - goto cleanup; - } + int ret = 0; + size_t decrypted_size = DECODED_LEN(encrypted_data.length()) + EVP_MAX_BLOCK_LENGTH * 2; + size_t decrypted_len = 0; + unsigned char *decrypted = new unsigned char[decrypted_size]; - if (1 != EVP_DecryptInit_ex(context, EVP_aes_256_cbc(), nullptr, (const unsigned char *)gen_key, iv)) { - TSDebug(PLUGIN, "Encryption of session data failed"); - goto cleanup; - } + std::memset(decrypted, 0, decrypted_size); + decrypt_decode64(reinterpret_cast(key), key_length, encrypted_data.c_str(), encrypted_data.length(), + decrypted, decrypted_size, &decrypted_len); - if (1 != - EVP_DecryptUpdate(context, decryptBuff, &decryptLength, (unsigned char *)encrypted_data.c_str(), encrypted_data.length())) { - TSDebug(PLUGIN, "Decryption of encrypted ticket key failed"); - goto cleanup; + if (sizeof(struct ssl_ticket_key_t) != decrypted_len) { + TSError("STEK data length mismatch, got %lu, should be %lu", decrypted_len, sizeof(struct ssl_ticket_key_t)); + goto Cleanup; } - if (sizeof(struct ssl_ticket_key_t) != decryptLength) { - TSError("STEK received is unexpected size length=%d not %d", decryptLength, static_cast(sizeof(struct ssl_ticket_key_t))); - goto cleanup; - } + memcpy(ret_STEK, decrypted, sizeof(struct ssl_ticket_key_t)); + memset(decrypted, 0, decrypted_size); // warm fuzzies + ret = 1; - memcpy(retSTEK, decryptBuff, sizeof(struct ssl_ticket_key_t)); - memset(decryptBuff, 0, sizeof(decryptBuff)); // warm fuzzies - retval = 1; +Cleanup: -cleanup: - if (context) { - EVP_CIPHER_CTX_free(context); + if (decrypted) { + delete[] decrypted; } - return retval; /* ok, length of data in retSTEK will be sizeof(struct ssl_ticket_key_t) */ + return ret; /* ok, length of data in ret_STEK will be sizeof(struct ssl_ticket_key_t) */ } int @@ -272,7 +228,7 @@ STEK_Send_To_Network(struct ssl_ticket_key_t *stekToSend) // encrypt the STEK before sending encryptedDataLength = sizeof(encryptedData); if (!STEK_encrypt(stekToSend, get_key_ptr(), get_key_length(), encryptedData, &encryptedDataLength)) { - TSError("Can't encrypt STEK. Not sending"); + TSError("STEK_encrypt failed, not sending."); return 0; // failure } @@ -307,7 +263,7 @@ STEK_Update_Setter_Thread(void *arg) } stek_master_setter_running = 1; - TSDebug(PLUGIN, "Will now act as the STEK rotator for pod"); + TSDebug(PLUGIN, "Will now act as the STEK rotator for POD."); while (true) { // Create new STEK, set it for me, and then send it to the POD. @@ -316,7 +272,7 @@ STEK_Update_Setter_Thread(void *arg) // perhaps publishig isn't up yet. startProblem++; // count how many times we have this problem. sleepInterval = 60; // short sleep for error retry - TSError("Could not create/send new STEK for key rotation...try again in %d seconds", sleepInterval); + TSError("Could not create/send new STEK for key rotation... Try again in %d seconds.", sleepInterval); } else { // Everything good. will sleep for normal rotation time period and then repeat startProblem = 0; @@ -343,7 +299,7 @@ STEK_Update_Setter_Thread(void *arg) } // while(forever) done_master_setter: - TSDebug(PLUGIN, "Yielding STEK-Master rotation responsibility to another node in POD"); + TSDebug(PLUGIN, "Yielding STEK-Master rotation responsibility to another node in POD."); memset(&newKey, 0, sizeof(struct ssl_ticket_key_t)); stek_master_setter_running = 0; return nullptr; @@ -387,7 +343,7 @@ STEK_Update_Checker_Thread(void *arg) * that something is up with our STEK master, and nominate a new STEK master. */ - TSDebug(PLUGIN, "Starting Update Checker Thread"); + TSDebug(PLUGIN, "Starting STEK_Update_Checker_Thread."); lastChangeTime = lastWarningTime = time(¤tTime); // init to current to supress a startup warning. @@ -396,7 +352,7 @@ STEK_Update_Checker_Thread(void *arg) // Launch a request for the master to resend you the ticket key std::string redis_channel = ssl_param.cluster_name + "." + STEK_ID_RESEND; ssl_param.pub->publish(redis_channel, ""); // send it - TSDebug(PLUGIN, "Request for ticket"); + TSDebug(PLUGIN, "Request for ticket."); } time(¤tTime); time_t sleepUntil; @@ -427,13 +383,13 @@ STEK_Update_Checker_Thread(void *arg) /* Time to nominate a new stek master for pod key rotation... */ if (!stek_master_setter_running) { - TSDebug(PLUGIN, "Will nominate a new STEK-master thread now for pod key rotation"); + TSDebug(PLUGIN, "Will nominate a new STEK-master thread now for pod key rotation."); TSThreadCreate(STEK_Update_Setter_Thread, nullptr); } } - } // while(forever) + return nullptr; } // STEK_Update_Checker_Thread() int @@ -441,15 +397,16 @@ STEK_init_keys() { ssl_ticket_key_t initKey; - if (!get_redis_auth_key(channel_key, MAX_REDIS_KEYSIZE)) { - TSError("STEK_init_keys: could not get redis authentication key"); + channel_key_length = get_redis_auth_key(channel_key, MAX_REDIS_KEYSIZE); + if (channel_key_length <= 0) { + TSError("STEK_init_keys: Could not get redis authentication key."); return -1; } // Initialize starter Session Ticket Encryption Key // Will sync up with master later if (!STEK_CreateNew(&initKey, 0, 0 /*fast start*/)) { - TSError("Cant init STEK"); + TSError("Cant init STEK."); return -1; } memcpy(&ssl_param.ticket_keys[0], &initKey, sizeof(struct ssl_ticket_key_t)); diff --git a/plugins/experimental/ssl_session_reuse/src/ssl_utils.h b/plugins/experimental/ssl_session_reuse/src/ssl_utils.h index 262728cb758..adfc39c80d7 100644 --- a/plugins/experimental/ssl_session_reuse/src/ssl_utils.h +++ b/plugins/experimental/ssl_session_reuse/src/ssl_utils.h @@ -23,15 +23,15 @@ */ #pragma once -#include #include +#include +#include +#include +#include #include -#include -#include #include "publisher.h" #include "subscriber.h" - #include "stek.h" struct ssl_session_param { @@ -47,35 +47,6 @@ struct ssl_session_param { ~ssl_session_param(); }; -class PluginThreads -{ -public: - void - store(const pthread_t &th) - { - std::lock_guard lock(threads_mutex); - threads_queue.push_back(th); - } - - void - terminate() - { - std::lock_guard lock(threads_mutex); - for (pthread_t th : threads_queue) { - ::pthread_cancel(th); - } - while (!threads_queue.empty()) { - pthread_t th = threads_queue.front(); - ::pthread_join(th, nullptr); - threads_queue.pop_front(); - } - } - -private: - std::deque threads_queue; - std::mutex threads_mutex; -}; - int STEK_init_keys(); const char *get_key_ptr(); @@ -97,5 +68,3 @@ int init_subscriber(); int SSL_session_callback(TSCont contp, TSEvent event, void *edata); extern ssl_session_param ssl_param; // almost everything one needs is stored in here - -extern PluginThreads plugin_threads; diff --git a/plugins/experimental/ssl_session_reuse/src/subscriber.cc b/plugins/experimental/ssl_session_reuse/src/subscriber.cc index 7dfc5560350..9d01f220a80 100644 --- a/plugins/experimental/ssl_session_reuse/src/subscriber.cc +++ b/plugins/experimental/ssl_session_reuse/src/subscriber.cc @@ -22,13 +22,13 @@ */ +#include #include -#include #include #include -#include -#include "common.h" +#include +#include "common.h" #include "subscriber.h" #include "Config.h" #include "redis_auth.h" @@ -67,7 +67,7 @@ RedisSubscriber::RedisSubscriber(const std::string &conf) char redis_auth_key[MAX_REDIS_KEYSIZE]; if (!(get_redis_auth_key(redis_auth_key, MAX_REDIS_KEYSIZE))) { err = true; - TSError("RedisPublisher::RedisPublisher.Cannot get redis AUTH password."); + TSError("RedisPublisher::RedisPublisher: Cannot get redis AUTH password."); redis_passwd.clear(); } else { redis_passwd = redis_auth_key; @@ -76,7 +76,7 @@ RedisSubscriber::RedisSubscriber(const std::string &conf) m_channel_prefix = m_channel.substr(0, m_channel.find('*')); - TSDebug(PLUGIN, "RedisSubscriber::RedisSubscriber.SubscriberChannel= %s SubscriberChannelPrefix= %s", m_channel.c_str(), + TSDebug(PLUGIN, "RedisSubscriber::RedisSubscriber: SubscriberChannel: %s SubscriberChannelPrefix: %s", m_channel.c_str(), m_channel_prefix.c_str()); addto_endpoint_vector(m_redisEndpoints, redisEndpointsStr); @@ -103,7 +103,7 @@ RedisSubscriber::get_endpoint_index() ::redisContext * RedisSubscriber::setup_connection(int index) { - TSDebug(PLUGIN, "RedisSubscriber::setup_connection.called for host= %s and port= %d", m_redisEndpoints[index].m_hostname.c_str(), + TSDebug(PLUGIN, "RedisSubscriber::setup_connection: Called for host: %s port: %d", m_redisEndpoints[index].m_hostname.c_str(), m_redisEndpoints[index].m_port); ::redisContext *my_context(nullptr); @@ -115,31 +115,31 @@ RedisSubscriber::setup_connection(int index) my_context = ::redisConnectWithTimeout(m_redisEndpoints[index].m_hostname.c_str(), m_redisEndpoints[index].m_port, timeout_connect); if (!my_context) { - TSError("RedisSubscriber::setup_connection.connect to host: %s and port: %d failed", - m_redisEndpoints[index].m_hostname.c_str(), m_redisEndpoints[index].m_port); + TSError("RedisSubscriber::setup_connection: Connect to host: %s port: %d failed.", m_redisEndpoints[index].m_hostname.c_str(), + m_redisEndpoints[index].m_port); } else if (my_context->err) { - TSError("RedisSubscriber::setup_connection.connect to host: %s and port: %d failed.", - m_redisEndpoints[index].m_hostname.c_str(), m_redisEndpoints[index].m_port); + TSError("RedisSubscriber::setup_connection: Connect to host: %s port: %d failed.", m_redisEndpoints[index].m_hostname.c_str(), + m_redisEndpoints[index].m_port); } else { - TSDebug(PLUGIN, "RedisSubscriber::setup_connection: successfully connected to the redis host: %s on port: %d", + TSDebug(PLUGIN, "RedisSubscriber::setup_connection: Successfully connected to the redis host: %s port: %d", m_redisEndpoints[index].m_hostname.c_str(), m_redisEndpoints[index].m_port); redisReply *reply = static_cast(redisCommand(my_context, "AUTH %s", redis_passwd.c_str())); if (reply == nullptr) { - TSError("RedisSubscriber::setup_connection Cannot AUTH redis server, no reply."); + TSError("RedisSubscriber::setup_connection: Cannot AUTH redis server, no reply."); } else if (reply->type == REDIS_REPLY_ERROR) { - TSError("RedisSubscriber::setup_connection Cannot AUTH redis server, error reply."); + TSError("RedisSubscriber::setup_connection: Cannot AUTH redis server, error reply."); freeReplyObject(reply); } else { - TSDebug(PLUGIN, "RedisSubscriber::setup_connection. Successfully AUTH redis server."); + TSDebug(PLUGIN, "RedisSubscriber::setup_connection: Successfully AUTH redis server."); freeReplyObject(reply); } break; } - TSError("RedisSubscriber::setup_connection.will wait for: %d microseconds and try again.", m_redisRetryDelay); + TSError("RedisSubscriber::setup_connection: Will wait for: %d microseconds and try again.", m_redisRetryDelay); ::usleep(m_redisRetryDelay); } @@ -150,7 +150,7 @@ RedisSubscriber::setup_connection(int index) void RedisSubscriber::run() { - TSDebug(PLUGIN, "RedisSubscriber::runMaster.called"); + TSDebug(PLUGIN, "RedisSubscriber::runMaster: Called."); int my_endpoint_index = get_endpoint_index(); ::redisContext *my_context(setup_connection(my_endpoint_index)); ::redisReply *current_reply(nullptr); @@ -161,16 +161,16 @@ RedisSubscriber::run() my_context = setup_connection(my_endpoint_index); } - TSDebug(PLUGIN, "RedisSubscriber::runMaster.Issuing command: \"PSUBSCRIBE %s\"", m_channel.c_str()); + TSDebug(PLUGIN, "RedisSubscriber::runMaster: Issuing command: PSUBSCRIBE %s", m_channel.c_str()); current_reply = static_cast(::redisCommand(my_context, "PSUBSCRIBE %s", m_channel.c_str())); if (!current_reply || (REDIS_REPLY_ERROR == current_reply->type)) { - TSError("RedisSubscriber::runMaster.subscribe to redis server on channel: %s failed.", m_channel.c_str()); + TSError("RedisSubscriber::runMaster: Subscribe to redis server on channel: %s failed.", m_channel.c_str()); ::usleep(1000 * 1000); continue; } else { - TSDebug(PLUGIN, "RedisSubscriber::runMaster.Successfully subscribed to channel: \"%s\"", m_channel.c_str()); - TSDebug(PLUGIN, "RedisSubscriber::runMaster.Waiting for messages to appear on the channel!"); + TSDebug(PLUGIN, "RedisSubscriber::runMaster: Successfully subscribed to channel: %s", m_channel.c_str()); + TSDebug(PLUGIN, "RedisSubscriber::runMaster: Waiting for messages to appear on the channel!"); ::freeReplyObject(current_reply); } @@ -179,7 +179,7 @@ RedisSubscriber::run() // Process Message std::string channel(current_reply->element[2]->str, current_reply->element[2]->len); std::string data(current_reply->element[3]->str, current_reply->element[3]->len); - TSDebug(PLUGIN, "Redis request channel=%s message=%s", channel.c_str(), data.c_str()); + TSDebug(PLUGIN, "RedisSubscriber::runMaster: Redis request channel: %s message: %s", channel.c_str(), hex_str(data).c_str()); std::string key = ""; // Strip the channel name to get the key @@ -193,28 +193,29 @@ RedisSubscriber::run() // Requesting last ticket to be resent } else if (strncmp(key.c_str(), STEK_ID_RESEND, strlen(STEK_ID_RESEND)) == 0) { if (isSTEKMaster()) { - TSDebug(PLUGIN, "RedisSubscriber Resend ticket"); + TSDebug(PLUGIN, "RedisSubscriber::runMaster: Resend ticket."); STEK_Send_To_Network(ssl_param.ticket_keys); } } else { // Otherwise this is a new session. Let ATS core know about it char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH * 2]; int session_id_len = sizeof(session_id); if (decode_id(key, session_id, session_id_len) == 0) { // Decrypt the data - TSDebug(PLUGIN, "Add session encoded_id=%s decoded_id=%.*s %d", key.c_str(), session_id_len, session_id, session_id_len); + TSDebug(PLUGIN, "RedisSubscriber::runMaster: Add session encoded_id: %s decoded_id: %.*s %d", key.c_str(), session_id_len, + hex_str(std::string(session_id, session_id_len)).c_str(), session_id_len); add_session(session_id, session_id_len, data); } else { - TSDebug(PLUGIN, "failed to decode key=%s", key.c_str()); + TSDebug(PLUGIN, "RedisSubscriber::runMaster: Failed to decode key: %s", key.c_str()); } } ::freeReplyObject(current_reply); - TSDebug(PLUGIN, "RedisSubscriber::runMaster.Got message: %s on channel: %s", data.c_str(), channel.c_str()); + TSDebug(PLUGIN, "RedisSubscriber::runMaster: Got message: %s channel: %s", hex_str(data).c_str(), channel.c_str()); } } } RedisSubscriber::~RedisSubscriber() { - TSDebug(PLUGIN, "RedisSubscriber::~RedisSubscriber.called for endpoint"); + TSDebug(PLUGIN, "RedisSubscriber::~RedisSubscriber: Called for endpoint."); } diff --git a/plugins/experimental/ssl_session_reuse/src/subscriber.h b/plugins/experimental/ssl_session_reuse/src/subscriber.h index 19c18127b6c..9e0ae854dfe 100644 --- a/plugins/experimental/ssl_session_reuse/src/subscriber.h +++ b/plugins/experimental/ssl_session_reuse/src/subscriber.h @@ -25,6 +25,7 @@ #include #include + #include "message.h" #include "globals.h" #include "redis_endpoint.h" From 1f029cd57e31e3ca95183957d75ef161efb9045c Mon Sep 17 00:00:00 2001 From: Bryan Call Date: Mon, 18 Nov 2019 16:50:02 +0800 Subject: [PATCH 171/718] Fix ssl_session_reuse to compile on macOS and FreeBSD (cherry picked from commit 7dd4a6f60743147d9d46c4f8d2ecc2e99034221e) --- .../ssl_session_reuse/src/config.cc | 4 +-- .../ssl_session_reuse/src/publish.cc | 30 ++++++++++--------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/plugins/experimental/ssl_session_reuse/src/config.cc b/plugins/experimental/ssl_session_reuse/src/config.cc index 65f81a5604c..6501048b2c3 100644 --- a/plugins/experimental/ssl_session_reuse/src/config.cc +++ b/plugins/experimental/ssl_session_reuse/src/config.cc @@ -101,9 +101,9 @@ Config::setLastConfigChange() memset(&s, 0, sizeof(s)); stat(m_filename.c_str(), &s); - m_lastmtime = s.st_mtim.tv_sec; + m_lastmtime = s.st_mtime; - if (s.st_mtim.tv_sec > oldLastmtime) { + if (s.st_mtime > oldLastmtime) { return true; } return false; diff --git a/plugins/experimental/ssl_session_reuse/src/publish.cc b/plugins/experimental/ssl_session_reuse/src/publish.cc index 0877155be25..98bab37d439 100644 --- a/plugins/experimental/ssl_session_reuse/src/publish.cc +++ b/plugins/experimental/ssl_session_reuse/src/publish.cc @@ -117,8 +117,8 @@ RedisPublisher::is_good() ::redisContext * RedisPublisher::setup_connection(const RedisEndpoint &re) { - ::pthread_t my_id = ::pthread_self(); - TSDebug(PLUGIN, "RedisPublisher::setup_connection: Called by threadId: %lx", my_id); + auto my_id = (unsigned long long)::pthread_self(); + TSDebug(PLUGIN, "RedisPublisher::setup_connection: Called by threadId: %llx", my_id); RedisContextPtr my_context; struct ::timeval timeout; @@ -128,14 +128,14 @@ RedisPublisher::setup_connection(const RedisEndpoint &re) for (int i = 0; i < static_cast(m_redisConnectTries); ++i) { my_context.reset(::redisConnectWithTimeout(re.m_hostname.c_str(), re.m_port, timeout)); if (!my_context) { - TSError("RedisPublisher::setup_connection: Connect to host: %s port: %d fail count: %d threadId: %lx", re.m_hostname.c_str(), + TSError("RedisPublisher::setup_connection: Connect to host: %s port: %d fail count: %d threadId: %llx", re.m_hostname.c_str(), re.m_port, i + 1, my_id); } else if (my_context->err) { - TSError("RedisPublisher::setup_connection: Connect to host: %s port: %d fail count: %d threadId: %lx", re.m_hostname.c_str(), + TSError("RedisPublisher::setup_connection: Connect to host: %s port: %d fail count: %d threadId: %llx", re.m_hostname.c_str(), re.m_port, i + 1, my_id); my_context.reset(nullptr); } else { - TSDebug(PLUGIN, "RedisPublisher::setup_connection: threadId: %lx Successfully connected to the redis instance.", my_id); + TSDebug(PLUGIN, "RedisPublisher::setup_connection: threadId: %llx Successfully connected to the redis instance.", my_id); redisReply *reply = static_cast(redisCommand(my_context.get(), "AUTH %s", redis_passwd.c_str())); @@ -163,8 +163,8 @@ RedisPublisher::setup_connection(const RedisEndpoint &re) ::redisReply * RedisPublisher::send_publish(RedisContextPtr &ctx, const RedisEndpoint &re, const Message &msg) { - ::pthread_t my_id = ::pthread_self(); - TSDebug(PLUGIN, "RedisPublisher::send_publish: Called by threadId: %lx", my_id); + auto my_id = (unsigned long long)::pthread_self(); + TSDebug(PLUGIN, "RedisPublisher::send_publish: Called by threadId: %llx", my_id); ::redisReply *current_reply(nullptr); @@ -173,7 +173,7 @@ RedisPublisher::send_publish(RedisContextPtr &ctx, const RedisEndpoint &re, cons ctx.reset(setup_connection(re)); if (!ctx) { - TSError("RedisPublisher::send_publish: Unable to setup a connection to the redis server: %s:%d threadId: %lx try: %d", + TSError("RedisPublisher::send_publish: Unable to setup a connection to the redis server: %s:%d threadId: %llx try: %d", re.m_hostname.c_str(), re.m_port, my_id, (i + 1)); continue; } @@ -181,12 +181,12 @@ RedisPublisher::send_publish(RedisContextPtr &ctx, const RedisEndpoint &re, cons current_reply = static_cast(::redisCommand(ctx.get(), "PUBLISH %s %s", msg.channel.c_str(), msg.data.c_str())); if (!current_reply) { - TSError("RedisPublisher::send_publish: Unable to get a reply from the server for publish. threadId: %lx try: %d", my_id, + TSError("RedisPublisher::send_publish: Unable to get a reply from the server for publish. threadId: %llx try: %d", my_id, (i + 1)); ctx.reset(nullptr); // Clean up previous attempt } else if (REDIS_REPLY_ERROR == current_reply->type) { - TSError("RedisPublisher::send_publish: Server responded with error for publish. threadId: %lx try: %d", my_id, i + 1); + TSError("RedisPublisher::send_publish: Server responded with error for publish. threadId: %llx try: %d", my_id, i + 1); clear_reply(current_reply); current_reply = nullptr; ctx.reset(nullptr); // Clean up previous attempt @@ -219,7 +219,7 @@ RedisPublisher::runWorker() } m_endpointIndexMutex.unlock(); - ::pthread_t my_id = ::pthread_self(); + auto my_id = (unsigned long long)::pthread_self(); RedisContextPtr my_context; ::redisReply *current_reply(nullptr); @@ -249,7 +249,7 @@ RedisPublisher::runWorker() ::sem_wait(&m_workerSem); if (current_message.cleanup) { - TSDebug(PLUGIN, "RedisPublisher::runWorker: threadId: %lx received the cleanup message. Exiting!", my_id); + TSDebug(PLUGIN, "RedisPublisher::runWorker: threadId: %llx received the cleanup message. Exiting!", my_id); break; } current_reply = send_publish(my_context, my_endpoint, current_message); @@ -322,7 +322,8 @@ RedisPublisher::~RedisPublisher() std::string RedisPublisher::get_session(const std::string &channel) { - TSDebug(PLUGIN, "RedisPublisher::get_session: Called by threadId: %lx", ::pthread_self()); + auto my_id = (unsigned long long)::pthread_self(); + TSDebug(PLUGIN, "RedisPublisher::get_session: Called by threadId: %llx", my_id); std::string ret; uint32_t index = get_hash_index(channel); redisReply *reply = nullptr; @@ -354,7 +355,8 @@ RedisPublisher::get_session(const std::string &channel) redisReply * RedisPublisher::set_session(const Message &msg) { - TSDebug(PLUGIN, "RedisPublisher::set_session: Called by threadId: %lx", ::pthread_self()); + auto my_id = (unsigned long long)::pthread_self(); + TSDebug(PLUGIN, "RedisPublisher::set_session: Called by threadId: %llx", my_id); uint32_t index = get_hash_index(msg.channel); redisReply *reply = nullptr; for (uint32_t i = 0; i < m_redisEndpoints.size(); i++) { From 226d2544643a9b44d22d997ce0fb725ed245049e Mon Sep 17 00:00:00 2001 From: "Alan M. Carroll" Date: Sat, 16 Nov 2019 15:05:58 -0600 Subject: [PATCH 172/718] remap_stats: Fix BufferWriter usage error. (cherry picked from commit fa47dfc118378e359a506e4f60f911673ed7e05b) --- plugins/experimental/remap_stats/remap_stats.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/experimental/remap_stats/remap_stats.cc b/plugins/experimental/remap_stats/remap_stats.cc index 43df970dd5d..6b4751fa734 100644 --- a/plugins/experimental/remap_stats/remap_stats.cc +++ b/plugins/experimental/remap_stats/remap_stats.cc @@ -143,9 +143,9 @@ handle_post_remap(TSCont cont, TSEvent event ATS_UNUSED, void *edata) } static void -create_stat_name(ts::LocalBufferWriter &stat_name, std::string_view h, std::string_view b) +create_stat_name(ts::FixedBufferWriter &stat_name, std::string_view h, std::string_view b) { - stat_name.reset().reduce(1); + stat_name.reset().clip(1); stat_name.print("plugin.{}.{}.{}", PLUGIN_NAME, h, b); stat_name.extend(1).write('\0'); } From ec47b2bcd4ba650406332b1dfa629da6a67f4367 Mon Sep 17 00:00:00 2001 From: Leif Hedstrom Date: Tue, 19 Nov 2019 11:00:11 +0800 Subject: [PATCH 173/718] Upgrade Catch.hpp to v2.11 (#6185) (cherry picked from commit 95601e9be8367cddce169bf9056da68b2d14517d) --- tests/include/catch.hpp | 10300 +++++++++++++++++++++++++++----------- 1 file changed, 7420 insertions(+), 2880 deletions(-) diff --git a/tests/include/catch.hpp b/tests/include/catch.hpp index bc24a4298f1..b4eccfc1483 100644 --- a/tests/include/catch.hpp +++ b/tests/include/catch.hpp @@ -1,9 +1,9 @@ /* - * Catch v2.2.2 - * Generated: 2018-04-06 12:05:03.186665 + * Catch v2.11.0 + * Generated: 2019-11-15 15:01:56.628356 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2018 Two Blue Cubes Ltd. All rights reserved. + * Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved. * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -14,8 +14,8 @@ #define CATCH_VERSION_MAJOR 2 -#define CATCH_VERSION_MINOR 2 -#define CATCH_VERSION_PATCH 2 +#define CATCH_VERSION_MINOR 11 +#define CATCH_VERSION_PATCH 0 #ifdef __clang__ # pragma clang system_header @@ -30,14 +30,17 @@ # pragma warning(push) # pragma warning(disable: 161 1682) # else // __ICC -# pragma clang diagnostic ignored "-Wunused-variable" # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wpadded" # pragma clang diagnostic ignored "-Wswitch-enum" # pragma clang diagnostic ignored "-Wcovered-switch-default" # endif #elif defined __GNUC__ -# pragma GCC diagnostic ignored "-Wparentheses" + // Because REQUIREs trigger GCC's -Wparentheses, and because still + // supported version of g++ have only buggy support for _Pragmas, + // Wparentheses have to be suppressed globally. +# pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details + # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wunused-variable" # pragma GCC diagnostic ignored "-Wpadded" @@ -55,7 +58,9 @@ # if defined(CATCH_CONFIG_DISABLE_MATCHERS) # undef CATCH_CONFIG_DISABLE_MATCHERS # endif -# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +# if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) +# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +# endif #endif #if !defined(CATCH_CONFIG_IMPL_ONLY) @@ -72,7 +77,7 @@ #elif defined(linux) || defined(__linux) || defined(__linux__) # define CATCH_PLATFORM_LINUX -#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) # define CATCH_PLATFORM_WINDOWS #endif @@ -104,6 +109,7 @@ namespace Catch { // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? // CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? // CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? +// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? // **************** // Note to maintainers: if new toggles are added please document them // in configuration.md, too @@ -116,11 +122,11 @@ namespace Catch { #ifdef __cplusplus -# if __cplusplus >= 201402L +# if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) # define CATCH_CPP14_OR_GREATER # endif -# if __cplusplus >= 201703L +# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) # define CATCH_CPP17_OR_GREATER # endif @@ -130,20 +136,33 @@ namespace Catch { # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS #endif -#ifdef __clang__ +// We have to avoid both ICC and Clang, because they try to mask themselves +// as gcc, and we want only GCC in this block +#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) +#endif + +#if defined(__clang__) + +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) -# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ - _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") -# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ - _Pragma( "clang diagnostic pop" ) +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ + _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic pop" ) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) + +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) #endif // __clang__ @@ -164,6 +183,25 @@ namespace Catch { # define CATCH_CONFIG_COLOUR_NONE #endif +//////////////////////////////////////////////////////////////////////////////// +// Android somehow still does not support std::to_string +#if defined(__ANDROID__) +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING +# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Not all Windows environments support SEH properly +#if defined(__MINGW32__) +# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH +#endif + +//////////////////////////////////////////////////////////////////////////////// +// PS4 +#if defined(__ORBIS__) +# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE +#endif + //////////////////////////////////////////////////////////////////////////////// // Cygwin #ifdef __CYGWIN__ @@ -171,12 +209,22 @@ namespace Catch { // Required for some versions of Cygwin to declare gettimeofday // see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin # define _BSD_SOURCE +// some versions of cygwin (most) do not support std::to_string. Use the libstd check. +// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 +# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ + && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING + +# endif #endif // __CYGWIN__ //////////////////////////////////////////////////////////////////////////////// // Visual C++ -#ifdef _MSC_VER +#if defined(_MSC_VER) + +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) # if _MSC_VER >= 1900 // Visual Studio 2015 or newer # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS @@ -190,15 +238,37 @@ namespace Catch { # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH # endif +// MSVC traditional preprocessor needs some workaround for __VA_ARGS__ +// _MSVC_TRADITIONAL == 0 means new conformant preprocessor +// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor +# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) +# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +# endif +#endif // _MSC_VER + +#if defined(_REENTRANT) || defined(_MSC_VER) +// Enable async processing, as -pthread is specified or no additional linking is required +# define CATCH_INTERNAL_CONFIG_USE_ASYNC #endif // _MSC_VER //////////////////////////////////////////////////////////////////////////////// +// Check if we are compiled with -fno-exceptions or equivalent +#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) +# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED +#endif +//////////////////////////////////////////////////////////////////////////////// // DJGPP #ifdef __DJGPP__ # define CATCH_INTERNAL_CONFIG_NO_WCHAR #endif // __DJGPP__ +//////////////////////////////////////////////////////////////////////////////// +// Embarcadero C++Build +#if defined(__BORLANDC__) + #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN +#endif + //////////////////////////////////////////////////////////////////////////////// // Use of __COUNTER__ is suppressed during code analysis in @@ -210,10 +280,59 @@ namespace Catch { #define CATCH_INTERNAL_CONFIG_COUNTER #endif +//////////////////////////////////////////////////////////////////////////////// + +// RTX is a special version of Windows that is real time. +// This means that it is detected as Windows, but does not provide +// the same set of capabilities as real Windows does. +#if defined(UNDER_RTSS) || defined(RTX64_BUILD) + #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH + #define CATCH_INTERNAL_CONFIG_NO_ASYNC + #define CATCH_CONFIG_COLOUR_NONE +#endif + +#if defined(__UCLIBC__) +#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Various stdlib support checks that require __has_include +#if defined(__has_include) + // Check if string_view is available and usable + #if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW + #endif + + // Check if optional is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if byte is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_BYTE + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if variant is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # if defined(__clang__) && (__clang_major__ < 8) + // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 + // fix should be in clang 8, workaround in libstdc++ 8.2 + # include + # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # define CATCH_CONFIG_NO_CPP17_VARIANT + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__clang__) && (__clang_major__ < 8) + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) +#endif // defined(__has_include) + #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) # define CATCH_CONFIG_COUNTER #endif -#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) +#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) # define CATCH_CONFIG_WINDOWS_SEH #endif // This is set by default, because we assume that unix compilers are posix-signal-compatible by default. @@ -225,17 +344,101 @@ namespace Catch { # define CATCH_CONFIG_WCHAR #endif +#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) +# define CATCH_CONFIG_CPP11_TO_STRING +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) +# define CATCH_CONFIG_CPP17_OPTIONAL +#endif + #if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) # define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS #endif +#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) +# define CATCH_CONFIG_CPP17_STRING_VIEW +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) +# define CATCH_CONFIG_CPP17_VARIANT +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) +# define CATCH_CONFIG_CPP17_BYTE +#endif + +#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) +# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE) +# define CATCH_CONFIG_NEW_CAPTURE +#endif + +#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +# define CATCH_CONFIG_DISABLE_EXCEPTIONS +#endif + +#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) +# define CATCH_CONFIG_POLYFILL_ISNAN +#endif + +#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) +# define CATCH_CONFIG_USE_ASYNC +#endif + +#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) +# define CATCH_CONFIG_ANDROID_LOGWRITE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) +# define CATCH_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Even if we do not think the compiler has that warning, we still have +// to provide a macro that can be used by the code. +#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +#endif #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS +#endif + +#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#elif defined(__clang__) && (__clang_major__ < 5) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +#define CATCH_TRY if ((true)) +#define CATCH_CATCH_ALL if ((false)) +#define CATCH_CATCH_ANON(type) if ((false)) +#else +#define CATCH_TRY try +#define CATCH_CATCH_ALL catch (...) +#define CATCH_CATCH_ANON(type) catch (type) +#endif + +#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) +#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #endif // end catch_compiler_capabilities.h @@ -251,6 +454,10 @@ namespace Catch { #include #include +// We need a dummy global operator<< so we can bring it into Catch namespace later +struct Catch_global_namespace_dummy {}; +std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); + namespace Catch { struct CaseSensitive { enum Choice { @@ -277,12 +484,12 @@ namespace Catch { line( _line ) {} - SourceLineInfo( SourceLineInfo const& other ) = default; - SourceLineInfo( SourceLineInfo && ) = default; - SourceLineInfo& operator = ( SourceLineInfo const& ) = default; - SourceLineInfo& operator = ( SourceLineInfo && ) = default; + SourceLineInfo( SourceLineInfo const& other ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo( SourceLineInfo&& ) noexcept = default; + SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; - bool empty() const noexcept; + bool empty() const noexcept { return file[0] == '\0'; } bool operator == ( SourceLineInfo const& other ) const noexcept; bool operator < ( SourceLineInfo const& other ) const noexcept; @@ -292,6 +499,11 @@ namespace Catch { std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + // Bring in operator<< from global namespace into Catch namespace + // This is necessary because the overload of operator<< above makes + // lookup stop at namespace Catch + using ::operator<<; + // Use this in variadic streaming macros to allow // >> +StreamEndStop // as well as @@ -318,9 +530,10 @@ namespace Catch { } // end namespace Catch #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION // end catch_tag_alias_autoregistrar.h // start catch_test_registry.h @@ -328,7 +541,6 @@ namespace Catch { // start catch_interfaces_testcase.h #include -#include namespace Catch { @@ -339,8 +551,6 @@ namespace Catch { virtual ~ITestInvoker(); }; - using ITestCasePtr = std::shared_ptr; - class TestCase; struct IConfig; @@ -350,6 +560,7 @@ namespace Catch { virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; }; + bool isThrowSafe( TestCase const& testCase, IConfig const& config ); bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); std::vector const& getAllTestCasesSorted( IConfig const& config ); @@ -362,55 +573,30 @@ namespace Catch { #include #include #include +#include namespace Catch { - class StringData; - /// A non-owning string class (similar to the forthcoming std::string_view) /// Note that, because a StringRef may be a substring of another string, - /// it may not be null terminated. c_str() must return a null terminated - /// string, however, and so the StringRef will internally take ownership - /// (taking a copy), if necessary. In theory this ownership is not externally - /// visible - but it does mean (substring) StringRefs should not be shared between - /// threads. + /// it may not be null terminated. class StringRef { public: using size_type = std::size_t; + using const_iterator = const char*; private: - friend struct StringRefTestAccess; - - char const* m_start; - size_type m_size; - - char* m_data = nullptr; - - void takeOwnership(); - static constexpr char const* const s_empty = ""; - public: // construction/ assignment - StringRef() noexcept - : StringRef( s_empty, 0 ) - {} - - StringRef( StringRef const& other ) noexcept - : m_start( other.m_start ), - m_size( other.m_size ) - {} + char const* m_start = s_empty; + size_type m_size = 0; - StringRef( StringRef&& other ) noexcept - : m_start( other.m_start ), - m_size( other.m_size ), - m_data( other.m_data ) - { - other.m_data = nullptr; - } + public: // construction + constexpr StringRef() noexcept = default; StringRef( char const* rawChars ) noexcept; - StringRef( char const* rawChars, size_type size ) noexcept + constexpr StringRef( char const* rawChars, size_type size ) noexcept : m_start( rawChars ), m_size( size ) {} @@ -420,65 +606,333 @@ namespace Catch { m_size( stdString.size() ) {} - ~StringRef() noexcept { - delete[] m_data; - } - - auto operator = ( StringRef const &other ) noexcept -> StringRef& { - delete[] m_data; - m_data = nullptr; - m_start = other.m_start; - m_size = other.m_size; - return *this; + explicit operator std::string() const { + return std::string(m_start, m_size); } - operator std::string() const; - - void swap( StringRef& other ) noexcept; - public: // operators auto operator == ( StringRef const& other ) const noexcept -> bool; - auto operator != ( StringRef const& other ) const noexcept -> bool; + auto operator != (StringRef const& other) const noexcept -> bool { + return !(*this == other); + } - auto operator[] ( size_type index ) const noexcept -> char; + auto operator[] ( size_type index ) const noexcept -> char { + assert(index < m_size); + return m_start[index]; + } public: // named queries - auto empty() const noexcept -> bool { + constexpr auto empty() const noexcept -> bool { return m_size == 0; } - auto size() const noexcept -> size_type { + constexpr auto size() const noexcept -> size_type { return m_size; } - auto numberOfCharacters() const noexcept -> size_type; + // Returns the current start pointer. If the StringRef is not + // null-terminated, throws std::domain_exception auto c_str() const -> char const*; public: // substrings and searches - auto substr( size_type start, size_type size ) const noexcept -> StringRef; + // Returns a substring of [start, start + length). + // If start + length > size(), then the substring is [start, size()). + // If start > size(), then the substring is empty. + auto substr( size_type start, size_type length ) const noexcept -> StringRef; - // Returns the current start pointer. - // Note that the pointer can change when if the StringRef is a substring - auto currentData() const noexcept -> char const*; + // Returns the current start pointer. May not be null-terminated. + auto data() const noexcept -> char const*; - private: // ownership queries - may not be consistent between calls - auto isOwned() const noexcept -> bool; - auto isSubstring() const noexcept -> bool; - }; + constexpr auto isNullTerminated() const noexcept -> bool { + return m_start[m_size] == '\0'; + } - auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string; - auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string; - auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string; + public: // iterators + constexpr const_iterator begin() const { return m_start; } + constexpr const_iterator end() const { return m_start + m_size; } + }; auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; - inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { + constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { return StringRef( rawChars, size ); } - } // namespace Catch +constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { + return Catch::StringRef( rawChars, size ); +} + // end catch_stringref.h +// start catch_preprocessor.hpp + + +#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ +#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) + +#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ +// MSVC needs more evaluations +#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) +#else +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) +#endif + +#define CATCH_REC_END(...) +#define CATCH_REC_OUT + +#define CATCH_EMPTY() +#define CATCH_DEFER(id) id CATCH_EMPTY() + +#define CATCH_REC_GET_END2() 0, CATCH_REC_END +#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 +#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 +#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT +#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) +#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) + +#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) + +#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) + +// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, +// and passes userdata as the first parameter to each invocation, +// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) +#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) +#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ +#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ +#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) +#else +// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) +#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) +#endif + +#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ +#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) + +#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) + +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper()) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) +#else +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper())) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) +#endif + +#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\ + CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) + +#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) +#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) +#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) +#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) +#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) +#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) +#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _4, _5, _6) +#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) +#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) +#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) +#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) + +#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N + +#define INTERNAL_CATCH_TYPE_GEN\ + template struct TypeList {};\ + template\ + constexpr auto get_wrapper() noexcept -> TypeList { return {}; }\ + template class...> struct TemplateTypeList{};\ + template class...Cs>\ + constexpr auto get_wrapper() noexcept -> TemplateTypeList { return {}; }\ + template\ + struct append;\ + template\ + struct rewrap;\ + template class, typename...>\ + struct create;\ + template class, typename>\ + struct convert;\ + \ + template \ + struct append { using type = T; };\ + template< template class L1, typename...E1, template class L2, typename...E2, typename...Rest>\ + struct append, L2, Rest...> { using type = typename append, Rest...>::type; };\ + template< template class L1, typename...E1, typename...Rest>\ + struct append, TypeList, Rest...> { using type = L1; };\ + \ + template< template class Container, template class List, typename...elems>\ + struct rewrap, List> { using type = TypeList>; };\ + template< template class Container, template class List, class...Elems, typename...Elements>\ + struct rewrap, List, Elements...> { using type = typename append>, typename rewrap, Elements...>::type>::type; };\ + \ + template