📄 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 initialised
bool Uri::mEncodingReady = false;
// class static variables listing the default characters not to encode
// in user and password strings respectively
Data 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 // deprecated
Uri
Uri::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 // deprecated
Uri
Uri::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;
}
bool
Uri::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;
}
bool
Uri::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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -