📄 uri.cxx
字号:
#if defined(HAVE_CONFIG_H)#include "resip/stack/config.hxx"#endif#include <set>#include "resip/stack/Embedded.hxx"#include "resip/stack/Helper.hxx"#include "resip/stack/NameAddr.hxx" #include "resip/stack/SipMessage.hxx"#include "resip/stack/Symbols.hxx"#include "resip/stack/UnknownParameter.hxx"#include "resip/stack/Uri.hxx"#include "rutil/DataStream.hxx"#include "rutil/DnsUtil.hxx"#include "rutil/Logger.hxx"#include "rutil/ParseBuffer.hxx"#include "rutil/WinLeakCheck.hxx"using namespace resip;#define RESIPROCATE_SUBSYSTEM Subsystem::SIP#define HANDLE_CHARACTER_ESCAPING //undef for old behaviour// Set to true only after the tables are initialisedbool Uri::mEncodingReady = false;// class static variables listing the default characters not to encode// in user and password strings respectivelyData Uri::mUriNonEncodingUserChars = Data("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*\\()&=+$,;?/");Data Uri::mUriNonEncodingPasswordChars = Data("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*\\()&=+$");Uri::EncodingTable Uri::mUriEncodingUserTable;Uri::EncodingTable Uri::mUriEncodingPasswordTable;Uri::Uri() : ParserCategory(), mScheme(Data::Share, Symbols::DefaultSipScheme), mPort(0), mOldPort(0), mEmbeddedHeaders(0){}static const Data parseContext("Uri constructor");Uri::Uri(const Data& data) : ParserCategory(), mScheme(Symbols::DefaultSipScheme), mPort(0), mOldPort(0), mEmbeddedHeaders(0){ // must copy because parse creates overlays Uri tmp; ParseBuffer pb(data, parseContext); tmp.parse(pb); *this = tmp;}Uri::Uri(const Uri& rhs) : ParserCategory(rhs), mScheme(rhs.mScheme), mHost(rhs.mHost), mUser(rhs.mUser), mUserParameters(rhs.mUserParameters), mPort(rhs.mPort), mPassword(rhs.mPassword), mOldPort(0), mEmbeddedHeadersText(rhs.mEmbeddedHeadersText), mEmbeddedHeaders(rhs.mEmbeddedHeaders ? new SipMessage(*rhs.mEmbeddedHeaders) : 0){}Uri::~Uri(){ delete mEmbeddedHeaders;}// RFC 3261 19.1.6#if 0 // deprecatedUriUri::fromTel(const Uri& tel, const Data& host){ assert(tel.scheme() == Symbols::Tel); Uri u; u.scheme() = Symbols::Sip; u.user() = tel.user(); u.host() = host; u.param(p_user) = Symbols::Phone; // need to sort the user parameters if (!tel.userParameters().empty()) { DebugLog(<< "Uri::fromTel: " << tel.userParameters()); Data isub; Data postd; int totalSize = 0; std::set<Data> userParameters; ParseBuffer pb(tel.userParameters().data(), tel.userParameters().size()); while (true) { const char* anchor = pb.position(); pb.skipToChar(Symbols::SEMI_COLON[0]); Data param = pb.data(anchor); // !dlb! not supposed to lowercase extension parameters param.lowercase(); totalSize += param.size() + 1; if (param.prefix(Symbols::Isub)) { isub = param; } else if (param.prefix(Symbols::Postd)) { postd = param; } else { userParameters.insert(param); } if (pb.eof()) { break; } else { pb.skipChar(); } } u.userParameters().reserve(totalSize); if (!isub.empty()) { u.userParameters() = isub; } if (!postd.empty()) { if (!u.userParameters().empty()) { u.userParameters() += Symbols::SEMI_COLON[0]; } u.userParameters() += postd; } for(std::set<Data>::const_iterator i = userParameters.begin(); i != userParameters.end(); ++i) { DebugLog(<< "Adding param: " << *i); if (!u.userParameters().empty()) { u.userParameters() += Symbols::SEMI_COLON[0]; } u.userParameters() += *i; } } return u;}#endif // deprecatedUriUri::fromTel(const Uri& tel, const Uri& hostUri){ assert(tel.scheme() == Symbols::Tel); Uri u(hostUri); u.scheme() = Symbols::Sip; u.user() = tel.user(); u.param(p_user) = Symbols::Phone; // need to sort the user parameters if (!tel.userParameters().empty()) { DebugLog(<< "Uri::fromTel: " << tel.userParameters()); Data isub; Data postd; int totalSize = 0; std::set<Data> userParameters; ParseBuffer pb(tel.userParameters().data(), tel.userParameters().size()); while (true) { const char* anchor = pb.position(); pb.skipToChar(Symbols::SEMI_COLON[0]); Data param = pb.data(anchor); // !dlb! not supposed to lowercase extension parameters param.lowercase(); totalSize += param.size() + 1; if (param.prefix(Symbols::Isub)) { isub = param; } else if (param.prefix(Symbols::Postd)) { postd = param; } else { userParameters.insert(param); } if (pb.eof()) { break; } else { pb.skipChar(); } } u.userParameters().reserve(totalSize); if (!isub.empty()) { u.userParameters() = isub; } if (!postd.empty()) { if (!u.userParameters().empty()) { u.userParameters() += Symbols::SEMI_COLON[0]; } u.userParameters() += postd; } for(std::set<Data>::const_iterator i = userParameters.begin(); i != userParameters.end(); ++i) { DebugLog(<< "Adding param: " << *i); if (!u.userParameters().empty()) { u.userParameters() += Symbols::SEMI_COLON[0]; } u.userParameters() += *i; } } return u;}boolUri::isEnumSearchable() const{ return (!user().empty() && user().size() >= 2 && user()[0] == '+');}std::vector<Data> Uri::getEnumLookups(const std::vector<Data>& suffixes) const{ std::vector<Data> results; Data prefix; if (isEnumSearchable()) { // skip the leading + for (const char* i=user().end()-1 ; i!= user().begin(); --i) { if (isdigit(*i)) { prefix += *i; prefix += Symbols::DOT; } } for (std::vector<Data>::const_iterator j=suffixes.begin(); j != suffixes.end(); ++j) { results.push_back(prefix + *j); } } return results;}boolUri::hasEmbedded() const{ checkParsed(); return !mEmbeddedHeadersText.empty() || mEmbeddedHeaders != 0;}void Uri::removeEmbedded(){ delete mEmbeddedHeaders; mEmbeddedHeaders = 0; mEmbeddedHeadersText = Data::Empty; }Uri&Uri::operator=(const Uri& rhs){ if (this != &rhs) { ParserCategory::operator=(rhs); mScheme = rhs.mScheme; mHost = rhs.mHost; mUser = rhs.mUser; mUserParameters = rhs.mUserParameters; mPort = rhs.mPort; mPassword = rhs.mPassword; if (rhs.mEmbeddedHeaders != 0) { delete mEmbeddedHeaders; mEmbeddedHeaders = new SipMessage(*rhs.mEmbeddedHeaders); } else { mEmbeddedHeadersText = rhs.mEmbeddedHeadersText; } } return *this;}class OrderUnknownParameters{ public: OrderUnknownParameters() { notUsed=false; }; ~OrderUnknownParameters() {}; bool operator()(const Parameter* p1, const Parameter* p2) const { return dynamic_cast<const UnknownParameter*>(p1)->getName() < dynamic_cast<const UnknownParameter*>(p2)->getName(); } private: bool notUsed;};bool Uri::operator==(const Uri& other) const{ checkParsed(); other.checkParsed(); // compare hosts if (DnsUtil::isIpV6Address(mHost) && DnsUtil::isIpV6Address(other.mHost)) { // compare canonicalized IPV6 addresses // update canonicalized if host changed if (mOldHost != mHost) { mOldHost = mHost; mCanonicalHost = DnsUtil::canonicalizeIpV6Address(mHost); } // update canonicalized if host changed if (other.mOldHost != other.mHost) { other.mOldHost = other.mHost; other.mCanonicalHost = DnsUtil::canonicalizeIpV6Address(other.mHost); } if (mCanonicalHost != other.mCanonicalHost) { return false; } } else { if (!isEqualNoCase(mHost, other.mHost)) { return false; } } if (isEqualNoCase(mScheme, other.mScheme) && ((isEqualNoCase(mScheme, Symbols::Sip) || isEqualNoCase(mScheme, Symbols::Sips)) ? mUser == other.mUser : isEqualNoCase(mUser, other.mUser)) && isEqualNoCase(mUserParameters,other.mUserParameters) && mPassword == other.mPassword && mPort == other.mPort) { for (ParameterList::iterator it = mParameters.begin(); it != mParameters.end(); ++it) { Parameter* otherParam = other.getParameterByEnum((*it)->getType()); switch ((*it)->getType()) { case ParameterTypes::user: { if (!(otherParam && isEqualNoCase(dynamic_cast<DataParameter*>(*it)->value(), dynamic_cast<DataParameter*>(otherParam)->value()))) { return false; } } break; case ParameterTypes::ttl: { if (!(otherParam && (dynamic_cast<UInt32Parameter*>(*it)->value() == dynamic_cast<UInt32Parameter*>(otherParam)->value()))) { return false; } break; } case ParameterTypes::method: { // this should possilby be case sensitive, but is allowed to be // case insensitive for robustness. if (otherParam) { DataParameter* dp1 = dynamic_cast<DataParameter*>(*it); DataParameter* dp2 = dynamic_cast<DataParameter*>(otherParam); assert(dp1); assert(dp2); } if (!(otherParam && isEqualNoCase(dynamic_cast<DataParameter*>(*it)->value(), dynamic_cast<DataParameter*>(otherParam)->value()))) { return false; } break; } case ParameterTypes::maddr: { if (!(otherParam && isEqualNoCase(dynamic_cast<DataParameter*>(*it)->value(), dynamic_cast<DataParameter*>(otherParam)->value()))) { return false; } } break; case ParameterTypes::transport: { if (!(otherParam && isEqualNoCase(dynamic_cast<DataParameter*>(*it)->value(), dynamic_cast<DataParameter*>(otherParam)->value()))) { return false; } } break; // the parameters that follow don't affect comparison if only present // in one of the URI's case ParameterTypes::lr: break; default: break; //treat as unknown parameter? } } // now check the other way, sigh for (ParameterList::iterator it = other.mParameters.begin(); it != other.mParameters.end(); ++it) { Parameter* param = getParameterByEnum((*it)->getType()); switch ((*it)->getType()) { case ParameterTypes::user: { if (!(param && isEqualNoCase(dynamic_cast<DataParameter*>(*it)->value(), dynamic_cast<DataParameter*>(param)->value()))) { return false; } } break; case ParameterTypes::ttl: { if (!(param && (dynamic_cast<UInt32Parameter*>(*it)->value() == dynamic_cast<UInt32Parameter*>(param)->value()))) { return false; } break; } case ParameterTypes::method: { // this should possilby be case sensitive, but is allowed to be // case insensitive for robustness. if (!(param && isEqualNoCase(dynamic_cast<DataParameter*>(*it)->value(), dynamic_cast<DataParameter*>(param)->value()))) { return false; } } break; case ParameterTypes::maddr: { if (!(param && isEqualNoCase(dynamic_cast<DataParameter*>(*it)->value(), dynamic_cast<DataParameter*>(param)->value()))) { return false; } } break; case ParameterTypes::transport: { if (!(param && isEqualNoCase(dynamic_cast<DataParameter*>(*it)->value(), dynamic_cast<DataParameter*>(param)->value()))) { return false; } } break; // the parameters that follow don't affect comparison if only present // in one of the URI's case ParameterTypes::lr: break; default: break; //treat as unknown parameter? } } } else { return false; } OrderUnknownParameters orderUnknown;#if defined(__SUNPRO_CC) || defined(WIN32) || defined(__sun__) // The Solaris Forte STL implementation does not support the // notion of a list.sort() function taking a BinaryPredicate. // The hacky workaround is to load the Parameter pointers into // an STL set which does support an ordering function. typedef std::set<Parameter*, OrderUnknownParameters> ParameterSet; ParameterSet unA, unB; for (ParameterList::iterator i = mUnknownParameters.begin(); i != mUnknownParameters.end(); ++i) { unA.insert(*i); } for (ParameterList::iterator i = other.mUnknownParameters.begin(); i != other.mUnknownParameters.end(); ++i) { unB.insert(*i); } ParameterSet::iterator a = unA.begin(); ParameterSet::iterator b = unB.begin();#else // .dlb. more efficient to copy to vector for sorting? // Uri comparison is expensive; consider caching? ugh ParameterList unA = mUnknownParameters; ParameterList unB = other.mUnknownParameters; sort(unA.begin(), unA.end(), orderUnknown); sort(unB.begin(), unB.end(), orderUnknown); ParameterList::iterator a = unA.begin(); ParameterList::iterator b = unB.begin();#endif while(a != unA.end() && b != unB.end()) { if (orderUnknown(*a, *b)) { ++a; } else if (orderUnknown(*b, *a)) { ++b; } else { if (!isEqualNoCase(dynamic_cast<UnknownParameter*>(*a)->value(), dynamic_cast<UnknownParameter*>(*b)->value())) { return false; } ++a;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -