diff options
Diffstat (limited to 'cpp/src/qpid/Url.cpp')
-rw-r--r-- | cpp/src/qpid/Url.cpp | 265 |
1 files changed, 0 insertions, 265 deletions
diff --git a/cpp/src/qpid/Url.cpp b/cpp/src/qpid/Url.cpp deleted file mode 100644 index ab796f4642..0000000000 --- a/cpp/src/qpid/Url.cpp +++ /dev/null @@ -1,265 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed 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 "qpid/Url.h" -#include "qpid/Exception.h" -#include "qpid/Msg.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/sys/StrError.h" -#include "qpid/client/Connector.h" -#include "qpid/sys/Mutex.h" -#include <boost/lexical_cast.hpp> - -#include <algorithm> -#include <vector> -#include <string> - -#include <string.h> - -using namespace std; -using boost::lexical_cast; - -namespace qpid { - -class ProtocolTags { - public: - bool find(const string& tag) { - sys::Mutex::ScopedLock l(lock); - return std::find(tags.begin(), tags.end(), tag) != tags.end(); - } - - void add(const string& tag) { - sys::Mutex::ScopedLock l(lock); - if (std::find(tags.begin(), tags.end(), tag) == tags.end()) - tags.push_back(tag); - } - - static ProtocolTags& instance() { - /** First call must be made while program is still single threaded. - * This will be the case since tags are registered in static initializers. - */ - static ProtocolTags tags; - return tags; - } - - private: - sys::Mutex lock; - vector<string> tags; -}; - -Url::Invalid::Invalid(const string& s) : Exception(s) {} - -Url Url::getHostNameUrl(uint16_t port) { - Address address("tcp", std::string(), port); - if (!sys::SystemInfo::getLocalHostname(address)) - throw Url::Invalid(QPID_MSG("Cannot get host name: " << qpid::sys::strError(errno))); - return Url(address); -} - -Url Url::getIpAddressesUrl(uint16_t port) { - Url url; - sys::SystemInfo::getLocalIpAddresses(port, url); - return url; -} - -string Url::str() const { - if (cache.empty() && !this->empty()) { - ostringstream os; - os << *this; - cache = os.str(); - } - return cache; -} - -ostream& operator<<(ostream& os, const Url& url) { - os << "amqp:"; - if (!url.getUser().empty()) os << url.getUser(); - if (!url.getPass().empty()) os << "/" << url.getPass(); - if (!(url.getUser().empty() && url.getPass().empty())) os << "@"; - Url::const_iterator i = url.begin(); - if (i!=url.end()) { - os << *i++; - while (i != url.end()) - os << "," << *i++; - } - return os; -} - -static const std::string TCP = "tcp"; - -/** Simple recursive-descent parser for this grammar: -url = ["amqp:"][ user ["/" password] "@" ] protocol_addr *("," protocol_addr) -protocol_addr = tcp_addr / rmda_addr / ssl_addr / .. others plug-in -tcp_addr = ["tcp:"] host [":" port] -rdma_addr = "rdma:" host [":" port] -ssl_addr = "ssl:" host [":" port] -*/ -class UrlParser { - public: - UrlParser(Url& u, const char* s) : url(u), text(s), end(s+strlen(s)), i(s) {} - bool parse() { - literal("amqp:"); // Optional - userPass(); // Optional - return list(&UrlParser::protocolAddr, &UrlParser::comma) && i == end; - } - - private: - typedef bool (UrlParser::*Rule)(); - - bool userPass() { - const char* at = std::find(i, end, '@'); - if (at == end) return false; - const char* slash = std::find(i, at, '/'); - url.setUser(string(i, slash)); - const char* pass = (slash == at) ? slash : slash+1; - url.setPass(string(pass, at)); - i = at+1; - return true; - } - - bool comma() { return literal(","); } - - bool protocolAddr() { - Address addr(Address::TCP, "", Address::AMQP_PORT); // Set up defaults - protocolTag(addr.protocol); // Optional - bool ok = (host(addr.host) && - (literal(":") ? port(addr.port) : true)); - if (ok) url.push_back(addr); - return ok; - } - - bool protocolTag(string& result) { - const char* j = std::find(i,end,':'); - if (j != end) { - string tag(i,j); - if (ProtocolTags::instance().find(tag)) { - i = j+1; - result = tag; - return true; - } - } - return false; - } - - // TODO aconway 2008-11-20: this does not fully implement - // http://www.ietf.org/rfc/rfc3986.txt. Works for DNS names and - // ipv4 literals but won't handle ipv6. - // - bool host(string& h) { - const char* start=i; - while (unreserved() || pctEncoded()) - ; - if (start == i) return false;//host is required - else h.assign(start, i); - return true; - } - - bool unreserved() { return (::isalnum(*i) || ::strchr("-._~", *i)) && advance(); } - - bool pctEncoded() { return literal("%") && hexDigit() && hexDigit(); } - - bool hexDigit() { return i < end && ::strchr("01234567890abcdefABCDEF", *i) && advance(); } - - bool port(uint16_t& p) { return decimalInt(p); } - - template <class IntType> bool decimalInt(IntType& n) { - const char* start = i; - while (decDigit()) - ; - try { - n = lexical_cast<IntType>(string(start, i)); - return true; - } catch(...) { return false; } - } - - bool decDigit() { return i < end && ::isdigit(*i) && advance(); } - - bool literal(const char* s) { - int n = ::strlen(s); - if (n <= end-i && equal(s, s+n, i)) return advance(n); - return false; - }; - - bool noop() { return true; } - - /** List of item, separated by separator, with min & max bounds. */ - bool list(Rule item, Rule separator, size_t min=0, size_t max=UNLIMITED) { - assert(max > 0); - assert(max >= min); - if (!(this->*item)()) return min == 0; // Empty list. - size_t n = 1; - while (n < max && i < end) { - if (!(this->*separator)()) break; - if (i == end || !(this->*item)()) return false; // Separator with no item. - ++n; - } - return n >= min; - } - - /** List of items with no separator */ - bool list(Rule item, size_t min=0, size_t max=UNLIMITED) { return list(item, &UrlParser::noop, min, max); } - - bool advance(size_t n=1) { - if (i+n > end) return false; - i += n; - return true; - } - - static const size_t UNLIMITED = size_t(~1); - static const std::string LOCALHOST; - - Url& url; - const char* text; - const char* end; - const char* i; -}; - -const string UrlParser::LOCALHOST("127.0.0.1"); - -void Url::parse(const char* url) { - parseNoThrow(url); - if (empty()) - throw Url::Invalid(QPID_MSG("Invalid URL: " << url)); -} - -void Url::parseNoThrow(const char* url) { - cache.clear(); - if (!UrlParser(*this, url).parse()) - clear(); -} - -void Url::throwIfEmpty() const { - if (empty()) - throw Url::Invalid("URL contains no addresses"); -} - -std::string Url::getUser() const { return user; } -std::string Url::getPass() const { return pass; } -void Url::setUser(const std::string& s) { user = s; } -void Url::setPass(const std::string& s) { pass = s; } - -std::istream& operator>>(std::istream& is, Url& url) { - std::string s; - is >> s; - url.parse(s); - return is; -} - -void Url::addProtocol(const std::string& tag) { ProtocolTags::instance().add(tag); } - -} // namespace qpid |