You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by sj...@apache.org on 2010/03/30 20:22:25 UTC
svn commit: r929213 - in
/incubator/trafficserver/traffic/trunk/example/query_remap: ./ query_remap.c
Author: sjiang
Date: Tue Mar 30 18:22:25 2010
New Revision: 929213
URL: http://svn.apache.org/viewvc?rev=929213&view=rev
Log:
TS-270: code for example in chapter 3
Added:
incubator/trafficserver/traffic/trunk/example/query_remap/
incubator/trafficserver/traffic/trunk/example/query_remap/query_remap.c
Added: incubator/trafficserver/traffic/trunk/example/query_remap/query_remap.c
URL: http://svn.apache.org/viewvc/incubator/trafficserver/traffic/trunk/example/query_remap/query_remap.c?rev=929213&view=auto
==============================================================================
--- incubator/trafficserver/traffic/trunk/example/query_remap/query_remap.c (added)
+++ incubator/trafficserver/traffic/trunk/example/query_remap/query_remap.c Tue Mar 30 18:22:25 2010
@@ -0,0 +1,179 @@
+/** @file
+
+ A sample plugin to remap requests based on a query parameter
+
+ @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/remap.h>
+#include <ts/ts.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define PLUGIN_NAME "query_remap"
+
+//function prototypes
+u_int32_t hash_fnv32(char *buf, size_t len);
+
+typedef struct _query_remap_info {
+ char *param_name;
+ size_t param_len;
+ char **hosts;
+ int num_hosts;
+} query_remap_info;
+
+
+int tsremap_init(TSRemapInterface *api_info,char *errbuf,int errbuf_size)
+{
+// Called at TS startup. Nothing needed for this plugin
+ INKDebug(PLUGIN_NAME , "remap plugin initialized");
+ return 0;
+}
+
+
+int tsremap_new_instance(int argc,char *argv[],ihandle *ih,char *errbuf,int errbuf_size)
+{
+// Called for each remap rule using this plugin. The parameters are parsed here
+ int i;
+ INKDebug(PLUGIN_NAME, "new instance fromURL: %s toURL: %s", argv[0], argv[1]);
+
+ if (argc < 4) {
+ INKError("Missing parameters for " PLUGIN_NAME);
+ return -1;
+ }
+
+ //initialize the struct to store info about this remap instance
+ // the argv parameters are:
+ // 0: fromURL
+ // 1: toURL
+ // 2: query param to hash
+ // 3,4,... : server hostnames
+ query_remap_info *qri = (query_remap_info*) malloc(sizeof(query_remap_info));
+
+ qri->param_name = strdup(argv[2]);
+ qri->param_len = strlen(qri->param_name);
+ qri->num_hosts = argc - 3;
+ qri->hosts = (char**) malloc(qri->num_hosts*sizeof(char*));
+
+ INKDebug(PLUGIN_NAME, " - Hash using query parameter [%s] with %d hosts",
+ qri->param_name, qri->num_hosts);
+
+ for (i=0; i < qri->num_hosts; ++i) {
+ qri->hosts[i] = strdup(argv[i+3]);
+ INKDebug(PLUGIN_NAME, " - Host %d: %s", i, qri->hosts[i]);
+ }
+
+ *ih = (ihandle)qri;
+ INKDebug(PLUGIN_NAME, "created instance %p", *ih);
+ return 0;
+}
+
+void tsremap_delete_instance(ihandle ih)
+{
+// Release instance memory allocated in tsremap_new_instance
+ int i;
+ INKDebug(PLUGIN_NAME, "deleting instance %p", ih);
+
+ if (ih) {
+ query_remap_info *qri = (query_remap_info*)ih;
+ if (qri->param_name)
+ free(qri->param_name);
+ if (qri->hosts) {
+ for (i=0; i < qri->num_hosts; ++i) {
+ free(qri->hosts[i]);
+ }
+ free(qri->hosts);
+ }
+ free(qri);
+ }
+}
+
+
+int tsremap_remap(ihandle ih, rhandle rh, TSRemapRequestInfo *rri)
+{
+ int hostidx = -1;
+ query_remap_info *qri = (query_remap_info*)ih;
+
+ if (!qri) {
+ INKError(PLUGIN_NAME "NULL ihandle");
+ return 0;
+ }
+
+ INKDebug(PLUGIN_NAME, "tsremap_remap request: %.*s", rri->orig_url_size, rri->orig_url);
+
+ if (rri && rri->request_query && rri->request_query_size > 0) {
+ char *q, *s, *key;
+
+ //make a copy of the query, as it is read only
+ q = (char*) malloc(rri->request_query_size+1);
+ strncpy(q, rri->request_query, rri->request_query_size);
+ q[rri->request_query_size] = '\0';
+
+ s = q;
+ //parse query parameters
+ for (key = strsep(&s, "&"); key != NULL; key = strsep(&s, "&")) {
+ char *val = strchr(key, '=');
+ if (val && (size_t)(val-key) == qri->param_len &&
+ !strncmp(key, qri->param_name, qri->param_len)) {
+ ++val;
+ //the param key matched the configured param_name
+ //hash the param value to pick a host
+ hostidx = hash_fnv32(val, strlen(val)) % (u_int32_t)qri->num_hosts;
+ INKDebug(PLUGIN_NAME, "modifying host based on %s", key);
+ break;
+ }
+ }
+
+ free(q);
+
+ if (hostidx >= 0) {
+ rri->new_host_size = strlen(qri->hosts[hostidx]);
+ if (rri->new_host_size <= TSREMAP_RRI_MAX_HOST_SIZE) {
+ //copy the chosen host into rri
+ memcpy(rri->new_host, qri->hosts[hostidx], rri->new_host_size);
+
+ INKDebug(PLUGIN_NAME, "host changed from [%.*s] to [%.*s]",
+ rri->request_host_size, rri->request_host,
+ rri->new_host_size, rri->new_host);
+ return 1; //host has been modified
+ }
+ }
+ }
+
+ //the request was not modified, TS will use the toURL from the remap rule
+ INKDebug(PLUGIN_NAME, "request not modified");
+ return 0;
+}
+
+
+// FNV (Fowler/Noll/Vo) hash
+// (description: http://www.isthe.com/chongo/tech/comp/fnv/index.html)
+u_int32_t
+hash_fnv32(char *buf, size_t len)
+{
+ u_int32_t hval = (u_int32_t)0x811c9dc5; //FNV1_32_INIT
+
+ for (; len > 0; --len) {
+ hval *= (u_int32_t)0x01000193; //FNV_32_PRIME
+ hval ^= (u_int32_t)*buf++;
+ }
+
+ return hval;
+}
+