Repository: trafficserver Updated Branches: refs/heads/master 030a15d59 -> 63757db53
TS-3149: add traffic_via command Move Via header decoding from traffic_line to a new command, traffic_via. This closes #133. Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/63757db5 Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/63757db5 Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/63757db5 Branch: refs/heads/master Commit: 63757db53eed5d16a2ae2ee1b24c8d568bda0c80 Parents: 030a15d Author: Meera Mosale Nataraja <[email protected]> Authored: Wed Oct 29 15:40:42 2014 -0700 Committer: James Peach <[email protected]> Committed: Thu Oct 30 12:31:00 2014 -0700 ---------------------------------------------------------------------- CHANGES | 3 + cmd/Makefile.am | 3 +- cmd/traffic_line/traffic_line.cc | 220 --------------- cmd/traffic_via/Makefile.am | 34 +++ cmd/traffic_via/traffic_via.cc | 348 ++++++++++++++++++++++++ configure.ac | 1 + doc/manpages.py | 1 + doc/reference/commands/index.en.rst | 1 + doc/reference/commands/traffic_line.en.rst | 5 - doc/reference/commands/traffic_via.en.rst | 90 ++++++ lib/ts/ink_args.cc | 33 ++- 11 files changed, 504 insertions(+), 235 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/63757db5/CHANGES ---------------------------------------------------------------------- diff --git a/CHANGES b/CHANGES index 0f44cc4..73b576d 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes with Apache Traffic Server 5.2.0 + *) [TS-3149] Move Via decode out of traffic_line and make a separate tool. + Author: Meera Mosale Nataraja <[email protected]> + *) [TS-3151] Added an extra check for background fills to avoid crash. *) [TS-3119] Add SO_LINGER socket option support. http://git-wip-us.apache.org/repos/asf/trafficserver/blob/63757db5/cmd/Makefile.am ---------------------------------------------------------------------- diff --git a/cmd/Makefile.am b/cmd/Makefile.am index 764e18b..80a13e2 100644 --- a/cmd/Makefile.am +++ b/cmd/Makefile.am @@ -20,4 +20,5 @@ SUBDIRS = \ traffic_layout \ traffic_line \ traffic_manager \ - traffic_top + traffic_top \ + traffic_via http://git-wip-us.apache.org/repos/asf/trafficserver/blob/63757db5/cmd/traffic_line/traffic_line.cc ---------------------------------------------------------------------- diff --git a/cmd/traffic_line/traffic_line.cc b/cmd/traffic_line/traffic_line.cc index 73ef29b..f998730 100644 --- a/cmd/traffic_line/traffic_line.cc +++ b/cmd/traffic_line/traffic_line.cc @@ -52,220 +52,6 @@ static int ShowAlarms; static int ShowStatus; static int ShowBacktrace; static char ClearAlarms[1024]; -static char viaHeader[1024]; - -struct VIA -{ - VIA() : title(NULL), next(NULL) { } - VIA(const char * t) : title(t), next(NULL) { } - - ~VIA() { - delete next; - } - - const char * title; - const char * viaData[128]; - VIA * next; -}; - -//Function to get via header table for every field/category in the via header -static VIA * -detailViaLookup(char flag) -{ - VIA * viaTable = NULL; - - //Detailed via codes after ":" - switch (flag) { - case 't': - viaTable = new VIA("Tunnel info"); - viaTable->viaData[(unsigned char) ' '] = "no tunneling"; - viaTable->viaData[(unsigned char) 'U'] = "tunneling because of url (url suggests dynamic content)"; - viaTable->viaData[(unsigned char) 'M'] = "tunneling due to a method (e.g. CONNECT)"; - viaTable->viaData[(unsigned char) 'O'] = "tunneling because cache is turned off"; - viaTable->viaData[(unsigned char) 'F'] = "tunneling due to a header field (such as presence of If-Range header)"; - break; - case 'c': - //Cache type - viaTable = new VIA( "Cache Type"); - viaTable->viaData[(unsigned char) 'C'] = "cache"; - viaTable->viaData[(unsigned char) 'L'] = "cluster, (not used)"; - viaTable->viaData[(unsigned char) 'I'] = "icp"; - viaTable->viaData[(unsigned char) ' '] = "unknown"; - - //Cache Lookup Result - viaTable->next = new VIA("Cache Lookup Result"); - viaTable->next->viaData[(unsigned char) 'C'] = "cache hit but config forces revalidate"; - viaTable->next->viaData[(unsigned char) 'I'] = "conditional miss (client sent conditional, fresh in cache, returned 412)"; - viaTable->next->viaData[(unsigned char) ' '] = "cache miss or no cache lookup"; - viaTable->next->viaData[(unsigned char) 'U'] = "cache hit, but client forces revalidate (e.g. Pragma: no-cache)"; - viaTable->next->viaData[(unsigned char) 'D'] = "cache hit, but method forces revalidated (e.g. ftp, not anonymous)"; - viaTable->next->viaData[(unsigned char) 'M'] = "cache miss (url not in cache)"; - viaTable->next->viaData[(unsigned char) 'N'] = "conditional hit (client sent conditional, doc fresh in cache, returned 304)"; - viaTable->next->viaData[(unsigned char) 'H'] = "cache hit"; - viaTable->next->viaData[(unsigned char) 'S'] = "cache hit, but expired"; - break; - case 'i': - viaTable = new VIA("ICP status"); - viaTable->viaData[(unsigned char) ' '] = "no icp"; - viaTable->viaData[(unsigned char) 'S'] = "connection opened successfully"; - viaTable->viaData[(unsigned char) 'F'] = "connection open failed"; - break; - case 'p': - viaTable = new VIA("Parent proxy connection status"); - viaTable->viaData[(unsigned char) ' '] = "no parent proxy or unknown"; - viaTable->viaData[(unsigned char) 'S'] = "connection opened successfully"; - viaTable->viaData[(unsigned char) 'F'] = "connection open failed"; - break; - case 's': - viaTable = new VIA("Origin server connection status"); - viaTable->viaData[(unsigned char) ' '] = "no server connection needed"; - viaTable->viaData[(unsigned char) 'S'] = "connection opened successfully"; - viaTable->viaData[(unsigned char) 'F'] = "connection open failed"; - break; - default: - fprintf(stderr, "%s: %s: %c\n", program_name, "Invalid VIA header character",flag); - break; - } - return viaTable; -} - -//Function to get via header table for every field/category in the via header -static VIA * -standardViaLookup(char flag) -{ - VIA * viaTable; - - //Via codes before ":" - switch (flag) { - case 'u': - viaTable = new VIA("Request headers received from client"); - viaTable->viaData[(unsigned char) 'C'] = "cookie"; - viaTable->viaData[(unsigned char) 'E'] = "error in request"; - viaTable->viaData[(unsigned char) 'S'] = "simple request (not conditional)"; - viaTable->viaData[(unsigned char) 'N'] = "no-cache"; - viaTable->viaData[(unsigned char) 'I'] = "IMS"; - viaTable->viaData[(unsigned char) ' '] = "unknown"; - break; - case 'c': - viaTable = new VIA( "Result of Traffic Server cache lookup for URL"); - viaTable->viaData[(unsigned char) 'A'] = "in cache, not acceptable (a cache \"MISS\")"; - viaTable->viaData[(unsigned char) 'H'] = "in cache, fresh (a cache \"HIT\")"; - viaTable->viaData[(unsigned char) 'S'] = "in cache, stale (a cache \"MISS\")"; - viaTable->viaData[(unsigned char) 'R'] = "in cache, fresh Ram hit (a cache \"HIT\")"; - viaTable->viaData[(unsigned char) 'M'] = "miss (a cache \"MISS\")"; - viaTable->viaData[(unsigned char) ' '] = "no cache lookup"; - break; - case 's': - viaTable = new VIA("Response information received from origin server"); - viaTable->viaData[(unsigned char) 'E'] = "error in response"; - viaTable->viaData[(unsigned char) 'S'] = "connection opened successfully"; - viaTable->viaData[(unsigned char) 'N'] = "not-modified"; - viaTable->viaData[(unsigned char) ' '] = "no server connection needed"; - break; - case 'f': - viaTable = new VIA("Result of document write-to-cache:"); - viaTable->viaData[(unsigned char) 'U'] = "updated old cache copy"; - viaTable->viaData[(unsigned char) 'D'] = "cached copy deleted"; - viaTable->viaData[(unsigned char) 'W'] = "written into cache (new copy)"; - viaTable->viaData[(unsigned char) ' '] = "no cache write performed"; - break; - case 'p': - viaTable = new VIA("Proxy operation result"); - viaTable->viaData[(unsigned char) 'R'] = "origin server revalidated"; - viaTable->viaData[(unsigned char) ' '] = "unknown"; - viaTable->viaData[(unsigned char) 'S'] = "served or connection opened successfully"; - viaTable->viaData[(unsigned char) 'N'] = "not-modified"; - break; - case 'e': - viaTable = new VIA("Error codes (if any)"); - viaTable->viaData[(unsigned char) 'A'] = "authorization failure"; - viaTable->viaData[(unsigned char) 'H'] = "header syntax unacceptable"; - viaTable->viaData[(unsigned char) 'C'] = "connection to server failed"; - viaTable->viaData[(unsigned char) 'T'] = "connection timed out"; - viaTable->viaData[(unsigned char) 'S'] = "server related error"; - viaTable->viaData[(unsigned char) 'D'] = "dns failure"; - viaTable->viaData[(unsigned char) 'N'] = "no error"; - viaTable->viaData[(unsigned char) 'F'] = "request forbidden"; - viaTable->viaData[(unsigned char) ' '] = "unknown"; - break; - default: - viaTable = new VIA(); - fprintf(stderr, "%s: %s: %c\n", program_name, "Invalid VIA header character",flag); - break; - } - return viaTable; -} - -//Function to print via header -static void -printViaHeader(const char * header) -{ - VIA * viaTable = NULL; - VIA * viaEntry = NULL; - bool isDetail = false; - - printf("Via Header Details:\n"); - - //Loop through input via header flags - for (const char * c = header; *c; ++c) { - - if (*c == ':') { - isDetail = true; - continue; - } - - if (islower(*c)) { - //Get the via header table - delete viaTable; - viaEntry = viaTable = isDetail ? detailViaLookup(*c) : standardViaLookup(*c); - } else { - // This is a one of the sequence of (uppercase) VIA codes. - if (viaEntry) { - printf("%-55s:", viaEntry->title); - printf("%s\n", viaEntry->viaData[(unsigned char)*c]); - viaEntry = viaEntry->next; - } - } - } - - delete viaTable; -} - -//Check validity of via header and then decode it -static TSMgmtError -decodeViaHeader(char * Via) -{ - size_t viaHdrLength = strlen(Via); - -#ifdef DEBUG - printf("Via header is %s, Length is %zu\n",Via, viaHdrLength); -#endif - - // Via header inside square brackets ... - if (viaHdrLength > 2 && Via[0] == '[' && Via[viaHdrLength - 1] == ']') { - viaHdrLength = viaHdrLength - 2; - Via++; - Via[viaHdrLength] = '\0'; //null terminate the string after trimming - } - - if (viaHdrLength == 24 || viaHdrLength == 6) { - //Decode via header - printViaHeader(Via); - return TS_ERR_OKAY; - } - - // Be kind to people who did not quote the via argument correctly - // by appending one space character before decoding via header. - if (viaHdrLength == 23 || viaHdrLength == 5) { - Via = strcat(Via, " "); - printViaHeader(Via); - return TS_ERR_OKAY; - } - - printf("\nInvalid VIA header. VIA header length should be 6 or 24 characters\n"); - printf("Valid via header format is [u<client-stuff>c<cache-lookup-stuff>s<server-stuff>f<cache-fill-stuff>p<proxy-stuff>]e<error-codes>:t<tunneling-info>c<cache type><cache-lookup-result>i<icp-conn-info>p<parent-proxy-conn-info>s<server-conn-info>]"); - return TS_ERR_FAIL; -} static TSMgmtError handleArgInvocation() @@ -507,10 +293,6 @@ handleArgInvocation() } else if (*VarValue != '\0') { // We have a value but no variable to set fprintf(stderr, "%s: Must specify variable to set with -s when using -v\n", program_name); return TS_ERR_FAIL; - } else if (*viaHeader != '\0') { // Read via header and decode - TSMgmtError rc; - rc = decodeViaHeader(viaHeader); - return rc; } fprintf(stderr, "%s: No arguments specified\n", program_name); @@ -548,7 +330,6 @@ main(int /* argc ATS_UNUSED */, char **argv) ShowAlarms = 0; ShowStatus = 0; ClearAlarms[0] = '\0'; - viaHeader[0] = '\0'; /* Argument description table used to describe how to parse command line args, */ /* see 'ink_args.h' for meanings of the various fields */ @@ -574,7 +355,6 @@ main(int /* argc ATS_UNUSED */, char **argv) {"clear_alarms", '-', "Clear specified, or all, alarms", "S1024", &ClearAlarms, NULL, NULL}, {"status", '-', "Show proxy server status", "F", &ShowStatus, NULL, NULL}, {"backtrace", '-', "Show proxy stack backtrace", "F", &ShowBacktrace, NULL, NULL}, - {"decode_via", '-', "Decode Via Header", "S1024", &viaHeader, NULL, NULL}, HELP_ARGUMENT_DESCRIPTION(), VERSION_ARGUMENT_DESCRIPTION() }; http://git-wip-us.apache.org/repos/asf/trafficserver/blob/63757db5/cmd/traffic_via/Makefile.am ---------------------------------------------------------------------- diff --git a/cmd/traffic_via/Makefile.am b/cmd/traffic_via/Makefile.am new file mode 100644 index 0000000..c9482e2 --- /dev/null +++ b/cmd/traffic_via/Makefile.am @@ -0,0 +1,34 @@ +# +# Makefile.am for the Enterprise Management module. +# +# 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 = \ + $(iocore_include_dirs) \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/lib/ts \ + -I$(top_srcdir)/mgmt/api/include + +bin_PROGRAMS = traffic_via + +traffic_via_SOURCES = \ + traffic_via.cc + +traffic_via_LDFLAGS = @EXTRA_CXX_LDFLAGS@ @LIBTOOL_LINK_FLAGS@ +traffic_via_LDADD = \ + $(top_builddir)/lib/ts/libtsutil.la \ + @LIBTCL@ http://git-wip-us.apache.org/repos/asf/trafficserver/blob/63757db5/cmd/traffic_via/traffic_via.cc ---------------------------------------------------------------------- diff --git a/cmd/traffic_via/traffic_via.cc b/cmd/traffic_via/traffic_via.cc new file mode 100644 index 0000000..1321f1e --- /dev/null +++ b/cmd/traffic_via/traffic_via.cc @@ -0,0 +1,348 @@ +/** @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 "libts.h" + +#include "ink_args.h" +#include "I_Version.h" +#include "Tokenizer.h" +#include "TextBuffer.h" +#include "mgmtapi.h" +#include <stdio.h> +#include <string.h> +#include "Regex.h" + +/// XXX Use DFA or Regex wrappers? +#ifdef HAVE_PCRE_PCRE_H +#include <pcre/pcre.h> +#else +#include <pcre.h> +#endif + +#define SUBSTRING_VECTOR_COUNT 30 //Should be multiple of 3 + +static AppVersionInfo appVersionInfo; + +struct VIA +{ + VIA() : title(NULL), next(NULL) { } + VIA(const char * t) : title(t), next(NULL) { } + + ~VIA() { + delete next; + } + + const char * title; + const char * viaData[128]; + VIA * next; +}; + +//Function to get via header table for every field/category in the via header +static VIA * +detailViaLookup(char flag) +{ + VIA * viaTable = new VIA(); + + //Detailed via codes after ":" + switch (flag) { + case 't': + viaTable = new VIA("Tunnel info"); + viaTable->viaData[(unsigned char) ' '] = "no tunneling"; + viaTable->viaData[(unsigned char) 'U'] = "tunneling because of url (url suggests dynamic content)"; + viaTable->viaData[(unsigned char) 'M'] = "tunneling due to a method (e.g. CONNECT)"; + viaTable->viaData[(unsigned char) 'O'] = "tunneling because cache is turned off"; + viaTable->viaData[(unsigned char) 'F'] = "tunneling due to a header field (such as presence of If-Range header)"; + viaTable->viaData[(unsigned char) 'N'] = "tunneling due to no forward"; + viaTable->viaData[(unsigned char) 'A'] = "tunnel authorization"; + break; + case 'c': + //Cache type + viaTable = new VIA( "Cache Type"); + viaTable->viaData[(unsigned char) 'C'] = "cache"; + viaTable->viaData[(unsigned char) 'L'] = "cluster, (not used)"; + viaTable->viaData[(unsigned char) 'I'] = "icp"; + viaTable->viaData[(unsigned char) 'P'] = "parent"; + viaTable->viaData[(unsigned char) 'S'] = "server"; + viaTable->viaData[(unsigned char) ' '] = "unknown"; + + //Cache Lookup Result + viaTable->next = new VIA("Cache Lookup Result"); + viaTable->next->viaData[(unsigned char) 'C'] = "cache hit but config forces revalidate"; + viaTable->next->viaData[(unsigned char) 'I'] = "conditional miss (client sent conditional, fresh in cache, returned 412)"; + viaTable->next->viaData[(unsigned char) ' '] = "cache miss or no cache lookup"; + viaTable->next->viaData[(unsigned char) 'U'] = "cache hit, but client forces revalidate (e.g. Pragma: no-cache)"; + viaTable->next->viaData[(unsigned char) 'D'] = "cache hit, but method forces revalidated (e.g. ftp, not anonymous)"; + viaTable->next->viaData[(unsigned char) 'M'] = "cache miss (url not in cache)"; + viaTable->next->viaData[(unsigned char) 'N'] = "conditional hit (client sent conditional, doc fresh in cache, returned 304)"; + viaTable->next->viaData[(unsigned char) 'H'] = "cache hit"; + viaTable->next->viaData[(unsigned char) 'S'] = "cache hit, but expired"; + viaTable->next->viaData[(unsigned char) 'K'] = "cookie miss"; + break; + case 'i': + viaTable = new VIA("ICP status"); + viaTable->viaData[(unsigned char) ' '] = "no icp"; + viaTable->viaData[(unsigned char) 'S'] = "connection opened successfully"; + viaTable->viaData[(unsigned char) 'F'] = "connection open failed"; + break; + case 'p': + viaTable = new VIA("Parent proxy connection status"); + viaTable->viaData[(unsigned char) ' '] = "no parent proxy or unknown"; + viaTable->viaData[(unsigned char) 'S'] = "connection opened successfully"; + viaTable->viaData[(unsigned char) 'F'] = "connection open failed"; + break; + case 's': + viaTable = new VIA("Origin server connection status"); + viaTable->viaData[(unsigned char) ' '] = "no server connection needed"; + viaTable->viaData[(unsigned char) 'S'] = "connection opened successfully"; + viaTable->viaData[(unsigned char) 'F'] = "connection open failed"; + break; + default: + fprintf(stderr, "%s: %s: %c\n", appVersionInfo.AppStr, "Invalid VIA header character",flag); + break; + } + return viaTable; +} + +//Function to get via header table for every field/category in the via header +static VIA * +standardViaLookup(char flag) +{ + VIA * viaTable; + + viaTable = new VIA(); + + //Via codes before ":" + switch (flag) { + case 'u': + viaTable = new VIA("Request headers received from client"); + viaTable->viaData[(unsigned char) 'C'] = "cookie"; + viaTable->viaData[(unsigned char) 'E'] = "error in request"; + viaTable->viaData[(unsigned char) 'S'] = "simple request (not conditional)"; + viaTable->viaData[(unsigned char) 'N'] = "no-cache"; + viaTable->viaData[(unsigned char) 'I'] = "IMS"; + viaTable->viaData[(unsigned char) ' '] = "unknown"; + break; + case 'c': + viaTable = new VIA( "Result of Traffic Server cache lookup for URL"); + viaTable->viaData[(unsigned char) 'A'] = "in cache, not acceptable (a cache \"MISS\")"; + viaTable->viaData[(unsigned char) 'H'] = "in cache, fresh (a cache \"HIT\")"; + viaTable->viaData[(unsigned char) 'S'] = "in cache, stale (a cache \"MISS\")"; + viaTable->viaData[(unsigned char) 'R'] = "in cache, fresh Ram hit (a cache \"HIT\")"; + viaTable->viaData[(unsigned char) 'M'] = "miss (a cache \"MISS\")"; + viaTable->viaData[(unsigned char) ' '] = "no cache lookup"; + break; + case 's': + viaTable = new VIA("Response information received from origin server"); + viaTable->viaData[(unsigned char) 'E'] = "error in response"; + viaTable->viaData[(unsigned char) 'S'] = "connection opened successfully"; + viaTable->viaData[(unsigned char) 'N'] = "not-modified"; + viaTable->viaData[(unsigned char) ' '] = "no server connection needed"; + break; + case 'f': + viaTable = new VIA("Result of document write-to-cache:"); + viaTable->viaData[(unsigned char) 'U'] = "updated old cache copy"; + viaTable->viaData[(unsigned char) 'D'] = "cached copy deleted"; + viaTable->viaData[(unsigned char) 'W'] = "written into cache (new copy)"; + viaTable->viaData[(unsigned char) ' '] = "no cache write performed"; + break; + case 'p': + viaTable = new VIA("Proxy operation result"); + viaTable->viaData[(unsigned char) 'R'] = "origin server revalidated"; + viaTable->viaData[(unsigned char) ' '] = "unknown"; + viaTable->viaData[(unsigned char) 'S'] = "served or connection opened successfully"; + viaTable->viaData[(unsigned char) 'N'] = "not-modified"; + break; + case 'e': + viaTable = new VIA("Error codes (if any)"); + viaTable->viaData[(unsigned char) 'A'] = "authorization failure"; + viaTable->viaData[(unsigned char) 'H'] = "header syntax unacceptable"; + viaTable->viaData[(unsigned char) 'C'] = "connection to server failed"; + viaTable->viaData[(unsigned char) 'T'] = "connection timed out"; + viaTable->viaData[(unsigned char) 'S'] = "server related error"; + viaTable->viaData[(unsigned char) 'D'] = "dns failure"; + viaTable->viaData[(unsigned char) 'N'] = "no error"; + viaTable->viaData[(unsigned char) 'F'] = "request forbidden"; + viaTable->viaData[(unsigned char) 'R'] = "cache read error"; + viaTable->viaData[(unsigned char) ' '] = "unknown"; + break; + default: + fprintf(stderr, "%s: %s: %c\n", appVersionInfo.AppStr, "Invalid VIA header character",flag); + break; + } + return viaTable; +} + +//Function to print via header +static void +printViaHeader(const char * header) +{ + VIA * viaTable = NULL; + VIA * viaEntry = NULL; + bool isDetail = false; + + printf("Via Header Details:\n"); + + //Loop through input via header flags + for (const char * c = header; *c; ++c) { + if (*c == ':') { + isDetail = true; + continue; + } + + if (islower(*c)) { + //Get the via header table + delete viaTable; + viaEntry = viaTable = isDetail ? detailViaLookup(*c) : standardViaLookup(*c); + } else { + // This is a one of the sequence of (uppercase) VIA codes. + if (viaEntry) { + printf("%-55s:", viaEntry->title); + printf("%s\n", viaEntry->viaData[(unsigned char)*c]); + viaEntry = viaEntry->next; + } + } + } + delete viaTable; +} + +//Check validity of via header and then decode it +static TSMgmtError +decodeViaHeader(const char * str) +{ + size_t viaHdrLength; + ats_scoped_str tmp(strdup(str)); + char * Via = &tmp[0]; + + viaHdrLength = strlen(Via); + printf("Via header is %s, Length is %zu\n",Via, viaHdrLength); + + //Via header inside square brackets + if (Via[0] == '[' && Via[viaHdrLength-1] == ']') { + viaHdrLength = viaHdrLength - 2; + Via++; + Via[viaHdrLength] = '\0'; //null terminate the string after trimming + } + + if (viaHdrLength == 24 || viaHdrLength == 6) { + //Decode via header + printViaHeader(Via); + return TS_ERR_OKAY; + } else if(viaHdrLength == 5) { + Via = strcat(Via," "); //Add one space character before decoding via header + printViaHeader(Via); + return TS_ERR_OKAY; + } + //Invalid header size, come out. + printf("\nInvalid VIA header. VIA header length should be 6 or 24 characters\n"); + printf("Valid via header format is [u<client-stuff>c<cache-lookup-stuff>s<server-stuff>f<cache-fill-stuff>p<proxy-stuff>]e<error-codes>:t<tunneling-info>c<cache type><cache-lookup-result>i<icp-conn-info>p<parent-proxy-conn-info>s<server-conn-info>]"); + return TS_ERR_FAIL; +} + +//Read user input from stdin +static TSMgmtError +filterViaHeader() +{ + const pcre *compiledReg; + const pcre_extra *extraReg = NULL; + int subStringVector[SUBSTRING_VECTOR_COUNT]; + const char *err; + int errOffset; + int pcreExecCode; + int i; + const char *viaPattern = "\\[([ucsfpe]+[^\\]]+)\\]"; //Regex to match via header with in [] which can start with character class ucsfpe + char *viaHeaderString; + char viaHeader[1024]; + + //Compile PCRE via header pattern + compiledReg = pcre_compile(viaPattern, 0, &err, &errOffset, NULL); + + if (compiledReg == NULL) { + printf("PCRE regex compilation failed with error %s at offset %d\n", err, errOffset); + return TS_ERR_FAIL; + } + + //Read all lines from stdin + while (fgets(viaHeader, sizeof(viaHeader), stdin)) { + //Trim new line character and null terminate it + char* newLinePtr = strchr(viaHeader, '\n'); + if (newLinePtr) { + *newLinePtr = '\0'; + } + //Match for via header pattern + pcreExecCode = pcre_exec(compiledReg, extraReg, viaHeader, (int)sizeof(viaHeader), 0, 0, subStringVector, SUBSTRING_VECTOR_COUNT); + + //Match failed, don't worry. Continue to next line. + if (pcreExecCode < 0) continue; + + //Match successful, but too many substrings + if (pcreExecCode == 0) { + pcreExecCode = SUBSTRING_VECTOR_COUNT/3; + printf("Too many substrings were found. %d substrings couldn't fit into subStringVector\n", pcreExecCode - 1); + } + + //Loop based on number of matches found + for (i = 1; i < pcreExecCode; i++) { + //Point to beginning of matched substring + char *subStringBegin = viaHeader + subStringVector[2*i]; + //Get length of matched substring + int subStringLen = subStringVector[2*i+1] - subStringVector[2*i]; + viaHeaderString = subStringBegin; + sprintf(viaHeaderString, "%.*s", subStringLen, subStringBegin); + //Decode matched substring + decodeViaHeader(viaHeaderString); + } + } + return TS_ERR_OKAY; +} + +int +main(int /* argc ATS_UNUSED */, char **argv) +{ + TSMgmtError status; + + // build the application information structure + appVersionInfo.setup(PACKAGE_NAME, "traffic_via", PACKAGE_VERSION, __DATE__, __TIME__, BUILD_MACHINE, BUILD_PERSON, ""); + + /* see 'ink_args.h' for meanings of the various fields */ + ArgumentDescription argument_descriptions[] = { + VERSION_ARGUMENT_DESCRIPTION(), + HELP_ARGUMENT_DESCRIPTION(), + }; + + process_args(&appVersionInfo, argument_descriptions, countof(argument_descriptions), argv); + + for (unsigned i = 0; i < n_file_arguments; ++i) { + if (strcmp(file_arguments[i], "-") == 0) { + // Filter arguments provided from stdin + status = filterViaHeader(); + } else { + status = decodeViaHeader(file_arguments[i]); + } + + if (status != TS_ERR_OKAY) { + return 1; + } + } + + return 0; +} http://git-wip-us.apache.org/repos/asf/trafficserver/blob/63757db5/configure.ac ---------------------------------------------------------------------- diff --git a/configure.ac b/configure.ac index 7bf4b6f..770d7f1 100644 --- a/configure.ac +++ b/configure.ac @@ -1856,6 +1856,7 @@ AC_CONFIG_FILES([ cmd/traffic_line/Makefile cmd/traffic_manager/Makefile cmd/traffic_top/Makefile + cmd/traffic_via/Makefile doc/Makefile example/Makefile iocore/Makefile http://git-wip-us.apache.org/repos/asf/trafficserver/blob/63757db5/doc/manpages.py ---------------------------------------------------------------------- diff --git a/doc/manpages.py b/doc/manpages.py index bbaabf0..ca6b6e8 100644 --- a/doc/manpages.py +++ b/doc/manpages.py @@ -31,6 +31,7 @@ man_pages = [ ('reference/commands/tspush.en', 'tspush', u'Push objects into the Traffic Server cache', None, '1'), ('reference/commands/traffic_top.en','traffic_top', u'Display Traffic Server statistics', None, '1'), ('reference/commands/tsxs.en', 'tsxs', u'Traffic Server plugin tool', None, '1'), + ('reference/commands/traffic_via.en', 'traffic_via', u'Traffic Server Via header decoder', None, '1'), ('reference/configuration/cache.config.en', 'cache.config', u'Traffic Server cache configuration file', None, '5'), ('reference/configuration/congestion.config.en', 'congestion.config', u'Traffic Server congestion control configuration file', None, '5'), http://git-wip-us.apache.org/repos/asf/trafficserver/blob/63757db5/doc/reference/commands/index.en.rst ---------------------------------------------------------------------- diff --git a/doc/reference/commands/index.en.rst b/doc/reference/commands/index.en.rst index f8681cf..6f42d65 100644 --- a/doc/reference/commands/index.en.rst +++ b/doc/reference/commands/index.en.rst @@ -28,5 +28,6 @@ Command Reference traffic_manager.en traffic_server.en traffic_top.en + traffic_via.en tspush.en tsxs.en http://git-wip-us.apache.org/repos/asf/trafficserver/blob/63757db5/doc/reference/commands/traffic_line.en.rst ---------------------------------------------------------------------- diff --git a/doc/reference/commands/traffic_line.en.rst b/doc/reference/commands/traffic_line.en.rst index 18238e8..2b6791e 100644 --- a/doc/reference/commands/traffic_line.en.rst +++ b/doc/reference/commands/traffic_line.en.rst @@ -139,11 +139,6 @@ Options Show the current proxy server status, indicating if we're running or not. -.. option:: --decode_via VAR - - Decode Via Header and provide detailed explaination of the fields. The value of Via header is given by variable VAR. - Via header can be given within [] or without [] - .. _traffic-line-performance-statistics: Performance Statistics http://git-wip-us.apache.org/repos/asf/trafficserver/blob/63757db5/doc/reference/commands/traffic_via.en.rst ---------------------------------------------------------------------- diff --git a/doc/reference/commands/traffic_via.en.rst b/doc/reference/commands/traffic_via.en.rst new file mode 100644 index 0000000..94a82fd --- /dev/null +++ b/doc/reference/commands/traffic_via.en.rst @@ -0,0 +1,90 @@ +.. 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. + +.. _traffic_via: + +============ +traffic_via +============ + +Synopsis +======== + +:program:`traffic_via` [OPTIONS] [VIA ...] + +.. program:: traffic_via + +Description +=========== + +:program:`traffic_via` decodes the Traffic Server Via header codes. +Via header strings are passed as command-line options. The enclosing +square brackets are optional. + +If the argument is '-', :program:`traffic_via` will filter standard +input for Via headers. This modes supports only supports Via headers +taht are enclosed by square brackets. + +Options +======= + +.. option:: -h, --help + + Print usage information and exit. + +.. option:: -V, --version + + Print version. + +Examples +======== + +Decode the Via header from command-line arguments:: + + $ traffic_via "[uScMsEf p eC:t cCMi p sF]" + Via header is uScMsEf p eC:t cCMi p sF, Length is 24 + Via Header Details: + Request headers received from client :simple request (not conditional) + Result of Traffic Server cache lookup for URL :miss (a cache "MISS") + Response information received from origin server :error in response + Result of document write-to-cache: :no cache write performed + Proxy operation result :unknown + Error codes (if any) :connection to server failed + Tunnel info :no tunneling + Cache Type :cache + Cache Lookup Result :cache miss (url not in cache) + ICP status :no icp + Parent proxy connection status :no parent proxy or unknown + Origin server connection status :connection open failed + +Decode the Via header from a curl request, using the :ref:`X-Debug <_xdebug_plugin>` plugin:: + + $ curl -H "X-Debug: Via" -I http://test.example.com | traffic_via - + Via header is uScMsSf pSeN:t cCMi p sS, Length is 24 + Via Header Details: + Request headers received from client :simple request (not conditional) + Result of Traffic Server cache lookup for URL :miss (a cache "MISS") + Response information received from origin server :connection opened successfully + Result of document write-to-cache: :no cache write performed + Proxy operation result :served or connection opened successfully + Error codes (if any) :no error + Tunnel info :no tunneling + Cache Type :cache + Cache Lookup Result :cache miss (url not in cache) + ICP status :no icp + Parent proxy connection status :no parent proxy or unknown + Origin server connection status :connection opened successfully http://git-wip-us.apache.org/repos/asf/trafficserver/blob/63757db5/lib/ts/ink_args.cc ---------------------------------------------------------------------- diff --git a/lib/ts/ink_args.cc b/lib/ts/ink_args.cc index 97f5f1b..cf2caf0 100644 --- a/lib/ts/ink_args.cc +++ b/lib/ts/ink_args.cc @@ -63,6 +63,16 @@ arg_is_version_flag(const ArgumentDescription * arg) } static void +append_file_argument(const char * arg) +{ + if (n_file_arguments >= countof(file_arguments)) { + ink_fatal(1, "too many files"); + } + file_arguments[n_file_arguments++] = arg; + file_arguments[n_file_arguments] = NULL; +} + +static void process_arg(const AppVersionInfo * appinfo, const ArgumentDescription * argument_descriptions, unsigned n_argument_descriptions, int i, char ***argv, const char *usage_string) { @@ -193,22 +203,27 @@ process_args(const AppVersionInfo * appinfo, const ArgumentDescription * argumen if (i >= n_argument_descriptions) usage(argument_descriptions, n_argument_descriptions, usage_string); } else { - while (*++(*argv)) - for (i = 0; i < n_argument_descriptions; i++) + // Hack for supporting '-' as a file argument. + if (strcmp(*argv, "-") == 0) { + append_file_argument(*argv); + } + + while (*++(*argv)) { + for (i = 0; i < n_argument_descriptions; i++) { + printf("i=%d **argv=%c\n", i, **argv); if (argument_descriptions[i].key == **argv) { process_arg(appinfo, argument_descriptions, n_argument_descriptions, i, &argv, usage_string); break; } - if (i >= n_argument_descriptions) { - usage(argument_descriptions, n_argument_descriptions, usage_string); + } + + if (i >= n_argument_descriptions) { + usage(argument_descriptions, n_argument_descriptions, usage_string); + } } } } else { - if (n_file_arguments >= countof(file_arguments)) { - ink_fatal(1, "too many files"); - } - file_arguments[n_file_arguments++] = *argv; - file_arguments[n_file_arguments] = NULL; + append_file_argument(*argv); } } }
