1#if defined(HAVE_CONFIG_H)
24#define RESIPROCATE_SUBSYSTEM Subsystem::SIP
25#define HANDLE_CHARACTER_ESCAPING
43 mHostCanonicalized(false),
44 mIsBetweenAngleQuotes(false),
45 mIsBareAddrSpec(false)
52 mHostCanonicalized(false),
53 mIsBetweenAngleQuotes(false),
54 mIsBareAddrSpec(false)
61 mScheme(
Symbols::DefaultSipScheme),
63 mHostCanonicalized(false),
64 mIsBetweenAngleQuotes(false),
65 mIsBareAddrSpec(false)
80 mUserParameters(rhs.mUserParameters),
82 mPassword(rhs.mPassword),
85 mHostCanonicalized(rhs.mHostCanonicalized),
86 mCanonicalHost(rhs.mCanonicalHost),
87 mIsBetweenAngleQuotes(rhs.mIsBetweenAngleQuotes),
88 mIsBareAddrSpec(rhs.mIsBareAddrSpec),
89 mEmbeddedHeadersText(rhs.mEmbeddedHeadersText.get() ? new
Data(*rhs.mEmbeddedHeadersText) : 0),
90 mEmbeddedHeaders(rhs.mEmbeddedHeaders.get() ? new
SipMessage(*rhs.mEmbeddedHeaders) : 0),
91 mUserRaw(rhs.mUserRaw ? new
Data(*rhs.mUserRaw) : nullptr)
124 const char* anchor = pb.position();
170 DebugLog(<<
"Adding param: " << *i);
252 DebugLog(<<
"Adding param: " << *i);
278 StackLog(<<
"user part of Uri empty or too short for E.164");
286 StackLog(<<
"user part of Uri does not begin with `+' or too short");
291 for(
const char* i=
user().begin() + 1; i!=
user().
end(); i++)
293 if (isdigit(
static_cast< unsigned char >(*i)))
301 StackLog(<<
"user part of Uri contains non-digit: " << *i);
309 StackLog(<<
"user part of Uri contains more than 15 digits");
320 std::vector<Data> results;
327 if (isdigit(
static_cast< unsigned char >(*i)))
333 StackLog(<<
"E.164 number reversed for ENUM query: " << prefix);
334 for (std::vector<Data>::const_iterator j=suffixes.begin(); j != suffixes.end(); ++j)
336 results.push_back(prefix + *j);
346 return (mEmbeddedHeadersText.get() && !mEmbeddedHeadersText->empty()) || mEmbeddedHeaders.get() != 0;
353 mEmbeddedHeaders.reset();
354 mEmbeddedHeadersText.reset();
371 mUserRaw.reset(
new Data(*rhs.mUserRaw));
381 if (rhs.mEmbeddedHeaders.get() != 0)
383 mEmbeddedHeaders.reset(
new SipMessage(*rhs.mEmbeddedHeaders));
385 else if(rhs.mEmbeddedHeadersText.get() != 0)
387 if(!mEmbeddedHeadersText.get())
389 mEmbeddedHeadersText.reset(
new Data(*rhs.mEmbeddedHeadersText));
394 *mEmbeddedHeadersText = *rhs.mEmbeddedHeadersText;
437 if (!param1 || !param2)
443 case ParameterTypes::user:
444 case ParameterTypes::method:
445 case ParameterTypes::maddr:
446 case ParameterTypes::transport:
447 case ParameterTypes::rinstance:
448 case ParameterTypes::comp:
449 case ParameterTypes::extension:
450 case ParameterTypes::wsSrcIp:
451 case ParameterTypes::sigcompId:
455 case ParameterTypes::ttl:
456 case ParameterTypes::duration:
457 case ParameterTypes::wsSrcPort:
461 case ParameterTypes::gr:
465 case ParameterTypes::lr:
466 case ParameterTypes::ob:
479 if (!param1 || !param2)
485 case ParameterTypes::user:
486 case ParameterTypes::method:
487 case ParameterTypes::maddr:
488 case ParameterTypes::transport:
489 case ParameterTypes::rinstance:
490 case ParameterTypes::comp:
491 case ParameterTypes::extension:
492 case ParameterTypes::wsSrcIp:
493 case ParameterTypes::sigcompId:
497 case ParameterTypes::ttl:
498 case ParameterTypes::duration:
499 case ParameterTypes::wsSrcPort:
503 case ParameterTypes::gr:
507 case ParameterTypes::lr:
508 case ParameterTypes::ob:
521 return type == ParameterTypes::user ||
522 type == ParameterTypes::ttl ||
523 type == ParameterTypes::method ||
524 type == ParameterTypes::maddr ||
525 type == ParameterTypes::transport;
642#if defined(__SUNPRO_CC) || defined(WIN32) || defined(__sun__)
648 typedef std::set<Parameter*, OrderUnknownParameters> ParameterSet;
649 ParameterSet unA, unB;
662 ParameterSet::iterator a = unA.begin();
663 ParameterSet::iterator b = unB.begin();
670 sort(unA.begin(), unA.end(), orderUnknown);
671 sort(unB.begin(), unB.end(), orderUnknown);
673 ParameterList::iterator a = unA.begin();
674 ParameterList::iterator b = unB.begin();
677 while(a != unA.end() && b != unB.end())
679 if (orderUnknown(*a, *b))
683 else if (orderUnknown(*b, *a))
704 return !(*
this == other);
804#if defined(__SUNPRO_CC) || defined(WIN32) || defined(__sun__)
810 typedef std::set<Parameter*, OrderUnknownParameters> ParameterSet;
811 ParameterSet thisUriParamList, otherUriParamList;
816 thisUriParamList.insert(*i);
821 otherUriParamList.insert(*i);
827 sort(thisUriParamList.begin(), thisUriParamList.end(), orderUnknown);
828 sort(otherUriParamList.begin(), otherUriParamList.end(), orderUnknown);
831 auto thisUriParam = thisUriParamList.begin();
832 auto otherUriParam = otherUriParamList.begin();
836 while(thisUriParam != thisUriParamList.end() && otherUriParam != otherUriParamList.end())
838 if (orderUnknown(*thisUriParam, *otherUriParam))
843 else if (orderUnknown(*otherUriParam, *thisUriParam))
928 addPort = addPort &&
mPort!=0;
933 if (hostIsIpV6Address)
959#ifdef HANDLE_CHARACTER_ESCAPING
980 if(hostIsIpV6Address && addPort)
1028 if(dialString.
empty())
1030 pb.
fail(__FILE__, __LINE__,
"Dial string is empty.");
1042 if(local || !pb.
eof())
1073 Token result = tempToken;
1082 str << telephoneSubscriber;
1114 ret.mUserRaw.reset(
new Data(*mUserRaw));
1119 if(transportTypeToRemoveDefaultPort ==
UDP ||
1120 transportTypeToRemoveDefaultPort ==
TCP)
1127 else if (transportTypeToRemoveDefaultPort ==
TLS ||
1128 transportTypeToRemoveDefaultPort ==
DTLS)
1143#ifdef HANDLE_CHARACTER_ESCAPING
1151 Data& user, std::unique_ptr<Data>& userRaw)
1153 const char* userEnd = pb.
position();
1154 bool userHasEscape =
false;
1155 for (
const char* p = start; p < userEnd; ++p)
1159 userHasEscape =
true;
1211 const char* anchor = pb.
position();
1242#ifdef HANDLE_CHARACTER_ESCAPING
1261 pb.
fail(__FILE__, __LINE__,
"urn: missing NID:NSS separator.");
1263 if (sep < 2 || sep > 32)
1265 pb.
fail(__FILE__, __LINE__,
"urn: NID must be 2-32 characters.");
1269 const unsigned char c = (
unsigned char)
mUser[i];
1275 const bool isAsciiAlnum = (c >=
'0' && c <=
'9') ||
1276 (c >=
'A' && c <=
'Z') ||
1277 (c >=
'a' && c <=
'z');
1278 if (!isAsciiAlnum && !(c ==
'-' && i > 0 && i <
sep - 1))
1280 pb.
fail(__FILE__, __LINE__,
"urn: NID has an invalid character.");
1285 pb.
fail(__FILE__, __LINE__,
"urn: NSS must not be empty.");
1289 pb.
fail(__FILE__, __LINE__,
"urn: NID must not be \"urn\".");
1322 const char* anchor = pb.
position();
1336 static std::bitset<256> userPortOrPasswordDelim(
Data::toBitset(
"@:\""));
1341 const char* atSign=0;
1345 const char* afterColon = pb.
skipChar();
1351#ifdef HANDLE_CHARACTER_ESCAPING
1356 pb.
reset(afterColon-1);
1376#ifdef HANDLE_CHARACTER_ESCAPING
1399 static std::bitset<256> hostDelimiter(
Data::toBitset(
"\r\n\t :;?>"));
1410 " be unparsable because IPV6 support is not"
1411 " enabled)",
"Uri",__FILE__,
1438 const char* anchor = pb.
position();
1456 if(!mEmbeddedHeadersText.get()) mEmbeddedHeadersText.reset(
new Data);
1457 pb.
data(*mEmbeddedHeadersText, anchor);
1464 return new Uri(*
this);
1470 return new (location)
Uri(*
this);
1476 return new (pool)
Uri(*
this);
1506#ifdef HANDLE_CHARACTER_ESCAPING
1521 Data decodedUserRaw;
1522 ParseBuffer pb(mUserRaw->data(), mUserRaw->size());
1523 const char* anchor = pb.
position();
1526 if (decodedUserRaw ==
mUser)
1549#ifdef HANDLE_CHARACTER_ESCAPING
1564 str <<
'[' <<
mHost <<
']';
1589 if (mEmbeddedHeaders.get() == 0)
1591 this->mEmbeddedHeaders.reset(
new SipMessage());
1592 if (mEmbeddedHeadersText.get() && !mEmbeddedHeadersText->empty())
1594 ParseBuffer pb(mEmbeddedHeadersText->data(), mEmbeddedHeadersText->size());
1599 return *mEmbeddedHeaders;
1605 Uri* ncthis =
const_cast<Uri*
>(
this);
1613 DebugLog(<<
"Uri::parseEmbeddedHeaders");
1621 Data headerContents;
1637 pb.
data(headerName, anchor);
1642 pb.
data(headerContents, anchor);
1646 mEmbeddedHeaders->addBuffer(decodedContents);
1650 mEmbeddedHeaders->setBody(decodedContents, len);
1654 DebugLog(<<
"Uri::parseEmbeddedHeaders(" << headerName <<
", " <<
Data(decodedContents, len) <<
")");
1657 decodedContents, len);
1665 if (mEmbeddedHeaders.get())
1667 mEmbeddedHeaders->encodeEmbedded(str);
1669 else if(mEmbeddedHeadersText.get())
1672 str << *mEmbeddedHeadersText;
1695 return ParameterFactories[type](type, pb, terminators, pool);
1715#define defineParam(_enum, _name, _type, _RFC_ref_ignored) \
1716_enum##_Param::DType& \
1717Uri::param(const _enum##_Param& paramType) \
1720 _enum##_Param::Type* p = \
1721 static_cast<_enum##_Param::Type*>(getParameterByEnum(paramType.getTypeNum())); \
1724 p = new _enum##_Param::Type(paramType.getTypeNum()); \
1725 mParameters.push_back(p); \
1727 return p->value(); \
1730const _enum##_Param::DType& \
1731Uri::param(const _enum##_Param& paramType) const \
1734 _enum##_Param::Type* p = \
1735 static_cast<_enum##_Param::Type*>(getParameterByEnum(paramType.getTypeNum())); \
1738 InfoLog(<< "Missing parameter " _name " " << ParameterTypes::ParameterNames[paramType.getTypeNum()]); \
1739 DebugLog(<< *this); \
1740 throw Exception("Missing parameter " _name, __FILE__, __LINE__); \
1742 return p->value(); \
#define defineParam(_enum, _name, _type, _RFC_ref_ignored)
#define HashValueImp(type, ret)
static const Data sep("[]")
#define resip_assert(x)
This file needs to work for both C and C++ code.
static void decodeUserPreservingEscapes(ParseBuffer &pb, const char *start, Data &user, std::unique_ptr< Data > &userRaw)
static const Data bodyData("Body")
static bool initAllTables()
used as a comparator for sorting purposes
bool operator()(const Parameter *p1, const Parameter *p2) const
used as a comparator for sorting purposes This does a straight Data comparison for name and returns t...
OrderUnknownParameters()
constructor ; never called explicitly
~OrderUnknownParameters()
empty destructor
Generically represents miscellaneous parameter data.
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
EncodeStream & escapeToStream(EncodeStream &str, Predicate shouldEscape) const
Performs escaping of this Data according to the indicated Predicate.
const char * end() const noexcept
Returns a pointer to the end of the buffer used by the Data.
bool prefix(const Data &pre) const noexcept
Returns true if this Data starts with the bytes indicated by the passed-in Data.
Data substr(size_type first, size_type count=Data::npos) const
Copies a portion of this Data into a new Data.
bool empty() const noexcept
Checks whether the Data is empty.
Data & lowercase()
Converts this Data to lowercase.
size_type size() const noexcept
Returns the number of bytes in this Data.
static Data from(const T &x)
Converts from arbitrary other type to Data.
size_type find(const Data &match, size_type start=0) const
Finds a specified sequence of bytes in this Data.
static const size_type npos
Represents an impossible position; returned to indicate failure to find.
Data & schemeLowercase()
Converts this Data to lowercase, assuming this Data only consists of scheme characters.
const char * begin() const noexcept
Returns a pointer to the beginning of the buffer used by the Data.
Data & clear()
Clears the contents of this Data.
static std::bitset< 256 > toBitset(const resip::Data &chars)
Creates a bitset reflecting the contents of this data (as a set) ie.
const char * data() const noexcept
Returns a pointer to the contents of this Data.
void reserve(size_type capacity)
Guarantees that the underlying buffer used by the Data is at least the number of bytes specified.
static bool isIpV6Address(const Data &ipAddress)
static Data canonicalizeIpV6Address(const Data &ipV6Address)
Converts the printable form of an IPv6 address into consistent format so that string comparisons will...
static char * decode(const Data &input, unsigned int &decodedLength)
Represents various parameters that are indicated to be in effect merely by being present,...
virtual ParameterTypes::Type getTypeNum() const =0
Parameter *(* Factory)(ParameterTypes::Type, ParseBuffer &, const std::bitset< 256 > &terminators, PoolBase *pool)
ParameterTypes::Type getType() const
Provides string-parsing functionality with protection from buffer overflow.
void dataUnescaped(Data &data, const char *start) const
uint32_t uInt32()
dcm! – merge these, ask about length checks
CurrentPosition skipToEnd()
CurrentPosition skipWhitespace()
CurrentPosition skipToChar(char c)
CurrentPosition position() const
static bool oneOf(char c, const char *cs)
void reset(const char *pos)
CurrentPosition skipChars(const char *cs)
void assertNotEof() const
CurrentPosition skipToOneOf(const char *cs)
CurrentPosition skipChar()
void fail(const char *file, unsigned int line, const Data &errmsg=Data::Empty) const
void data(Data &data, const char *start) const
make the passed in data share memory with the buffer (uses Data::Share)
static const char * Whitespace
BaseException used to indicate parse failures.
Base class for all SIP grammar elements that can have parameters.
Parameter * getParameterByEnum(ParameterTypes::Type type) const
ParameterList mUnknownParameters
ParserCategory & operator=(const ParserCategory &rhs)
void removeParameterByEnum(ParameterTypes::Type type)
void parseParameters(ParseBuffer &pb)
ParameterList mParameters
EncodeStream & encodeParameters(EncodeStream &str) const
Encodes parameters as they should appear on the wire.
std::vector< Parameter *, StlPoolAllocator< Parameter *, PoolBase > > ParameterList
Generically represents miscellaneous parameter data that is encoded using double quotes.
Represents a SIP message.
static const char * SEMI_COLON
static const int DefaultSipsPort
static const char * LS_BRACKET
static const char * PERCENT
static const char * COLON
static const char * RS_BRACKET
static const int DefaultSipPort
static const char * QUESTION
static const char * Phone
static const char * AT_SIGN
static const char * SLASH
static const char * Postd
static const char * RA_QUOTE
static const char * EQUALS
static const char * AMPERSAND
Represents the "token" element in the RFC 3261 grammar.
Generically represents unsigned 32-bit integer values conveyed by SIP parameters.
Generically used to represent any parameter that is not known by the implmentation.
Represents the "SIP-URI" and "SIPS-URI" elements in the RFC 3261 grammar.
static EncodingTable & getGlobalNumberTable()
virtual EncodeStream & encodeParsed(EncodeStream &str) const
static bool compareUriParametersEqual(Parameter *param1, Parameter *param2)
Compares two known URI parameters for equality.
bool aorEqual(const Uri &rhs) const
Token getUserAsTelephoneSubscriber() const
Returns the user-part as a 'telephone-subscriber' grammar element (in other words,...
static void setUriUrnEncoding(unsigned char c, bool encode)
bool isEnumSearchable() const
Returns true if the uri can be converted into a string that can be used as an enum lookup.
void parseEmbeddedHeaders(ParseBuffer &pb)
virtual void parse(ParseBuffer &pb)
virtual Parameter * createParam(ParameterTypes::Type type, ParseBuffer &pb, const std::bitset< 256 > &terminators, PoolBase *pool)
bool isUserRelevant() const
Checks if this URI's scheme has sip:/sips:/tel: user-part semantics, i.e.
std::vector< Data > getEnumLookups(const std::vector< Data > &suffixes) const
Return a vector of domains to do a NAPTR lookup for enum.
bool mIsBetweenAngleQuotes
static EncodingTable & getPasswordEncodingTable()
Data getAorNoPort() const
bool operator<(const Uri &other) const
Data getAOR(bool addPort) const
Data mCanonicalHost
cache for IPv6 host comparison
bool exists(const Param< Uri > ¶mType) const
EncodeStream & encodeEmbeddedHeaders(EncodeStream &str) const
Data mNetNs
Net namespace name scoping host and port.
static void setUriPasswordEncoding(unsigned char c, bool encode)
static bool compareUriParametersLessThan(Parameter *param1, Parameter *param2)
Compares two URI parameters to determine if the first is less than the second.
std::bitset< Uri::uriEncodingTableSize > EncodingTable
Uri & operator=(const Uri &rhs)
static EncodingTable & getUserEncodingTable()
static EncodingTable & getUrnEncodingTable()
Encoding table for the NID:NSS (plus optional rq-components/fragment) of a urn: URI (RFC 8141: namest...
void getAorInternal(bool dropScheme, bool addPort, Data &aor) const
static Uri fromTel(const Uri &, const Uri &hostUri)
void remove(const Param< Uri > ¶mType)
bool userIsTelephoneSubscriber() const
Returns true if the user appears to fit the BNF for the 'telephone-subscriber' element in the RFC 326...
static EncodingTable & getLocalNumberTable()
virtual ParserCategory * clone() const
static void setUriUserEncoding(unsigned char c, bool encode)
Modifies the default URI encoding character sets.
bool operator==(const Uri &other) const
Uri getAorAsUri(TransportType transportTypeToRemoveDefaultPort=UNKNOWN_TRANSPORT) const
static bool isSignificantUriParameter(const ParameterTypes::Type type) noexcept
Checks if the URI-parameter appearing in only one URI must not be ignored when comparing the URIs.
void setUserAsTelephoneSubscriber(const Token &telephoneSubscriber)
Sets the user-part of this URI using the dial-string and parameters stored in telephoneSubscriber.
bool operator!=(const Uri &other) const
const Data & param(const ExtensionParameter ¶m) const
Const accessor for non-natively-supported parameter types.
An ostream that operates on an existing Data.
This file is used to handle compatibility fixes/tweaks so reSIProcate can function on multiple platfo...
dcm! – add UnusedChecking(_enum) below;
bool isEqualNoCase(const Data &left, const Data &right)
bool isLessThanNoCase(const Data &left, const Data &right)
static const Data parseContext("PrivacyCategory constructor")
TransportType
An enumeration of transport protocols.
static char * encode(char *buf, const char *data, unsigned int length)