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 2010/11/04 22:52:27 UTC
svn commit: r1031274 - in /trafficserver/plugins/header_filter: ./
header_filter.cc lulu.h rules.cc rules.h
Author: zwoop
Date: Thu Nov 4 21:52:26 2010
New Revision: 1031274
URL: http://svn.apache.org/viewvc?rev=1031274&view=rev
Log:
Plugin to delete filters in various hook, or as a remap plugin
Added:
trafficserver/plugins/header_filter/
trafficserver/plugins/header_filter/header_filter.cc
trafficserver/plugins/header_filter/lulu.h
trafficserver/plugins/header_filter/rules.cc
trafficserver/plugins/header_filter/rules.h
Added: trafficserver/plugins/header_filter/header_filter.cc
URL: http://svn.apache.org/viewvc/trafficserver/plugins/header_filter/header_filter.cc?rev=1031274&view=auto
==============================================================================
--- trafficserver/plugins/header_filter/header_filter.cc (added)
+++ trafficserver/plugins/header_filter/header_filter.cc Thu Nov 4 21:52:26 2010
@@ -0,0 +1,198 @@
+//////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Main entry points for the plugin hooks etc.
+//
+#include <ts/ts.h>
+#include <ts/remap.h>
+#include <stdio.h>
+
+#include "rules.h"
+
+using namespace ::HeaderFilter;
+
+// Global plugin rules
+Rules global;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Continuation
+//
+static int
+cont_header_filter(INKCont contp, INKEvent event, void *edata)
+{
+ INKHttpTxn txnp = (INKHttpTxn) edata;
+ INKHttpHookID hook = INK_HTTP_LAST_HOOK;
+ INKMBuffer reqp;
+ INKMLoc hdr_loc;
+
+ // Get the resources necessary to process this event
+ switch (event) {
+ case INK_EVENT_HTTP_READ_REQUEST_HDR:
+ if (INKHttpTxnClientReqGet(txnp, &reqp, &hdr_loc))
+ hook = INK_HTTP_READ_REQUEST_HDR_HOOK;
+ break;
+ case INK_EVENT_HTTP_SEND_REQUEST_HDR:
+ if (INKHttpTxnServerReqGet(txnp, &reqp, &hdr_loc))
+ hook = INK_HTTP_SEND_REQUEST_HDR_HOOK;
+ break;
+ case INK_EVENT_HTTP_READ_RESPONSE_HDR:
+ if (INKHttpTxnServerRespGet(txnp, &reqp, &hdr_loc))
+ hook = INK_HTTP_READ_RESPONSE_HDR_HOOK;
+ break;
+ case INK_EVENT_HTTP_SEND_RESPONSE_HDR:
+ if (INKHttpTxnClientRespGet(txnp, &reqp, &hdr_loc))
+ hook = INK_HTTP_SEND_RESPONSE_HDR_HOOK;
+ break;
+ default:
+ INKError("header_rewrite: unknown event for this plugin");
+ INKDebug(PLUGIN_NAME, "unknown event for this plugin");
+ break;
+ }
+
+ if (hook != INK_HTTP_LAST_HOOK) {
+ Rules* from_remap;
+
+ global.execute(reqp, hdr_loc, hook);
+
+ if (INK_HTTP_READ_REQUEST_HDR_HOOK != hook) { // Don't run the hook handled by remap plugin
+ if (INK_SUCCESS == INKHttpTxnGetArg(txnp, 0, (void**)(&from_remap)) && from_remap)
+ from_remap->execute(reqp, hdr_loc, hook);
+ }
+
+ INKHandleMLocRelease(reqp, INK_NULL_MLOC, hdr_loc);
+ }
+
+ INKHttpTxnReenable(txnp, INK_EVENT_HTTP_CONTINUE);
+ return 0;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Initialize the InkAPI plugin for the global hooks we support.
+//
+void
+INKPluginInit(int argc, const char *argv[])
+{
+ INKPluginRegistrationInfo info;
+
+ info.plugin_name = const_cast<char*>(PLUGIN_NAME);
+ info.vendor_name = const_cast<char*>("Apache");
+ info.support_email = const_cast<char*>("users@trafficserver.apache.org");
+
+ if (!INKPluginRegister(INK_SDK_VERSION_2_0 , &info)) {
+ INKError("header_rewrite: plugin registration failed.\n");
+ }
+
+ if (argc != 2) {
+ INKError("usage: %s <config-file>\n", argv[0] );
+ }
+
+ // Parse the rules file
+ if (global.parse_file(argv[1])) {
+ INKCont cont = INKContCreate(cont_header_filter, NULL);
+
+ for (int i=INK_HTTP_READ_REQUEST_HDR_HOOK; i < INK_HTTP_LAST_HOOK; ++i) {
+ if (global.supported_hook(static_cast<INKHttpHookID>(i))) {
+ INKHttpHookAdd(static_cast<INKHttpHookID>(i), cont);
+ }
+ }
+ } else {
+ INKError("header_rewrite: failed to parse configuration file");
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Initialize the plugin as a remap plugin.
+//
+int
+tsremap_init(TSRemapInterface* api_info, char *errbuf, int errbuf_size)
+{
+ if (!api_info) {
+ strncpy(errbuf, "[tsremap_init] - Invalid TSRemapInterface argument", errbuf_size - 1);
+ return -1;
+ }
+
+ if (api_info->size < sizeof(TSRemapInterface)) {
+ strncpy(errbuf, "[tsremap_init] - Incorrect size of TSRemapInterface structure", errbuf_size - 1);
+ return -2;
+ }
+
+ if (api_info->tsremap_version < TSREMAP_VERSION) {
+ snprintf(errbuf, errbuf_size - 1, "[tsremap_init] - Incorrect API version %ld.%ld",
+ api_info->tsremap_version >> 16, (api_info->tsremap_version & 0xffff));
+ return -3;
+ }
+
+ INKDebug(PLUGIN_NAME, "remap plugin is succesfully initialized");
+ return 0; /* success */
+}
+
+
+int
+tsremap_new_instance(int argc, char* argv[], ihandle* ih, char* errbuf, int errbuf_size)
+{
+ if (argc < 3) {
+ INKError("Unable to create remap instance, need rules file");
+ return -1;
+ } else {
+ Rules* conf = new(Rules);
+
+ // TODO: Should deal with "inline" parameters here (in remap.config), e.g.
+ // @plugin=header_filter.so @pparam=READ_REQUEST_HDR @pparam=X-From-Me @pparam=X-From-Someone ...
+ conf->parse_file(argv[2]);
+ *ih = static_cast<ihandle>(conf);
+ }
+
+ return 0;
+}
+
+void
+tsremap_delete_instance(ihandle ih)
+{
+ Rules* conf = static_cast<Rules*>(ih);
+
+ delete conf;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Main entry point when used as a remap plugin.
+//
+int
+tsremap_remap(ihandle ih, rhandle rh, TSRemapRequestInfo *rri)
+{
+ if (NULL == ih) {
+ INKDebug(PLUGIN_NAME, "No Rules configured, falling back to default mapping rule");
+ return 0;
+ } else {
+ Rules* confp = static_cast<Rules*>(ih);
+ INKHttpTxn txnp = static_cast<INKHttpTxn>(rh);
+ INKMBuffer reqp;
+ INKMLoc hdr_loc;
+
+ INKHttpTxnSetArg(txnp, 0, static_cast<void*>(ih)); // Save for later hooks
+ if (INKHttpTxnClientReqGet(txnp, &reqp, &hdr_loc)) {
+ confp->execute(reqp, hdr_loc, INK_HTTP_READ_REQUEST_HDR_HOOK);
+ INKHandleMLocRelease(reqp, INK_NULL_MLOC, hdr_loc);
+ }
+ }
+
+ return 1;
+}
+
+
+/*
+ local variables:
+ mode: C++
+ indent-tabs-mode: nil
+ c-basic-offset: 2
+ c-comment-only-line-offset: 0
+ c-file-offsets: ((statement-block-intro . +)
+ (label . 0)
+ (statement-cont . +)
+ (innamespace . 0))
+ end:
+
+ Indent with: /usr/bin/indent -ncs -nut -npcs -l 120 logstats.cc
+*/
Added: trafficserver/plugins/header_filter/lulu.h
URL: http://svn.apache.org/viewvc/trafficserver/plugins/header_filter/lulu.h?rev=1031274&view=auto
==============================================================================
--- trafficserver/plugins/header_filter/lulu.h (added)
+++ trafficserver/plugins/header_filter/lulu.h Thu Nov 4 21:52:26 2010
@@ -0,0 +1,89 @@
+//////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Implement the classes for the various types of hash keys we support.
+//
+#ifndef __LULU_H__
+#define __LULU_H__ 1
+
+// Define UNUSED properly.
+#if ((__GNUC__ >= 3) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 7)))
+#define UNUSED __attribute__ ((unused))
+#else
+#define UNUSED
+#endif /* #if ((__GNUC__ >= 3) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 7))) */
+
+#include <sys/types.h>
+
+// Memory barriers on i386 / linux / gcc
+#if defined(__i386__)
+#define mb() __asm__ __volatile__ ( "lock; addl $0,0(%%esp)" : : : "memory" )
+#define rmb() __asm__ __volatile__ ( "lock; addl $0,0(%%esp)" : : : "memory" )
+#define wmb() __asm__ __volatile__ ( "" : : : "memory")
+#elif defined(__x86_64__)
+#define mb() __asm__ __volatile__ ( "mfence" : : : "memory")
+#define rmb() __asm__ __volatile__ ( "lfence" : : : "memory")
+#define wmb() __asm__ __volatile__ ( "" : : : "memory")
+#else
+#error "Define barriers"
+#endif
+
+// Used for Debug etc.
+static const char* PLUGIN_NAME = "header_filter";
+static const char* PLUGIN_NAME_DBG = "header_filter_dbg";
+
+
+// From the atomic portions of ATS
+typedef int int32;
+typedef unsigned int intu32;
+typedef long long int64;
+typedef unsigned long long intu64;
+
+typedef volatile int32 vint32;
+typedef volatile int64 vint64;
+typedef volatile void *vvoidp;
+typedef vint32 *pvint32;
+typedef vint64 *pvint64;
+typedef vvoidp *pvvoidp;
+
+#if defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
+
+/* see http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html */
+static inline int32 ink_atomic_swap(pvint32 mem, int32 value) { return __sync_lock_test_and_set(mem, value); }
+static inline int64 ink_atomic_swap64(pvint64 mem, int64 value) { return __sync_lock_test_and_set(mem, value); }
+static inline void *ink_atomic_swap_ptr(vvoidp mem, void *value) { return __sync_lock_test_and_set((void**)mem, value); }
+static inline int ink_atomic_cas(pvint32 mem, int old, int new_value) { return __sync_bool_compare_and_swap(mem, old, new_value); }
+static inline int64 ink_atomic_cas64(pvint64 mem, int64 old, int64 new_value) { return __sync_bool_compare_and_swap(mem, old, new_value); }
+static inline int ink_atomic_cas_ptr(pvvoidp mem, void* old, void* new_value) { return __sync_bool_compare_and_swap(mem, old, new_value); }
+static inline int ink_atomic_increment(pvint32 mem, int value) { return __sync_fetch_and_add(mem, value); }
+static inline int64 ink_atomic_increment64(pvint64 mem, int64 value) { return __sync_fetch_and_add(mem, value); }
+static inline void *ink_atomic_increment_ptr(pvvoidp mem, intptr_t value) { return __sync_fetch_and_add((void**)mem, value); }
+#else
+// TODO: Deal with this case?
+#failure
+#endif
+
+
+// From google styleguide: http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&); \
+ void operator=(const TypeName&)
+
+
+#endif // __LULU_H__
+
+
+
+/*
+ local variables:
+ mode: C++
+ indent-tabs-mode: nil
+ c-basic-offset: 2
+ c-comment-only-line-offset: 0
+ c-file-offsets: ((statement-block-intro . +)
+ (label . 0)
+ (statement-cont . +)
+ (innamespace . 0))
+ end:
+
+ Indent with: /usr/bin/indent -ncs -nut -npcs -l 120 logstats.cc
+*/
Added: trafficserver/plugins/header_filter/rules.cc
URL: http://svn.apache.org/viewvc/trafficserver/plugins/header_filter/rules.cc?rev=1031274&view=auto
==============================================================================
--- trafficserver/plugins/header_filter/rules.cc (added)
+++ trafficserver/plugins/header_filter/rules.cc Thu Nov 4 21:52:26 2010
@@ -0,0 +1,139 @@
+//////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Implemenation details for the rules class.
+//
+#include <fstream>
+#include <ts/ts.h>
+
+#include "rules.h"
+
+namespace HeaderFilter {
+
+// RulesEntry implementations
+void
+RulesEntry::append(RulesEntry* entry)
+{
+ RulesEntry* n = this;
+
+ while (NULL != n->_next)
+ n = n->_next;
+ n->_next = entry;
+}
+
+void
+RulesEntry::execute(INKMBuffer& reqp, INKMLoc& hdr_loc)
+{
+ INKMLoc field, tmp;
+ RulesEntry* n = this;
+
+ while (n) {
+ field = INKMimeHdrFieldFind(reqp, hdr_loc, n->_header, n->_len);
+ while (field) {
+ INKDebug(PLUGIN_NAME, "\tDeleting header %.*s", n->_len, n->_header);
+ tmp = INKMimeHdrFieldNextDup(reqp, hdr_loc, field);
+ INKMimeHdrFieldDestroy(reqp, hdr_loc, field);
+ INKHandleMLocRelease(reqp, hdr_loc, field);
+ field = tmp;
+ }
+ n = n->_next;
+ }
+}
+
+
+// Rules class implementations
+Rules::~Rules()
+{
+ INKDebug(PLUGIN_NAME_DBG, "Calling DTOR for Rules");
+
+ for (int i = 0; i < INK_HTTP_LAST_HOOK; ++i) {
+ if (_entries[i])
+ delete _entries[i];
+ }
+}
+
+RulesEntry*
+Rules::add_entry(const INKHttpHookID hook, const std::string& s)
+{
+ RulesEntry* e = new(RulesEntry)(s);
+
+ INKAssert(supported_hook(hook));
+ if (NULL == _entries[hook]) {
+ _entries[hook] = e;
+ } else {
+ _entries[hook]->append(e);
+ }
+
+ return e;
+}
+
+bool
+Rules::parse_file(const char* filename)
+{
+ std::ifstream f;
+ INKHttpHookID hook = INK_HTTP_READ_REQUEST_HDR_HOOK;
+ int lineno = 0;
+
+ // TODO: Should we support a 'default' prefix here for the ruless?
+ f.open(filename, std::ios::in);
+ if (!f.is_open()) {
+ INKError("unable to open %s", filename);
+ return false;
+ }
+ INKDebug(PLUGIN_NAME, "Parsing config file %s", filename);
+ while (!f.eof()) {
+ std::string line, word;
+ std::string::size_type pos1, pos2;
+
+ getline(f, line);
+ ++lineno;
+ if (line.empty())
+ continue;
+
+ pos1 = line.find_first_not_of(" \t\n");
+ if (pos1 != std::string::npos) {
+ if (line[pos1] == '#') {
+ continue; // Skip comments
+ } else {
+ pos2 = line.find_first_of("# \t\n", pos1); // End of line
+ if (pos2 == std::string::npos)
+ pos2 = line.length();
+ word = line.substr(pos1, pos2-pos1);
+
+ if (word == "READ_REQUEST_HDR:") {
+ hook = INK_HTTP_READ_REQUEST_HDR_HOOK;
+ } else if (word == "SEND_REQUEST_HDR:") {
+ hook = INK_HTTP_SEND_REQUEST_HDR_HOOK;
+ } else if (word == "READ_RESPONSE_HDR:") {
+ hook = INK_HTTP_READ_RESPONSE_HDR_HOOK;
+ } else if (word == "SEND_RESPONSE_HDR:") {
+ hook = INK_HTTP_SEND_RESPONSE_HDR_HOOK;
+ } else { // Assume it's a header name for everything else
+ if (!word.empty()) {
+ INKDebug(PLUGIN_NAME, "Adding %s to hook %d", word.c_str(), hook);
+ add_entry(hook, word);
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+} // End of namespace ::HeaderFilter
+
+
+/*
+ local variables:
+ mode: C++
+ indent-tabs-mode: nil
+ c-basic-offset: 2
+ c-comment-only-line-offset: 0
+ c-file-offsets: ((statement-block-intro . +)
+ (label . 0)
+ (statement-cont . +)
+ (innamespace . 0))
+ end:
+
+ Indent with: /usr/bin/indent -ncs -nut -npcs -l 120 logstats.cc
+*/
Added: trafficserver/plugins/header_filter/rules.h
URL: http://svn.apache.org/viewvc/trafficserver/plugins/header_filter/rules.h?rev=1031274&view=auto
==============================================================================
--- trafficserver/plugins/header_filter/rules.h (added)
+++ trafficserver/plugins/header_filter/rules.h Thu Nov 4 21:52:26 2010
@@ -0,0 +1,103 @@
+//////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Class for holding a set of configurations. There would be one global configuration, used
+// by all hooks / requests, and one optional configuration for each remap rule.
+//
+#ifndef __RULES_H__
+#define __RULES_H__ 1
+
+#include <string>
+#include <string.h>
+#include <ts/ts.h>
+#include "lulu.h"
+
+namespace HeaderFilter {
+
+class RulesEntry
+{
+public:
+ RulesEntry(const std::string& s)
+ : _header(NULL), _len(0), _next(NULL)
+ {
+ _header = INKstrdup(s.c_str());
+ _len = s.length();
+ INKDebug(PLUGIN_NAME_DBG, "Calling CTOR for RulesEntry, header is %s", _header);
+ }
+
+ ~RulesEntry()
+ {
+ INKDebug(PLUGIN_NAME_DBG, "Calling DTOR for RulesEntry");
+ if (_next)
+ delete _next; // Potentially "deep" recursion, but should be OK.
+ if (_header)
+ INKfree(_header);
+ }
+
+ void append(RulesEntry* entry);
+ void execute(INKMBuffer& reqp, INKMLoc& hdr_loc); // This is really the meat of the app
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(RulesEntry);
+
+ char* _header;
+ size_t _len;
+ RulesEntry* _next;
+};
+
+
+class Rules
+{
+public:
+ Rules()
+ {
+ INKDebug(PLUGIN_NAME_DBG, "Calling CTOR for Rules");
+ memset(_entries, 0, sizeof(_entries));
+ }
+
+ virtual ~Rules();
+
+ RulesEntry* add_entry(const INKHttpHookID hook, const std::string& s);
+ bool parse_file(const char* filename);
+
+ bool supported_hook(const INKHttpHookID hook)
+ {
+ return ((hook == INK_HTTP_READ_REQUEST_HDR_HOOK) ||
+ (hook == INK_HTTP_SEND_REQUEST_HDR_HOOK) ||
+ (hook == INK_HTTP_READ_RESPONSE_HDR_HOOK) ||
+ (hook == INK_HTTP_SEND_RESPONSE_HDR_HOOK));
+ }
+
+ void execute(INKMBuffer& reqp, INKMLoc& hdr_loc, const INKHttpHookID hook)
+ {
+ INKAssert(supported_hook(hook));
+ INKDebug(PLUGIN_NAME, "Executing rules(s) for hook %d", hook);
+ _entries[hook]->execute(reqp, hdr_loc);
+ }
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(Rules);
+
+ RulesEntry* _entries[INK_HTTP_LAST_HOOK]; // One possible set of entries for each hook
+};
+
+} // End of namespace ::HeaderFilter
+
+
+#endif // __RULES_H__
+
+
+
+/*
+ local variables:
+ mode: C++
+ indent-tabs-mode: nil
+ c-basic-offset: 2
+ c-comment-only-line-offset: 0
+ c-file-offsets: ((statement-block-intro . +)
+ (label . 0)
+ (statement-cont . +)
+ (innamespace . 0))
+ end:
+
+ Indent with: /usr/bin/indent -ncs -nut -npcs -l 120 logstats.cc
+*/