You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2019/11/08 21:33:06 UTC
[trafficserver] 03/04: Allow txn handler to be set from ssn on same
hook
This is an automated email from the ASF dual-hosted git repository.
zwoop pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit 712e1b9a340380e0aab45b6e7033557e37d85b13
Author: Susan Hinrichs <sh...@oath.com>
AuthorDate: Fri Oct 25 20:28:33 2019 +0000
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 +-
.../gold_tests/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(-)
diff --git a/proxy/InkAPIInternal.h b/proxy/InkAPIInternal.h
index 25fab38..4a90f35 100644
--- a/proxy/InkAPIInternal.h
+++ b/proxy/InkAPIInternal.h
@@ -357,8 +357,9 @@ public:
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 fb910e0..b508e03 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 0000000..9141bac
--- /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 0000000..3ea96bc
--- /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 0000000..f8fcfe4
--- /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 <ts/ts.h>
+
+#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<TSHttpTxn>(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<TSHttpSsn>(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<TSHttpSsn>(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<char *>(PLUGIN_TAG);
+ info.support_email = const_cast<char *>("shinrich@verizonmedia.com");
+ info.vendor_name = const_cast<char *>("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);
+}