quick cpp 11 commit more changes to come
Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/7986be61 Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/7986be61 Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/7986be61 Branch: refs/heads/master Commit: 7986be6188369778d55a4b275e258dddc9d1ae70 Parents: 1be0bfc Author: Brian Geffon <[email protected]> Authored: Mon Jul 23 12:56:20 2012 -0700 Committer: Brian Geffon <[email protected]> Committed: Mon Jul 23 12:56:20 2012 -0700 ---------------------------------------------------------------------- configure.ac | 15 +++ lib/Makefile.am | 4 + lib/cpp11api/Makefile.am | 28 +++++ lib/cpp11api/cpp11api.cc | 231 +++++++++++++++++++++++++++++++++++++++++ lib/cpp11api/ts-cpp11.h | 70 +++++++++++++ 5 files changed, 348 insertions(+), 0 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/7986be61/configure.ac ---------------------------------------------------------------------- diff --git a/configure.ac b/configure.ac index 2510ca3..696f871 100644 --- a/configure.ac +++ b/configure.ac @@ -288,6 +288,20 @@ TS_ARG_ENABLE_VAR([has],[wccp]) AC_SUBST(has_wccp) AM_CONDITIONAL([BUILD_WCCP], [test 0 -ne $has_wccp]) +# +# CPP 11 API +# +AC_MSG_CHECKING([whether to enable c++11 api]) +AC_ARG_WITH([cpp11api], + [AS_HELP_STRING([--with-cpp11api],[enable support for cpp11api [default=no]])], + [cpp11api=$withval], + [cpp11api=no] +) +AC_MSG_RESULT([$cpp11api]) +AM_CONDITIONAL([BUILD_CPP11API], [test "$cpp11api" = yes]) + + + # Google profiler AC_MSG_CHECKING([whether to enable profiler]) AC_ARG_WITH([profiler], @@ -1485,6 +1499,7 @@ AC_CONFIG_FILES([iocore/utils/Makefile]) AC_CONFIG_FILES([lib/Makefile]) AC_CONFIG_FILES([lib/ts/Makefile]) AC_CONFIG_FILES([lib/records/Makefile]) +AC_CONFIG_FILES([lib/cpp11api/Makefile]) AC_CONFIG_FILES([lib/tsconfig/Makefile]) AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([proxy/config/body_factory/default/Makefile]) http://git-wip-us.apache.org/repos/asf/trafficserver/blob/7986be61/lib/Makefile.am ---------------------------------------------------------------------- diff --git a/lib/Makefile.am b/lib/Makefile.am index 3507cfb..7f70234 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -22,3 +22,7 @@ SUBDIRS = ts records if BUILD_WCCP SUBDIRS += tsconfig wccp endif + +if BUILD_CPP11API +SUBDIRS += cpp11api +endif \ No newline at end of file http://git-wip-us.apache.org/repos/asf/trafficserver/blob/7986be61/lib/cpp11api/Makefile.am ---------------------------------------------------------------------- diff --git a/lib/cpp11api/Makefile.am b/lib/cpp11api/Makefile.am new file mode 100644 index 0000000..6ea5e8b --- /dev/null +++ b/lib/cpp11api/Makefile.am @@ -0,0 +1,28 @@ +# Makefile.am for C++11 API +# +# 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. + +AM_CPPFLAGS = -I$(top_srcdir)/proxy/api/ts -std=c++11 + +lib_LTLIBRARIES = libatscpp11api.la + +libatscpp11api_la_SOURCES = \ + cpp11api.cc + +includedir=$(prefix)/include/ts +include_HEADERS = \ + ts-cpp11.h \ No newline at end of file http://git-wip-us.apache.org/repos/asf/trafficserver/blob/7986be61/lib/cpp11api/cpp11api.cc ---------------------------------------------------------------------- diff --git a/lib/cpp11api/cpp11api.cc b/lib/cpp11api/cpp11api.cc new file mode 100644 index 0000000..d20ee3f --- /dev/null +++ b/lib/cpp11api/cpp11api.cc @@ -0,0 +1,231 @@ +/** @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. + */ + + +#include <ts.h> +#include "ts-cpp11.h" + +using namespace ats::api; + +TSHttpHookID TSHookIDFromHookType(HookType hook); + +class HookContinuationData { +public: + GlobalHookCallback callback; + HookType hooktype; + TSHttpHookID ts_hook_id; +}; + +class ats::api::Transaction { +public: + TSHttpTxn ts_http_txn_ = NULL; + TSCont ts_contp_ = NULL; +}; + +extern "C" void TSPluginInit(int argc, const char *argv[]) { + + TSPluginRegistrationInfo registration_info; + + const char *api_version_string = "cpp11api"; + + registration_info.plugin_name = const_cast<char*>(api_version_string); + registration_info.vendor_name = const_cast<char*>(api_version_string); + registration_info.support_email = const_cast<char*>(api_version_string); + + if (TSPluginRegister(TS_SDK_VERSION_3_0, ®istration_info) != TS_SUCCESS) { + return; + } + + StringVector arguments; + for (int i = 0; i < argc; ++i) { + arguments.push_back(std::string(argv[i])); + } + + // Finally we will call the wrapper API registration point + PluginRegister(arguments); +} + +TSHttpHookID TSHookIDFromHookType(HookType hook) { + switch (hook) { + case ats::api::HookType::HOOK_PRE_REMAP: + return TS_HTTP_PRE_REMAP_HOOK; + break; + case ats::api::HookType::HOOK_POST_REMAP: + return TS_HTTP_POST_REMAP_HOOK; + break; + case ats::api::HookType::HOOK_READ_REQUEST_HEADER: + return TS_HTTP_READ_REQUEST_HDR_HOOK; + break; + case ats::api::HookType::HOOK_READ_RESPONSE_HEADER: + return TS_HTTP_READ_RESPONSE_HDR_HOOK; + break; + case ats::api::HookType::HOOK_SEND_RESPONSE_HEADER: + return TS_HTTP_SEND_RESPONSE_HDR_HOOK; + break; + } + + return TS_HTTP_READ_REQUEST_HDR_HOOK; +} + +std::string ats::api::GetPristineRequestUrl(Transaction &t) { + TSMBuffer bufp; + TSMLoc url_loc; + + if (TSHttpTxnPristineUrlGet(t.ts_http_txn_, &bufp, &url_loc) != TS_SUCCESS) + return std::string(); + + int url_len; + char *urlp = TSUrlStringGet(bufp, url_loc, &url_len); + std::string url(urlp, url_len); + + TSfree(urlp); + + TSHandleMLocRelease(bufp, TS_NULL_MLOC, url_loc); + + return url; +} + +std::string ats::api::GetRequestUrl(Transaction &t) { + TSMBuffer bufp; + TSMLoc hdr_loc; + TSMLoc url_loc; + + if (TSHttpTxnClientReqGet(t.ts_http_txn_, &bufp, &hdr_loc) != TS_SUCCESS) + return std::string(); + + TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc); + + int url_len; + char *urlp = TSUrlStringGet(bufp, url_loc, &url_len); + std::string url(urlp, url_len); + + TSfree(urlp); + + TSHandleMLocRelease(bufp, hdr_loc, url_loc); + TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); + + return url; +} + +std::string ats::api::GetRequestUrlPath(Transaction &t) { + TSMBuffer bufp; + TSMLoc hdr_loc; + TSMLoc url_loc; + + if (TSHttpTxnClientReqGet(t.ts_http_txn_, &bufp, &hdr_loc) != TS_SUCCESS) + return std::string(); + + TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc); + + int path_length; + const char *path = TSUrlPathGet(bufp, url_loc, &path_length); + + std::string ret(path, path_length); + + TSHandleMLocRelease(bufp, hdr_loc, url_loc); + TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); + + return ret; +} + +void inline ReenableBasedOnNextState(TSHttpTxn txnp, NextState ns) +{ + switch (ns) { + case NextState::HTTP_DONT_CONTINUE: + return; + break; + case NextState::HTTP_ERROR: + TSHttpTxnReenable(txnp, static_cast<TSEvent>(TS_EVENT_HTTP_ERROR)); + break; + case NextState::HTTP_CONTINUE: + default: + TSHttpTxnReenable(txnp, static_cast<TSEvent>(TS_EVENT_HTTP_CONTINUE)); + break; + } +} + +static int GlobalContinuationHandler(TSCont contp, TSEvent event, void *edata) { + TSHttpTxn txnp = static_cast<TSHttpTxn>(edata); + + Transaction transaction; + transaction.ts_http_txn_ = txnp; + transaction.ts_contp_ = contp; + + HookContinuationData *data = static_cast<HookContinuationData*>(TSContDataGet(contp)); + auto ns = data->callback(transaction); + ReenableBasedOnNextState(txnp, ns); + + return 0; +} + +static int TransactionContinuationHandler(TSCont contp, TSEvent event, void *edata) { + TSHttpTxn txnp = static_cast<TSHttpTxn>(edata); + + Transaction transaction; + transaction.ts_http_txn_ = txnp; + transaction.ts_contp_ = contp; + + NextState ns = NextState::HTTP_CONTINUE; + HookContinuationData *data = static_cast<HookContinuationData*>(TSContDataGet(contp)); + if(event != TS_EVENT_HTTP_TXN_CLOSE || (event == TS_EVENT_HTTP_TXN_CLOSE && data->ts_hook_id == TS_HTTP_TXN_CLOSE_HOOK)) + { + ns = data->callback(transaction); + } + + // We must free the HookContinuationData structure and continuation + // If this transaction is complete + if(event == TS_EVENT_HTTP_TXN_CLOSE) { + delete data; + TSContDestroy(contp); + } + + ReenableBasedOnNextState(txnp, ns); + return 0; +} + +void ats::api::CreateTransactionHook(Transaction &txn, HookType hook, GlobalHookCallback callback) { + TSHttpHookID ts_hook_id = TSHookIDFromHookType(hook); + TSCont contp = TSContCreate(TransactionContinuationHandler, NULL); + + HookContinuationData *data = new HookContinuationData(); + data->callback = callback; + data->hooktype = hook; + data->ts_hook_id = ts_hook_id; + + TSContDataSet(contp, static_cast<void*>(data)); + TSHttpTxnHookAdd(txn.ts_http_txn_,ts_hook_id, contp); + + if(ts_hook_id != TS_HTTP_TXN_CLOSE_HOOK) { + TSHttpTxnHookAdd(txn.ts_http_txn_,TS_HTTP_TXN_CLOSE_HOOK, contp); + } +} + +void ats::api::CreateGlobalHook(HookType hook, GlobalHookCallback callback) { + + TSHttpHookID ts_hook_id = TSHookIDFromHookType(hook); + TSCont contp = TSContCreate(GlobalContinuationHandler, NULL); + + HookContinuationData *data = new HookContinuationData(); + data->callback = callback; + data->hooktype = hook; + + TSContDataSet(contp, static_cast<void*>(data)); + TSHttpHookAdd(ts_hook_id, contp); +} http://git-wip-us.apache.org/repos/asf/trafficserver/blob/7986be61/lib/cpp11api/ts-cpp11.h ---------------------------------------------------------------------- diff --git a/lib/cpp11api/ts-cpp11.h b/lib/cpp11api/ts-cpp11.h new file mode 100644 index 0000000..3fdd2ed --- /dev/null +++ b/lib/cpp11api/ts-cpp11.h @@ -0,0 +1,70 @@ +/** @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. + */ + +#ifndef TS_CPP11_H_ +#define TS_CPP11_H_ + +#ifndef __GXX_EXPERIMENTAL_CXX0X__ +#error The C++ Apache Traffic Server API wrapper requires C++11 support. +#endif + +#include <functional> +#include <string> +#include <vector> + +namespace ats { +namespace api { +typedef std::vector<std::string> StringVector; + +enum class HookType { + HOOK_PRE_REMAP = 100, HOOK_POST_REMAP, HOOK_READ_RESPONSE_HEADER, HOOK_READ_REQUEST_HEADER, HOOK_SEND_RESPONSE_HEADER +}; + +enum class NextState { + HTTP_CONTINUE = 200, HTTP_ERROR, HTTP_DONT_CONTINUE +}; + +class Transaction; + +/* + * This is the type our global hook callbacks will take + */ +typedef std::function<NextState(Transaction &)> GlobalHookCallback; + +/* + * Create a new hook + */ +void CreateGlobalHook(HookType, GlobalHookCallback); +void CreateTransactionHook(Transaction &, HookType, GlobalHookCallback); + +std::string GetPristineRequestUrl(Transaction &); +std::string GetRequestUrl(Transaction &); +std::string GetRequestUrlPath(Transaction &); + +} +} + +/* + * Every plugin must have a simple entry point + */ +void PluginRegister(const ats::api::StringVector &); + + +#endif /* TS_CPP11_H_ */
