TCAScheme.cc

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2005-2006 University of Waterloo
00003  * 
00004  *    Licensed under the Apache License, Version 2.0 (the "License");
00005  *    you may not use this file except in compliance with the License.
00006  *    You may obtain a copy of the License at
00007  * 
00008  *        http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  *    Unless required by applicable law or agreed to in writing, software
00011  *    distributed under the License is distributed on an "AS IS" BASIS,
00012  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *    See the License for the specific language governing permissions and
00014  *    limitations under the License.
00015  */
00016 
00017 
00018 
00019 #include <ctype.h>
00020 #include <oasys/debug/Log.h>
00021 #include <oasys/util/URL.h>
00022 
00023 #include "TCAScheme.h"
00024 #include "EndpointID.h"
00025 
00026 namespace dtn {
00027 
00028 template <>
00029 TCAScheme* oasys::Singleton<TCAScheme>::instance_ = 0;
00030 
00038 bool
00039 TCAScheme::validate(const std::string& ssp, bool is_pattern)
00040 {
00041     // DK: This is entirely borrowed from the DTNScheme implementation.
00042     // TODO: Revisit this once we are using email addresses or sha1 hashes
00043     // of email addresses as guids in the scheme. Are these still valid?
00044 
00045     // use the oasys builtin class for URLs, though we need to re-add
00046     // the dtn: since it was stripped by the basic endpoint id parsing
00047     std::string url_str = "tca:";
00048     url_str.append(ssp);
00049     oasys::URL url(url_str);
00050     if (! url.valid()) {
00051         return false;
00052     }
00053 
00054     // validate that the hostname contains only legal chars.
00055     // XXX/demmer we could be better about making sure it's really a
00056     // legal hostname, i.e. doesn't contain two dots in a row,
00057     // something like like www.foo..com 
00058     std::string::iterator iter;
00059     for (iter = url.host_.begin(); iter != url.host_.end(); ++iter) {
00060         char c = *iter;
00061         
00062         if (isalnum(c) || (c == '_') || (c == '-') || (c == '.'))
00063             continue;
00064 
00065         if (is_pattern && (c == '*'))
00066             continue;
00067 
00068         log_debug_p("/scheme/tca",
00069                     "ssp '%s' contains invalid hostname character '%c'",
00070                     ssp.c_str(), c);
00071 
00072         return false;
00073     }
00074     
00075     return true;
00076 }
00077 
00083 // DK: This is almost entirely copied from the DTNScheme implementation.
00084 // The one exception is a change to the matching logic, to allow for wildcard
00085 // * in either pattern or ssp. (Previously, * was only supported in pattern.)
00086 bool
00087 TCAScheme::match(const EndpointIDPattern& pattern, const EndpointID& eid)
00088 {
00089     // sanity check
00090     ASSERT(pattern.scheme() == this);
00091 
00092     // we only match endpoint ids of the same scheme
00093     if (!eid.known_scheme() || (eid.scheme() != this)) {
00094         return false;
00095     }
00096 
00097     // if the ssp of either string is "none", then nothing should
00098     // match it (ever)
00099     if (pattern.ssp() == "none" || eid.ssp() == "none") {
00100         return false;
00101     }
00102 
00103     // parse the two strings into URLs for easier manipulation
00104     oasys::URL eid_url(eid.str());
00105     oasys::URL pattern_url(pattern.str());
00106 
00107     if (!eid_url.valid()) {
00108         log_warn_p("/scheme/dtn",
00109                    "match error: eid '%s' not a valid url",
00110                    eid.c_str());
00111         return false;
00112     }
00113 
00114     if (!pattern_url.valid()) {
00115         log_warn_p("/scheme/dtn",
00116                    "match error: pattern '%s' not a valid url",
00117                    pattern.c_str());
00118         return false;
00119     }
00120 
00121     // check for a wildcard host specifier e.g dtn://*
00122     if (pattern_url.host_ == "*" && pattern_url.path_ == "")
00123     {
00124         return true;
00125     }
00126 
00127     // match the host part of the urls (though if the pattern host is
00128     // "*", fall through to the rest of the comparison)
00129     if ((pattern_url.host_ != "*") &&
00130          (eid_url.host_ != "*") &&                  // DK: added this
00131          (pattern_url.host_ != eid_url.host_))
00132     {
00133         log_debug_p("/scheme/dtn",
00134                     "match(%s, %s) failed: url hosts not equal ('%s' != '%s')",
00135                     eid_url.c_str(), pattern_url.c_str(),
00136                     pattern_url.host_.c_str(), eid_url.host_.c_str());
00137         return false;
00138     }
00139 
00140     // make sure the ports are equal (or unspecified in which case they're 0)
00141     if (pattern_url.port_ != eid_url.port_)
00142     {
00143         log_debug_p("/scheme/dtn",
00144                     "match(%s, %s) failed: url ports not equal (%d != %d)",
00145                     eid_url.c_str(), pattern_url.c_str(),
00146                     pattern_url.port_, eid_url.port_);
00147         return false;
00148     }
00149 
00150     // check for a wildcard path or an exact match of the path strings
00151     if ((pattern_url.path_ == "*") ||
00152         (pattern_url.path_ == eid_url.path_))
00153     {
00154         log_debug_p("/scheme/dtn",
00155                     "match(%s, %s) succeeded: pattern '%s' ssp '%s'",
00156                     eid_url.c_str(), pattern_url.c_str(),
00157                     pattern_url.host_.c_str(), eid_url.host_.c_str());
00158         return true;
00159     }
00160 
00161     // finally, try supporting a trailing * to truncate the path match
00162     size_t patternlen = pattern_url.path_.length();
00163     if (patternlen >= 1 && pattern_url.path_[patternlen-1] == '*') {
00164         patternlen--;
00165 
00166         if (pattern_url.path_.substr(0, patternlen) ==
00167             eid_url.path_.substr(0, patternlen))
00168         {
00169             log_debug_p("/scheme/dtn",
00170                         "match(%s, %s) substring succeeded: "
00171                         "pattern '%s' ssp '%s'",
00172                         eid_url.c_str(), pattern_url.c_str(),
00173                         pattern_url.host_.c_str(), eid_url.host_.c_str());
00174             return true;
00175         }
00176     }
00177 
00178     // XXX/demmer TODO: support CIDR style matching for explicit
00179     // dotted-quad ip addresses
00180 
00181     return false;
00182 }
00183 
00184 
00192 bool
00193 TCAScheme::append_service_tag(std::string* ssp, const char* tag)
00194 {
00195     if (tag[0] != '/') {
00196         ssp->push_back('/');
00197     }
00198     ssp->append(tag);
00199     return true;
00200 }
00201 
00202 } // namespace dtn

Generated on Sat Sep 8 08:36:18 2007 for DTN Reference Implementation by  doxygen 1.5.3