You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by am...@apache.org on 2011/02/25 03:39:28 UTC
svn commit: r1074382 - in /trafficserver/traffic/trunk:
lib/tsconfig/TsBuffer.h proxy/CacheControl.cc proxy/ControlBase.cc
proxy/ControlBase.h proxy/ControlMatcher.cc proxy/Makefile.am
proxy/ParentSelection.cc
Author: amc
Date: Fri Feb 25 02:39:27 2011
New Revision: 1074382
URL: http://svn.apache.org/viewvc?rev=1074382&view=rev
Log:
TS-674
Modified:
trafficserver/traffic/trunk/lib/tsconfig/TsBuffer.h
trafficserver/traffic/trunk/proxy/CacheControl.cc
trafficserver/traffic/trunk/proxy/ControlBase.cc
trafficserver/traffic/trunk/proxy/ControlBase.h
trafficserver/traffic/trunk/proxy/ControlMatcher.cc
trafficserver/traffic/trunk/proxy/Makefile.am
trafficserver/traffic/trunk/proxy/ParentSelection.cc
Modified: trafficserver/traffic/trunk/lib/tsconfig/TsBuffer.h
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/lib/tsconfig/TsBuffer.h?rev=1074382&r1=1074381&r2=1074382&view=diff
==============================================================================
--- trafficserver/traffic/trunk/lib/tsconfig/TsBuffer.h (original)
+++ trafficserver/traffic/trunk/lib/tsconfig/TsBuffer.h Fri Feb 25 02:39:27 2011
@@ -71,6 +71,14 @@ namespace ts {
*/
bool operator != (ConstBuffer const& that) const;
+ /// @name Accessors.
+ //@{
+ /// Get the data in the buffer.
+ char* data() const;
+ /// Get the size of the buffer.
+ size_t size() const;
+ //@}
+
/// Set the chunk.
/// Any previous values are discarded.
/// @return @c this object.
@@ -130,6 +138,14 @@ namespace ts {
Buffer const& that ///< Source buffer.
);
+ /// @name Accessors.
+ //@{
+ /// Get the data in the buffer.
+ char const * data() const;
+ /// Get the size of the buffer.
+ size_t size() const;
+ //@}
+
/// Set the chunk.
/// Any previous values are discarded.
/// @return @c this object.
@@ -156,6 +172,8 @@ namespace ts {
inline bool Buffer::operator == (ConstBuffer const& that) const {
return _size == that._size && 0 == memcmp(_ptr, that._ptr, _size);
}
+ inline char * Buffer::data() const { return _ptr; }
+ inline size_t Buffer::size() const { return _size; }
inline ConstBuffer::ConstBuffer() { }
inline ConstBuffer::ConstBuffer(char const* ptr, size_t n) : _ptr(ptr), _size(n) { }
@@ -171,6 +189,8 @@ namespace ts {
inline bool ConstBuffer::operator == (Buffer const& that) const {
return _size == that._size && 0 == memcmp(_ptr, that._ptr, _size);
}
+ inline char const * ConstBuffer::data() const { return _ptr; }
+ inline size_t ConstBuffer::size() const { return _size; }
}
# endif // TS_BUFFER_HEADER
Modified: trafficserver/traffic/trunk/proxy/CacheControl.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/CacheControl.cc?rev=1074382&r1=1074381&r2=1074382&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/CacheControl.cc (original)
+++ trafficserver/traffic/trunk/proxy/CacheControl.cc Fri Feb 25 02:39:27 2011
@@ -234,8 +234,8 @@ CacheControlRecord::Print()
case CC_STANDARD_CACHE:
case CC_IGNORE_NO_CACHE:
// case CC_CACHE_AUTH_CONTENT:
- // printf("\t\tDirective: %s\n", CC_directive_str[this->directive]);
- // break;
+ printf("\t\tDirective: %s\n", CC_directive_str[this->directive]);
+ break;
case CC_INVALID:
case CC_NUM_TYPES:
printf("\t\tDirective: INVALID\n");
Modified: trafficserver/traffic/trunk/proxy/ControlBase.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/ControlBase.cc?rev=1074382&r1=1074381&r2=1074382&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/ControlBase.cc (original)
+++ trafficserver/traffic/trunk/proxy/ControlBase.cc Fri Feb 25 02:39:27 2011
@@ -44,554 +44,575 @@
#include "ControlMatcher.h"
#include "HdrUtils.h"
-// iPort added
-static const char *ModTypeStrings[] = {
- "Modifier Invalid",
- "Port",
- "Scheme",
- "Prefix",
- "Suffix",
- "Method",
- "TimeOfDay",
- "SrcIP",
- "iPort",
- "Tag"
-};
+#include "tsconfig/TsBuffer.h"
-struct timeMod
-{
+/** Used for printing IP address.
+ @code
+ uint32_t addr; // IP address.
+ printf("IP address = " TS_IP_PRINTF_CODE,TS_IP_OCTETS(addr));
+ @endcode
+ @internal Need to move these to a common header.
+ */
+# define TS_IP_OCTETS(x) \
+ reinterpret_cast<unsigned char const*>(&(x))[0], \
+ reinterpret_cast<unsigned char const*>(&(x))[1], \
+ reinterpret_cast<unsigned char const*>(&(x))[2], \
+ reinterpret_cast<unsigned char const*>(&(x))[3]
+
+// ----------
+ControlBase::Modifier::~Modifier() {}
+ControlBase::Modifier::Type ControlBase::Modifier::type() const { return MOD_INVALID; }
+// --------------------------
+namespace {
+// ----------
+struct TimeMod : public ControlBase::Modifier {
time_t start_time;
time_t end_time;
-};
-struct ipMod
-{
- ip_addr_t start_addr;
- ip_addr_t end_addr;
+ static char const * const NAME;
+
+ virtual Type type() const;
+ virtual char const * name() const;
+ virtual bool check(HttpRequestData* req) const;
+ virtual void print(FILE* f) const;
+ static TimeMod* make(char * value, char const ** error);
+ static const char* timeOfDayToSeconds(const char *time_str, time_t * seconds);
};
-struct portMod
-{
+char const * const TimeMod::NAME = "Time";
+ControlBase::Modifier::Type TimeMod::type() const { return MOD_TIME; }
+char const * TimeMod::name() const { return NAME; }
+
+void TimeMod::print(FILE* f) const {
+ fprintf(f, "%s=%ld-%ld ", this->name(), start_time, end_time);
+}
+bool TimeMod::check(HttpRequestData* req) const {
+ struct tm cur_time;
+ time_t timeOfDay = req->xact_start;
+ // Use this to account for daylight savings time.
+ ink_localtime_r(&timeOfDay, &cur_time);
+ timeOfDay = cur_time.tm_hour*(60 * 60) + cur_time.tm_min*60 + cur_time.tm_sec;
+ return start_time <= timeOfDay && timeOfDay <= end_time;
+}
+
+TimeMod*
+TimeMod::make(char * value, char const ** error) {
+ Tokenizer rangeTok("-");
+ TimeMod* mod = 0;
+ TimeMod tmp;
+ int num_tok;
+
+ num_tok = rangeTok.Initialize(value, SHARE_TOKS);
+ if (num_tok == 1) {
+ *error = "End time not specified";
+ } else if (num_tok > 2) {
+ *error = "Malformed time range";
+ } else if (
+ 0 == (*error = timeOfDayToSeconds(rangeTok[0], &tmp.start_time))
+ && 0 == (*error = timeOfDayToSeconds(rangeTok[1], &tmp.end_time))
+ ) {
+ mod = new TimeMod(tmp);
+ }
+ return mod;
+}
+/** Converts TimeOfDay (TOD) to second value.
+ @a *seconds is set to number of seconds since midnight
+ represented by @a time_str.
+
+ @return 0 on success, static error string on failure.
+*/
+const char *
+TimeMod::timeOfDayToSeconds(const char *time_str, time_t * seconds) {
+ int hour = 0;
+ int min = 0;
+ int sec = 0;
+ time_t tmp = 0;
+
+ // coverity[secure_coding]
+ if (sscanf(time_str, "%d:%d:%d", &hour, &min, &sec) != 3) {
+ // coverity[secure_coding]
+ if (sscanf(time_str, "%d:%d", &hour, &min) != 2) {
+ return "Malformed time specified";
+ }
+ }
+
+ if (!(hour >= 0 && hour <= 23)) return "Illegal hour specification";
+
+ tmp = hour * 60;
+
+ if (!(min >= 0 && min <= 59)) return "Illegal minute specification";
+
+ tmp = (tmp + min) * 60;
+
+ if (!(sec >= 0 && sec <= 59)) return "Illegal second specification";
+
+ tmp += sec;
+
+ *seconds = tmp;
+ return 0;
+}
+
+// ----------
+struct PortMod : public ControlBase::Modifier {
int start_port;
int end_port;
+
+ static char const * const NAME;
+
+ virtual char const * name() const;
+ virtual bool check(HttpRequestData* req) const;
+ virtual void print(FILE* f) const;
+
+ static PortMod* make(char* value, char const **error);
};
-ControlBase::~ControlBase()
-{
- int num_el;
-
- if (mod_elements != NULL) {
-
- // Free all Prefix/Postfix strings and
- // SrcIP, Port, Time Of Day Structures
- num_el = (*mod_elements).length() + 1;
- for (intptr_t i = 0; i < num_el; i++) {
- modifier_el & cur_el = (*mod_elements)[i];
- if (cur_el.type == MOD_PREFIX ||
- cur_el.type == MOD_SUFFIX ||
- cur_el.type == MOD_TIME || cur_el.type == MOD_PORT || cur_el.type == MOD_SRC_IP || cur_el.type == MOD_TAG) {
- xfree(cur_el.opaque_data);
- }
- }
+char const * const PortMod::NAME = "Port";
+char const * PortMod::name() const { return NAME; }
+
+void PortMod::print(FILE* f) const {
+ fprintf(f, "%s=%d-%d ", this->name(), start_port, end_port);
+}
+
+bool PortMod::check(HttpRequestData* req) const {
+ int port = req->hdr->port_get();
+ return start_port <= port && port <= end_port;
+}
- delete mod_elements;
+PortMod*
+PortMod::make(char* value, char const ** error) {
+ Tokenizer rangeTok("-");
+ PortMod tmp;
+ int num_tok = rangeTok.Initialize(value, SHARE_TOKS);
+
+ *error = 0;
+ if (num_tok > 2) {
+ *error = "Malformed Range";
+ // coverity[secure_coding]
+ } else if (sscanf(rangeTok[0], "%d", &tmp.start_port) != 1) {
+ *error = "Invalid start port";
+ } else if (num_tok == 2) {
+ // coverity[secure_coding]
+ if (sscanf(rangeTok[1], "%d", &tmp.end_port) != 1)
+ *error = "Invalid end port";
+ else if (tmp.end_port < tmp.start_port)
+ *error = "Malformed Range: end port < start port";
+ } else {
+ tmp.end_port = tmp.start_port;
}
+
+ // If there's an error message, return null.
+ // Otherwise create a new item and return it.
+ return *error ? 0 : new PortMod(tmp);
}
-static const modifier_el default_el = { MOD_INVALID, NULL };
+// ----------
+struct IPortMod : public ControlBase::Modifier {
+ int _port;
+
+ static char const * const NAME;
+
+ IPortMod(int port);
+
+ virtual char const * name() const;
+ virtual bool check(HttpRequestData* req) const;
+ virtual void print(FILE* f) const;
+ static IPortMod* make(char* value, char const ** error);
+};
-void
-ControlBase::Print()
-{
- int num_el;
- struct in_addr a;
- int port;
+char const * const IPortMod::NAME = "IPort";
+IPortMod::IPortMod(int port) : _port(port) {}
+char const * IPortMod::name() const { return NAME; }
- if (mod_elements == NULL) {
- return;
+void IPortMod::print(FILE* f) const {
+ fprintf(f, "%s=%d ", this->name(), _port);
+}
+bool IPortMod::check(HttpRequestData* req) const {
+ return req->incoming_port == _port;
+}
+
+IPortMod*
+IPortMod::make(char* value, char const ** error) {
+ IPortMod* zret = 0;
+ int port;
+ // coverity[secure_coding]
+ if (sscanf(value, "%u", &port) == 1) {
+ zret = new IPortMod(port);
+ } else {
+ *error = "Invalid incoming port";
}
+ return zret;
+}
+// ----------
+struct SrcIPMod : public ControlBase::Modifier {
+ // Stored in host order because that's how they are compared.
+ ip_addr_t start_addr; ///< Start address in HOST order.
+ ip_addr_t end_addr; ///< End address in HOST order.
+
+ static char const * const NAME;
+
+ virtual Type type() const;
+ virtual char const * name() const;
+ virtual bool check(HttpRequestData* req) const;
+ virtual void print(FILE* f) const;
+ static SrcIPMod* make(char * value, char const ** error);
+};
+
+char const * const SrcIPMod::NAME = "SrcIP";
+ControlBase::Modifier::Type SrcIPMod::type() const { return MOD_SRC_IP; }
+char const * SrcIPMod::name() const { return NAME; }
+
+void SrcIPMod::print(FILE* f) const {
+ ip_addr_t a1 = htonl(start_addr);
+ ip_addr_t a2 = htonl(end_addr);
+ fprintf(f, "%s=%d.%d.%d.%d-%d.%d.%d.%d ",
+ this->name(), TS_IP_OCTETS(a1), TS_IP_OCTETS(a2)
+ );
+}
+bool SrcIPMod::check(HttpRequestData* req) const {
+ // Compare in host order
+ uint32_t addr = ntohl(req->src_ip);
+ return start_addr <= addr && addr <= end_addr;
+}
+SrcIPMod*
+SrcIPMod::make(char * value, char const ** error ) {
+ SrcIPMod tmp;
+ SrcIPMod* zret = 0;
+ *error = ExtractIpRange(value, &tmp.start_addr, &tmp.end_addr);
- num_el = (*mod_elements).length();
- if (num_el <= 0) {
- return;
+ if (!*error) zret = new SrcIPMod(tmp);
+ return zret;
+}
+// ----------
+struct SchemeMod : public ControlBase::Modifier {
+ int _scheme; ///< Tokenized scheme.
+
+ static char const * const NAME;
+
+ SchemeMod(int scheme);
+
+ virtual Type type() const;
+ virtual char const * name() const;
+ virtual bool check(HttpRequestData* req) const;
+ virtual void print(FILE* f) const;
+
+ char const* getWksText() const;
+
+ static SchemeMod* make(char * value, char const ** error);
+};
+
+char const * const SchemeMod::NAME = "Scheme";
+
+SchemeMod::SchemeMod(int scheme) : _scheme(scheme) {}
+
+ControlBase::Modifier::Type SchemeMod::type() const { return MOD_SCHEME; }
+char const * SchemeMod::name() const { return NAME; }
+char const *
+SchemeMod::getWksText() const {
+ return hdrtoken_index_to_wks(_scheme);
+}
+
+bool SchemeMod::check(HttpRequestData* req) const {
+ return req->hdr->url_get()->scheme_get_wksidx() == _scheme;
+}
+void SchemeMod::print(FILE* f) const {
+ fprintf(f, "%s=%s ", this->name(), hdrtoken_index_to_wks(_scheme));
+}
+SchemeMod*
+SchemeMod::make(char * value, char const ** error) {
+ SchemeMod* zret = 0;
+ int scheme = hdrtoken_tokenize(value, strlen(value));
+ if (scheme < 0) {
+ *error = "Unknown scheme";
+ } else {
+ zret = new SchemeMod(scheme);
}
+ return zret;
+}
+// ----------
+// This is a base class for all of the mods that have a
+// text string.
+struct TextMod : public ControlBase::Modifier {
+ ts::Buffer text;
+
+ TextMod();
+ ~TextMod();
+
+ // Calls name() which the subclass must provide.
+ virtual void print(FILE* f) const;
+};
+void TextMod::print(FILE* f) const {
+ fprintf(f, "%s=%*s ", this->name(), static_cast<int>(text.size()), text.data());
+}
+
+TextMod::TextMod() : text(0,0) {}
+TextMod::~TextMod() {
+ if (text.data()) free(text.data());
+}
+
+// ----------
+struct MethodMod : public TextMod {
+ static char const * const NAME;
+
+ virtual Type type() const;
+ virtual char const * name() const;
+ virtual bool check(HttpRequestData* req) const;
+
+ static MethodMod* make(char * value, char const ** error);
+};
+char const * const MethodMod::NAME = "Method";
+ControlBase::Modifier::Type MethodMod::type() const { return MOD_METHOD; }
+char const * MethodMod::name() const { return NAME; }
+bool MethodMod::check(HttpRequestData* req) const {
+ int method_len;
+ char const* method = req->hdr->method_get(&method_len);
+ return method_len >= static_cast<int>(text.size())
+ && 0 == strncasecmp(method, text.data(), text.size())
+ ;
+}
+MethodMod*
+MethodMod::make(char * value, char const **) {
+ MethodMod* mod = new MethodMod;
+ mod->text.set(xstrdup(value), strlen(value));
+ return mod;
+}
+
+// ----------
+struct PrefixMod : public TextMod {
+ static char const * const NAME;
+
+ virtual Type type() const;
+ virtual char const * name() const;
+ virtual bool check(HttpRequestData* req) const;
+ static PrefixMod* make(char * value, char const ** error);
+};
+
+char const * const PrefixMod::NAME = "Prefix";
+ControlBase::Modifier::Type PrefixMod::type() const { return MOD_PREFIX; }
+char const * PrefixMod::name() const { return NAME; }
+bool PrefixMod::check(HttpRequestData* req) const {
+ int path_len;
+ char const* path = req->hdr->url_get()->path_get(&path_len);
+ bool zret = path_len >= static_cast<int>(text.size())
+ && 0 == memcmp(path, text.data(), text.size())
+ ;
+/*
+ Debug("cache_control", "Prefix check: URL=%0.*s Mod=%0.*s Z=%s",
+ path_len, path, text.size(), text.data(),
+ zret ? "Match" : "Fail"
+ );
+*/
+ return zret;
+}
+PrefixMod*
+PrefixMod::make(char * value, char const ** error ) {
+ PrefixMod* mod = new PrefixMod;
+ // strip leading slashes because get_path which is used later
+ // doesn't include them from the URL.
+ while ('/' == *value) ++value;
+ mod->text.set(xstrdup(value), strlen(value));
+ return mod;
+}
+// ----------
+struct SuffixMod : public TextMod {
+ static char const * const NAME;
+
+ virtual Type type() const;
+ virtual char const * name() const;
+ virtual bool check(HttpRequestData* req) const;
+ static SuffixMod* make(char * value, char const ** error);
+};
+char const * const SuffixMod::NAME = "Suffix";
+ControlBase::Modifier::Type SuffixMod::type() const { return MOD_SUFFIX; }
+char const * SuffixMod::name() const { return NAME; }
+bool SuffixMod::check(HttpRequestData* req) const {
+ int path_len;
+ char const* path = req->hdr->url_get()->path_get(&path_len);
+ return path_len >= static_cast<int>(text.size())
+ && 0 == strncasecmp(path + path_len - text.size(), text.data(), text.size())
+ ;
+}
+SuffixMod*
+SuffixMod::make(char * value, char const ** error ) {
+ SuffixMod* mod = new SuffixMod;
+ mod->text.set(xstrdup(value), strlen(value));
+ return mod;
+}
+
+// ----------
+struct TagMod : public TextMod {
+ static char const * const NAME;
+
+ virtual Type type() const;
+ virtual char const * name() const;
+ virtual bool check(HttpRequestData* req) const;
+ static TagMod* make(char * value, char const ** error);
+};
+char const * const TagMod::NAME = "Tag";
+ControlBase::Modifier::Type TagMod::type() const { return MOD_TAG; }
+char const * TagMod::name() const { return NAME; }
+bool TagMod::check(HttpRequestData* req) const {
+ return 0 == strcmp(req->tag, text.data());
+}
+TagMod*
+TagMod::make(char * value, char const ** error ) {
+ TagMod* mod = new TagMod;
+ mod->text.set(xstrdup(value), strlen(value));
+ return mod;
+}
+// ----------
+} // anon name space
+// ------------------------------------------------
+ControlBase::~ControlBase() {
+ this->clear();
+}
+
+void
+ControlBase::clear() {
+ line_num = 0;
+ for ( Array::iterator spot = _mods.begin(), limit = _mods.end()
+ ; spot != limit
+ ; ++spot
+ )
+ delete *spot;
+ _mods.clear();
+}
+
+// static const modifier_el default_el = { MOD_INVALID, NULL };
+
+void
+ControlBase::Print() {
+ int n = _mods.size();
+
+ if (0 >= n) return;
printf("\t\t\t");
- for (intptr_t i = 0; i < num_el; i++) {
- modifier_el & cur_el = (*mod_elements)[i];
- switch (cur_el.type) {
- case MOD_INVALID:
- printf("%s ", ModTypeStrings[MOD_INVALID]);
- break;
- case MOD_PORT:
- port = ((portMod *) cur_el.opaque_data)->start_port;
- printf("%s=%d-", ModTypeStrings[MOD_PORT], port);
- port = ((portMod *) cur_el.opaque_data)->end_port;
- printf("%d ", port);
- break;
- case MOD_IPORT:
- printf("%s=%d ", ModTypeStrings[MOD_IPORT], (int) (long) cur_el.opaque_data);
- break;
- case MOD_SCHEME:
- printf("%s=%s ", ModTypeStrings[MOD_SCHEME], (char *) cur_el.opaque_data);
- break;
- case MOD_PREFIX:
- printf("%s=%s ", ModTypeStrings[MOD_PREFIX], (char *) cur_el.opaque_data);
- break;
- case MOD_SUFFIX:
- printf("%s=%s ", ModTypeStrings[MOD_SUFFIX], (char *) cur_el.opaque_data);
- break;
- case MOD_METHOD:
- printf("%s=%s ", ModTypeStrings[MOD_METHOD], (char *) cur_el.opaque_data);
- break;
- case MOD_TAG:
- printf("%s=%s ", ModTypeStrings[MOD_TAG], (char *) cur_el.opaque_data);
- break;
- case MOD_SRC_IP:
- a.s_addr = ((ipMod *) cur_el.opaque_data)->start_addr;
- printf("%s=%s-", ModTypeStrings[MOD_SRC_IP], inet_ntoa(a));
- a.s_addr = ((ipMod *) cur_el.opaque_data)->end_addr;
- printf("%s ", inet_ntoa(a));
- break;
- case MOD_TIME:
- printf("%s=%d-%d ", ModTypeStrings[MOD_TIME],
- (int) ((timeMod *) cur_el.opaque_data)->start_time, (int) ((timeMod *) cur_el.opaque_data)->end_time);
- break;
- }
+ for (intptr_t i = 0; i < n; ++i) {
+ Modifier* cur_mod = _mods[i];
+ if (!cur_mod) printf("INVALID ");
+ else cur_mod->print(stdout);
}
printf("\n");
}
+char const *
+ControlBase::getSchemeModText() const {
+ char const* zret = 0;
+ Modifier* mod = this->findModOfType(Modifier::MOD_SCHEME);
+ if (mod) zret = static_cast<SchemeMod*>(mod)->getWksText();
+ return zret;
+}
+
bool
-ControlBase::CheckModifiers(HttpRequestData * request_data)
-{
+ControlBase::CheckModifiers(HttpRequestData * request_data) {
if (!request_data->hdr) {
//we use the same request_data for Socks as well (only IpMatcher)
//we just return false here
return true;
}
- const char *data;
- const char *path;
- const char *method;
- ipMod *ipRange;
- portMod *portRange;
- timeMod *timeRange;
- time_t timeOfDay;
- URL *request_url = request_data->hdr->url_get();
- int data_len, path_len, scheme_len, method_len;
- char *tag, *request_tag;
- ip_addr_t src_ip;
- int port;
// If the incoming request has no tag but the entry does, or both
// have tags that do not match, then we do NOT have a match.
- request_tag = request_data->tag;
- if (!request_tag && mod_elements != NULL && getModElem(MOD_TAG) != NULL)
+ if (!request_data->tag && findModOfType(Modifier::MOD_TAG))
return false;
- // If there are no modifiers, then of course we match them
- if (mod_elements == NULL) {
- return true;
- }
-
- for (intptr_t i = 0; i < mod_elements->length(); i++) {
- modifier_el & cur_el = (*mod_elements)[i];
-
- switch (cur_el.type) {
- case MOD_PORT:
- port = request_url->port_get();
- portRange = (portMod *) cur_el.opaque_data;
- if (port < portRange->start_port || port > portRange->end_port) {
- return false;
- }
- break;
- case MOD_IPORT:
- if (request_data->incoming_port != (long) cur_el.opaque_data) {
- return false;
- }
- break;
- case MOD_SCHEME:
- if (request_url->scheme_get(&scheme_len) != (char *) cur_el.opaque_data) {
- return false;
- }
- break;
- case MOD_PREFIX:
- // INKqa07820
- // The problem is that path_get() returns the URL's path
- // without the leading '/'.
- // E.g., If URL is http://inktomi/foo/bar,
- // then path_get() returns "foo/bar" but not "/foo/bar".
- // A simple solution is to skip the leading '/' in data.
- data = (char *) cur_el.opaque_data;
- if (*data == '/')
- data++;
- path = request_url->path_get(&path_len);
- if (ptr_len_ncmp(path, path_len, data, strlen(data)) != 0) {
- return false;
- }
- break;
- case MOD_SUFFIX:
- data = (char *) cur_el.opaque_data;
- data_len = strlen(data);
- ink_assert(data_len > 0);
- path = request_url->path_get(&path_len);
- // Suffix matching is case-insentive b/c it's
- // mainly used for file type matching and
- // jpeg, JPEG, Jpeg all mean the same thing
- // (INKqa04363)
- if (path_len < data_len || strncasecmp(path + (path_len - data_len), data, data_len) != 0) {
- return false;
- }
- break;
- case MOD_METHOD:
- method = request_data->hdr->method_get(&method_len);
- if (ptr_len_casecmp(method, method_len, (char *) cur_el.opaque_data) != 0) {
- return false;
- }
- break;
- case MOD_TIME:
- timeRange = (timeMod *) cur_el.opaque_data;
- // INKqa11534
- // daylight saving time is not taken into consideration
- // so use ink_localtime_r() instead.
- // timeOfDay = (request_data->xact_start - ink_timezone()) % secondsInDay;
- {
- struct tm cur_tm;
- timeOfDay = request_data->xact_start;
- ink_localtime_r(&timeOfDay, &cur_tm);
- timeOfDay = cur_tm.tm_hour * (60 * 60)
- + cur_tm.tm_min * 60 + cur_tm.tm_sec;
- }
- if (timeOfDay < timeRange->start_time || timeOfDay > timeRange->end_time) {
- return false;
- }
- break;
- case MOD_SRC_IP:
- src_ip = htonl(request_data->src_ip);
- ipRange = (ipMod *) cur_el.opaque_data;
- if (src_ip < ipRange->start_addr || src_ip > ipRange->end_addr) {
- return false;
- }
- break;
- case MOD_TAG:
- // Check for a tag match.
- tag = (char *) cur_el.opaque_data;
- ink_assert(tag);
- if (request_tag && strcmp(request_tag, tag) != 0) {
- return false;
- }
- break;
- case MOD_INVALID:
- // Fall Through
- default:
- // Should never get here
- ink_assert(0);
- break;
- }
+ for (int i = 0, n = _mods.size() ; i < n; ++i) {
+ Modifier* cur_mod = _mods[i];
+ if (cur_mod && ! cur_mod->check(request_data)) return false;
}
return true;
}
-enum mod_errors
-{ ME_UNKNOWN, ME_PARSE_FAILED,
- ME_BAD_SCHEME, ME_BAD_METHOD, ME_BAD_MOD,
- ME_CALLEE_GENERATED, ME_BAD_IPORT
+enum mod_errors {
+ ME_UNKNOWN,
+ ME_PARSE_FAILED,
+ ME_BAD_MOD,
+ ME_CALLEE_GENERATED
};
static const char *errorFormats[] = {
"Unknown error parsing modifier",
"Unable to parse modifier",
- "Unknown scheme",
- "Unknown method",
"Unknown modifier",
"Callee Generated",
- "Bad incoming port"
};
-const void *
-ControlBase::getModElem(ModifierTypes t)
-{
- for (int i = 0; i < mod_elements->length(); i++) {
- modifier_el & cur_el = (*mod_elements) (i);
- if (cur_el.type == t) {
- return cur_el.opaque_data;
- }
+ControlBase::Modifier*
+ControlBase::findModOfType(Modifier::Type t) const {
+ for (int i = 0, n = _mods.size(); i < n; ++i) {
+ Modifier* m = _mods[i];
+ if (m && t == m->type()) return m;
}
- return NULL;
+ return 0;
}
const char *
-ControlBase::ProcessModifiers(matcher_line * line_info)
-{
-
+ControlBase::ProcessModifiers(matcher_line * line_info) {
// Variables for error processing
const char *errBuf = NULL;
mod_errors err = ME_UNKNOWN;
- int num = 0;
- char *label;
- char *val;
- unsigned int tmp;
- int num_mod_elements;
- const char *tmp_scheme = NULL;
-
- // Set up the array to handle the modifier
- num_mod_elements = (line_info->num_el > 0) ? line_info->num_el : 1;
- mod_elements = new DynArray<modifier_el> (&default_el, num_mod_elements);
-
-
- for (int i = 0; i < MATCHER_MAX_TOKENS; i++) {
-
- label = line_info->line[0][i];
- val = line_info->line[1][i];
-
- // Skip NULL tags
- if (label == NULL) {
- continue;
- }
+ int n_elts = line_info->num_el; // Element count for line.
- modifier_el & cur_el = (*mod_elements) (num);
- num++;
+ // No elements -> no modifiers.
+ if (0 >= n_elts) return 0;
+ // Can't have more modifiers than elements, so reasonable upper bound.
+ _mods.clear();
+ _mods.reserve(n_elts);
+
+ // As elements are consumed, the labels are nulled out and the element
+ // count decremented. So we have to scan the entire array to be sure of
+ // finding all the elements. We'll track the element count so we can
+ // escape if we've found all of the elements.
+ for (int i = 0; n_elts && ME_UNKNOWN == err && i < MATCHER_MAX_TOKENS; ++i) {
+ Modifier* mod = 0;
- // Make sure we have a value
- if (val == NULL) {
+ char * label = line_info->line[0][i];
+ char * value = line_info->line[1][i];
+
+ if (!label) continue; // Already use.
+ if (!value) {
err = ME_PARSE_FAILED;
- goto error;
+ break;
}
if (strcasecmp(label, "port") == 0) {
- cur_el.type = MOD_PORT;
- errBuf = ProcessPort(val, &cur_el.opaque_data);
- if (errBuf != NULL) {
- err = ME_CALLEE_GENERATED;
- goto error;
- }
+ mod = PortMod::make(value, &errBuf);
} else if (strcasecmp(label, "iport") == 0) {
- // coverity[secure_coding]
- if (sscanf(val, "%u", &tmp) == 1) {
- cur_el.type = MOD_IPORT;
- cur_el.opaque_data = (void *)(uintptr_t)tmp;
- } else {
- err = ME_BAD_IPORT;
- goto error;
- }
-
+ mod = IPortMod::make(value, &errBuf);
} else if (strcasecmp(label, "scheme") == 0) {
- tmp_scheme = hdrtoken_string_to_wks(val);
- if (!tmp_scheme) {
- err = ME_BAD_SCHEME;
- goto error;
- }
- cur_el.type = MOD_SCHEME;
- cur_el.opaque_data = (void *) tmp_scheme;
-
+ mod = SchemeMod::make(value, &errBuf);
} else if (strcasecmp(label, "method") == 0) {
- cur_el.type = MOD_METHOD;
- cur_el.opaque_data = (void *) xstrdup(val);
-
+ mod = MethodMod::make(value, &errBuf);
} else if (strcasecmp(label, "prefix") == 0) {
- cur_el.type = MOD_PREFIX;
- cur_el.opaque_data = (void *) xstrdup(val);
-
+ mod = PrefixMod::make(value, &errBuf);
} else if (strcasecmp(label, "suffix") == 0) {
- cur_el.type = MOD_SUFFIX;
- cur_el.opaque_data = (void *) xstrdup(val);
+ mod = SuffixMod::make(value, &errBuf);
} else if (strcasecmp(label, "src_ip") == 0) {
- cur_el.type = MOD_SRC_IP;
- errBuf = ProcessSrcIp(val, &cur_el.opaque_data);
- if (errBuf != NULL) {
- err = ME_CALLEE_GENERATED;
- goto error;
- }
+ mod = SrcIPMod::make(value, &errBuf);
} else if (strcasecmp(label, "time") == 0) {
- cur_el.type = MOD_TIME;
- errBuf = ProcessTimeOfDay(val, &cur_el.opaque_data);
- if (errBuf != NULL) {
- err = ME_CALLEE_GENERATED;
- goto error;
- }
+ mod = TimeMod::make(value, &errBuf);
} else if (strcasecmp(label, "tag") == 0) {
- cur_el.type = MOD_TAG;
- cur_el.opaque_data = (void *) xstrdup(val);
+ mod = TagMod::make(value, &errBuf);
} else {
err = ME_BAD_MOD;
- goto error;
-
}
- }
-
- return NULL;
-
-error:
- delete mod_elements;
- mod_elements = NULL;
- if (err == ME_CALLEE_GENERATED) {
- return errBuf;
- } else {
- return errorFormats[err];
- }
-}
-// const char* ControlBase::ProcessSrcIp(char* val, void** opaque_ptr)
-//
-// Wrapper to Parse out the src ip range
-//
-// On success, sets *opaque_ptr to a malloc allocated ipMod
-// structure and returns NULL
-// On failure, returns a static error string
-//
-const char *
-ControlBase::ProcessSrcIp(char *val, void **opaque_ptr)
-{
- ipMod *range = (ipMod *) xmalloc(sizeof(ipMod));
- const char *errBuf = ExtractIpRange(val, &range->start_addr,
- &range->end_addr);
-
- if (errBuf == NULL) {
- *opaque_ptr = range;
- return NULL;
- } else {
- *opaque_ptr = NULL;
- xfree(range);
- return errBuf;
- }
-}
+ if (errBuf) err = ME_CALLEE_GENERATED; // Mod make failed.
-// const char* TODtoSeconds(const char* time_str, time_t* seconds) {
-//
-// Convents a TimeOfDay (TOD) to a second value
-//
-// On success, sets *seconds to number of seconds since midnight
-// represented by time_str and returns NULL
-//
-// On failure, returns a static error string
-//
-const char *
-TODtoSeconds(const char *time_str, time_t * seconds)
-{
- int hour = 0;
- int min = 0;
- int sec = 0;
- time_t tmp = 0;
-
- // coverity[secure_coding]
- if (sscanf(time_str, "%d:%d:%d", &hour, &min, &sec) != 3) {
- // coverity[secure_coding]
- if (sscanf(time_str, "%d:%d", &hour, &min) != 2) {
- return "Malformed time specified";
+ // If nothing went wrong, add the mod and bump the element count.
+ if (ME_UNKNOWN == err) {
+ _mods.push_back(mod);
+ --n_elts;
}
}
- if (!(hour >= 0 && hour <= 23)) {
- return "Illegal hour specification";
- }
- tmp = hour * 60;
-
- if (!(min >= 0 && min <= 59)) {
- return "Illegal minute specification";
- }
- tmp = (tmp + min) * 60;
-
- if (!(sec >= 0 && sec <= 59)) {
- return "Illegal second specification";
- }
- tmp += sec;
-
- *seconds = tmp;
- return NULL;
-}
-
-// const char* ControlBase::ProcessTimeOfDay(char* val, void** opaque_ptr)
-//
-// Parse out a time of day range.
-//
-// On success, sets *opaque_ptr to a malloc allocated timeMod
-// structure and returns NULL
-// On failure, returns a static error string
-//
-const char *
-ControlBase::ProcessTimeOfDay(char *val, void **opaque_ptr)
-{
- Tokenizer rangeTok("-");
- timeMod *t_mod = NULL;
- int num_tok;
- const char *errBuf;
-
- *opaque_ptr = NULL;
-
- num_tok = rangeTok.Initialize(val, SHARE_TOKS);
- if (num_tok == 1) {
- return "End time not specified";
- } else if (num_tok > 2) {
- return "Malformed Range";
- }
-
- t_mod = (timeMod *) xmalloc(sizeof(timeMod));
-
- errBuf = TODtoSeconds(rangeTok[0], &t_mod->start_time);
-
- if (errBuf != NULL) {
- xfree(t_mod);
- return errBuf;
- }
-
- errBuf = TODtoSeconds(rangeTok[1], &t_mod->end_time);
-
- if (errBuf != NULL) {
- xfree(t_mod);
- return errBuf;
- }
-
- *opaque_ptr = t_mod;
- return NULL;
-}
-
-
-// const char* ControlBase::ProcessPort(char* val, void** opaque_ptr)
-//
-// Parse out a port range.
-//
-// On success, sets *opaque_ptr to a malloc allocated portMod
-// structure and returns NULL
-// On failure, returns a static error string
-//
-const char *
-ControlBase::ProcessPort(char *val, void **opaque_ptr)
-{
- Tokenizer rangeTok("-");
- portMod *p_mod = NULL;
- int num_tok;
-
- *opaque_ptr = NULL;
-
- num_tok = rangeTok.Initialize(val, SHARE_TOKS);
- if (num_tok > 2) {
- return "Malformed Range";
- }
-
- p_mod = (portMod *) xmalloc(sizeof(portMod));
-
- // coverity[secure_coding]
- if (sscanf(rangeTok[0], "%d", &p_mod->start_port) != 1) {
- xfree(p_mod);
- return "Invalid start port";
- }
-
- if (num_tok == 2) {
- // coverity[secure_coding]
- if (sscanf(rangeTok[1], "%d", &p_mod->end_port) != 1) {
- xfree(p_mod);
- return "Invalid end port";
- }
- if (p_mod->end_port < p_mod->start_port) {
- xfree(p_mod);
- return "Malformed Range: end port < start port";
+ if (err != ME_UNKNOWN) {
+ this->clear();
+ if (err != ME_CALLEE_GENERATED) {
+ errBuf = errorFormats[err];
}
- } else {
- p_mod->end_port = p_mod->start_port;
}
- *opaque_ptr = p_mod;
- return NULL;
+ return errBuf;
}
Modified: trafficserver/traffic/trunk/proxy/ControlBase.h
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/ControlBase.h?rev=1074382&r1=1074381&r2=1074382&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/ControlBase.h (original)
+++ trafficserver/traffic/trunk/proxy/ControlBase.h Fri Feb 25 02:39:27 2011
@@ -34,27 +34,44 @@
#define _CONTROL_BASE_H_
#include "libts.h"
-#include "DynArray.h"
+#include <vector>
class HttpRequestData;
class Tokenizer;
struct matcher_line;
-// MOD_IPORT added
-enum ModifierTypes
-{ MOD_INVALID, MOD_PORT, MOD_SCHEME, MOD_PREFIX,
- MOD_SUFFIX, MOD_METHOD, MOD_TIME, MOD_SRC_IP,
- MOD_IPORT, MOD_TAG
-};
-
-struct modifier_el
-{
- ModifierTypes type;
- void *opaque_data;
-};
-
-class ControlBase
-{
+class ControlBase {
public:
+ struct Modifier {
+ enum Type {
+ MOD_INVALID,
+ MOD_PORT,
+ MOD_SCHEME,
+ MOD_PREFIX,
+ MOD_SUFFIX,
+ MOD_METHOD,
+ MOD_TIME,
+ MOD_SRC_IP,
+ MOD_IPORT,
+ MOD_TAG
+ };
+ /// Destructor - force virtual.
+ virtual ~Modifier();
+ /// Return the modifier type.
+ virtual Type type() const;
+ /// Return the name for the modifier type.
+ virtual char const* name() const = 0;
+ /** Test if the modifier matches the request.
+ @return @c true if the request is matched, @c false if not.
+ */
+ virtual bool check(
+ HttpRequestData* req ///< Request to check.
+ ) const = 0;
+ /// Print the mod information.
+ virtual void print(
+ FILE* f ///< Output stream.
+ ) const = 0;
+ };
+
ControlBase();
~ControlBase();
const char *ProcessModifiers(matcher_line * line_info);
@@ -62,29 +79,33 @@ public:
bool CheckForMatch(HttpRequestData * request_data, int last_number);
void Print();
int line_num;
- const void *getModElem(ModifierTypes t);
+ Modifier* findModOfType(Modifier::Type t) const;
+protected:
+ /// Get the text for the Scheme modifier, if any.
+ /// @return The text if present, 0 otherwise.
+ /// @internal Ugly but it's the only place external access is needed.
+ char const* getSchemeModText() const;
private:
- DynArray<modifier_el> *mod_elements;
+ typedef std::vector<Modifier*> Array;
+ Array _mods;
const char *ProcessSrcIp(char *val, void **opaque_ptr);
const char *ProcessTimeOfDay(char *val, void **opaque_ptr);
const char *ProcessPort(char *val, void **opaque_ptr);
+
+ // Reset to default constructed state, free all allocations.
+ void clear();
};
inline
-ControlBase::ControlBase():
-line_num(0),
-mod_elements(NULL)
-{
+ControlBase::ControlBase()
+ : line_num(0) {
}
inline bool
-ControlBase::CheckForMatch(HttpRequestData * request_data, int last_number)
-{
- if ((last_number<0 || last_number> this->line_num) && this->CheckModifiers(request_data)) {
- return true;
- } else {
- return false;
- }
+ControlBase::CheckForMatch(HttpRequestData * request_data, int last_number) {
+ return (last_number<0 || last_number> this->line_num)
+ && this->CheckModifiers(request_data)
+ ;
}
#endif
Modified: trafficserver/traffic/trunk/proxy/ControlMatcher.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/ControlMatcher.cc?rev=1074382&r1=1074381&r2=1074382&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/ControlMatcher.cc (original)
+++ trafficserver/traffic/trunk/proxy/ControlMatcher.cc Fri Feb 25 02:39:27 2011
@@ -203,7 +203,7 @@ template<class Data, class Result> char
ink_assert(match_data != NULL);
// Remove our consumed label from the parsed line
- line_info->line[0][line_info->dest_entry - 1] = NULL; // XXX
+ line_info->line[0][line_info->dest_entry] = 0;
line_info->num_el--;
// Fill in the parameter info
@@ -319,7 +319,7 @@ template<class Data, class Result> char
re_str[num_el] = xstrdup(pattern);
// Remove our consumed label from the parsed line
- line_info->line[0][line_info->dest_entry - 1] = NULL; // XXX
+ line_info->line[0][line_info->dest_entry] = 0;
line_info->num_el--;
// Fill in the parameter info
Modified: trafficserver/traffic/trunk/proxy/Makefile.am
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/Makefile.am?rev=1074382&r1=1074381&r2=1074382&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/Makefile.am (original)
+++ trafficserver/traffic/trunk/proxy/Makefile.am Fri Feb 25 02:39:27 2011
@@ -41,7 +41,8 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/mgmt \
-I$(top_srcdir)/mgmt/preparse \
-I$(top_srcdir)/mgmt/utils \
- -I$(srcdir)/api/ts
+ -I$(srcdir)/api/ts \
+ -I$(top_srcdir)/lib
noinst_HEADERS = \
ConfigParse.h \
Modified: trafficserver/traffic/trunk/proxy/ParentSelection.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/ParentSelection.cc?rev=1074382&r1=1074381&r2=1074382&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/ParentSelection.cc (original)
+++ trafficserver/traffic/trunk/proxy/ParentSelection.cc Fri Feb 25 02:39:27 2011
@@ -830,7 +830,7 @@ ParentRecord::Init(matcher_line * line_i
}
// record SCHEME modifier if present.
// NULL if not present
- this->scheme = (const char *) getModElem(MOD_SCHEME);
+ this->scheme = this->getSchemeModText();
if (this->scheme != NULL) {
// update parent entries' schemes
for (int j = 0; j < num_parents; j++) {