📄 sipurl.cxx
字号:
/* ==================================================================== * The Vovida Software License, Version 1.0 * * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The names "VOCAL", "Vovida Open Communication Application Library", * and "Vovida Open Communication Application Library (VOCAL)" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact vocal@vovida.org. * * 4. Products derived from this software may not be called "VOCAL", nor * may "VOCAL" appear in their name, without prior written * permission of Vovida Networks, Inc. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * * ==================================================================== * * This software consists of voluntary contributions made by Vovida * Networks, Inc. and many individuals on behalf of Vovida Networks, * Inc. For more information on Vovida Networks, Inc., please see * <http://www.vovida.org/>. * */static const char* const SipUrl_cxx_Version = "$Id: SipUrl.cxx,v 1.134 2002/12/14 01:05:12 veer Exp $";#include "global.h"#include "SipUrl.hxx"#include "symbols.hxx"#include "HostMatch.hxx"#include "cpLog.h"#include "Data.hxx"#include <cassert>#include "SipUser.hxx"#include "SipTelSubscriberUser.hxx"using namespace Vocal;//const Data DefaultSipPort(DEFAULT_SIP_PORT);stringSipUrlParserException::getName( void ) const{ return "SipUrlParserException";}void SipUrl::initializeFrom(){ transportParam.erase(); maddrParam.erase(); headers.erase(); lrParam = false;} void SipUrl::initializeTo(){ transportParam.erase(); maddrParam.erase(); ttlParam.erase(); lrParam = false;}SipUrl::SipUrl(const SipUrl& src) :BaseUrl(), schemeName(src.schemeName), passwd(src.passwd), host(src.host), port(src.port), transportParam(src.transportParam), ttlParam(src.ttlParam), maddrParam(src.maddrParam), userParam(src.userParam), methodParam(src.methodParam), otherParam(src.otherParam), otherName(src.otherName), headers(src.headers), lrParam(src.lrParam), ipv6Addr(src.ipv6Addr), EscObj(src.EscObj){ if (src.user != 0) { user = src.user->duplicate(); //Sptr of BaseUser now. }}SipUrl::SipUrl( const Data& data ) throw(SipUrlParserException&) :BaseUrl(), schemeName("sip"), user(), passwd(), host(), port(), transportParam(), ttlParam(), maddrParam(), userParam(), methodParam(), otherParam(), otherName(), headers(), lrParam(false), ipv6Addr(false), EscObj(){ try { decode(data); } catch (SipUrlParserException&) { if (SipParserMode::sipParserMode()) { throw SipUrlParserException("failed in Decode", __FILE__, __LINE__, DECODE_FAILED); } }}SipUrl::SipUrl(bool lr) :BaseUrl(), schemeName("sip"), user(), passwd(), host(), port(), transportParam(), ttlParam(), maddrParam(), userParam(), methodParam(), otherParam(), otherName(), headers(), lrParam(lr), // !jf! - should be true when it is a looser router ipv6Addr(false), EscObj(){}SipUrl::~SipUrl(){}UrlTypeSipUrl::getType() const{ return SIP_URL;} Sptr<BaseUrl> SipUrl::duplicate() const{ return new SipUrl(*this);} bool SipUrl::areEqual(Sptr<BaseUrl> baseUrl) const{ if (baseUrl != 0) { return areEqual(*baseUrl); } else { return false; }} bool SipUrl::isLessThan(Sptr<BaseUrl> baseUrl) const{ if (baseUrl != 0 && baseUrl->getType() == SIP_URL) { Sptr<SipUrl> newUrl; newUrl.dynamicCast(baseUrl); assert(newUrl != 0); return ( *(this) < *(newUrl) ); } else { return false; }}boolSipUrl::areEqual(const BaseUrl& baseUrl) const{ if(baseUrl.getType() == SIP_URL) { const SipUrl& newUrl = dynamic_cast<const SipUrl&> (baseUrl); return ( *(this) == newUrl ); } else { return false; }} SipUrl& SipUrl::operator =(const SipUrl& srcUrl){ if (&srcUrl != this) { schemeName = srcUrl.schemeName; if(srcUrl.user != 0) user = srcUrl.user->duplicate(); passwd = srcUrl.passwd; host = srcUrl.host; port = srcUrl.port; transportParam = srcUrl.transportParam; ttlParam = srcUrl.ttlParam; maddrParam = srcUrl.maddrParam; userParam = srcUrl.userParam; methodParam = srcUrl.methodParam; otherParam = srcUrl.otherParam; headers = srcUrl.headers; lrParam = srcUrl.lrParam; ipv6Addr = srcUrl.ipv6Addr; if(srcUrl.EscObj != 0) EscObj = srcUrl.EscObj; } return (*this);}#define IsLess(a, b) if ((a) < (b)) return true; else if ((b) < (a)) return falsebool SipUrl::operator<(const SipUrl& src) const{ IsLess(user, src.user); //this will call SipUser, or SipTelSubscriberUsr isLessThan IsLess(passwd, src.passwd); IsLess(ttlParam, src.ttlParam); IsLess(maddrParam, src.maddrParam); IsLess(userParam, src.userParam); IsLess(methodParam, src.methodParam); IsLess(otherParam, src.otherParam); IsLess(port, src.port); IsLess(headers, src.headers); return false;}#undef IsLessbool SipUrl::operator>(const SipUrl& srcUrl) const{ //compare reverse. return ( srcUrl < (*this) );} bool SipUrl::operator ==(const SipUrl& srcUrl) const{ bool equal = false; cpLog(LOG_DEBUG_STACK, "Url operator == function"); if (user != 0) { cpLog(LOG_DEBUG_STACK, "this.user= %s", user->encode().logData()); } if (srcUrl.user != 0) { cpLog(LOG_DEBUG_STACK, "other.user= %s", srcUrl.user->encode().logData()); } cpLog(LOG_DEBUG_STACK, "this.passwd= %s" , passwd.logData()); cpLog(LOG_DEBUG_STACK, "other.passwd= %s", srcUrl.passwd.logData()); cpLog(LOG_DEBUG_STACK, "this.host= %s" , host.logData()); cpLog(LOG_DEBUG_STACK, "other.host= %s", srcUrl.host.logData()); cpLog(LOG_DEBUG_STACK, "this.ttlParam= %s", ttlParam.logData() ); cpLog(LOG_DEBUG_STACK, "other.ttlParam= %s" , srcUrl.ttlParam.logData()); cpLog(LOG_DEBUG_STACK, "this.maddrParam= %s" , maddrParam.logData()); cpLog(LOG_DEBUG_STACK, "other.maddrParam= %s" , srcUrl.maddrParam.logData()); cpLog(LOG_DEBUG_STACK, "this.userParam= %s " , userParam.logData()); cpLog(LOG_DEBUG_STACK, "other.userParam= %s" , srcUrl.userParam.logData()); cpLog(LOG_DEBUG_STACK, "this.methodParam= %s" , methodParam.logData()); cpLog(LOG_DEBUG_STACK, "other.methodParam= %s" , srcUrl.methodParam.logData()); cpLog(LOG_DEBUG_STACK, "this.otherParam= %s", otherParam.logData()); cpLog(LOG_DEBUG_STACK, "other.otherParam= %s" , srcUrl.otherParam.logData()); cpLog(LOG_DEBUG_STACK, "this.headers = %s" , headers.logData()); cpLog(LOG_DEBUG_STACK, "other.headers = %s" , srcUrl.headers.logData()); //compare user if it is defined. if ( (user != 0) && (srcUrl.user != 0) ) { equal = ( user->areEqual(srcUrl.user) ); } else if ( (user.getPtr() == 0) && (srcUrl.user.getPtr() == 0) ) { //both are empty. equal = true; } else { equal = false; } //take care of some header comparsions requiring case sensitivity, and //some requiring case-insensitivity. equal = (equal && (isEqualNoCase(schemeName, srcUrl.schemeName)) && (passwd == srcUrl.passwd) && (isEqualNoCase(host, srcUrl.host) ) && (isEqualNoCase(ttlParam,srcUrl.ttlParam)) && (maddrParam == srcUrl.maddrParam) && (isEqualNoCase(userParam,srcUrl.userParam) ) && (methodParam == srcUrl.methodParam) && (isEqualNoCase(otherParam, srcUrl.otherParam)) && (isEqualNoCase(headers, srcUrl.headers)) ); //compare the parameters having default values. if ( srcUrl.port.length() && port.length() ) { equal = (equal && (port == srcUrl.port)); } else { // one or the other is a default // the two ? : expressions evaluate to either the default // value (in this case Data("5060") if there is nothing in the // port) or the port (which is a Data) if there is something // there. Thus, when they are compared via == , you do a // comparison which substitutes the default value if they are // not supplied. equal = (equal && (( (srcUrl.port.length() == 0) ? Data("5060") : srcUrl.port) == ( (port.length() == 0) ? Data("5060") : port))); } if (( srcUrl.transportParam.length() && transportParam.length()) ) { equal = (equal && (transportParam == srcUrl.transportParam)); } else { // the two ? : expressions evaluate to either the default // value (in this case Data("udp") if there is nothing in the // port) or the port (which is a Data) if there is something // there. Thus, when they are compared via == , you do a // comparison which substitutes the default value if they are // not supplied. equal = (equal && (( (srcUrl.transportParam.length() == 0) ? Data("udp") : srcUrl.transportParam) == ( (transportParam.length() == 0) ? Data("udp") : transportParam))); } cpLog(LOG_DEBUG_STACK, "sipUrl comparison: , returning: %s", (equal == true ? "true" : "false" )); return equal; } voidSipUrl::decode( const Data& urlstr ){ if (fastDecode(urlstr) == false) { cpLog(LOG_ERR, "Failed in Decode (SIP_URL): %s", urlstr.logData()); throw SipUrlParserException("Failed in Decode (SIP_URL)", __FILE__, __LINE__, NOT_VALID_URL_DATA); } //cpLog(LOG_DEBUG_STACK, "completed decoding in the SipUrl");} // SipUrl::decodeboolSipUrl::fastDecode( Data myData ){ // new decoder, hopefully faster bool userValid = false; bool hostValid = false; bool portValid = false; bool userParamValid = false; // used to figure if the user is //telUser or sipUser to parse differently. bool parseFailed; string::size_type keyPos; string tmpmyData; string workstring = myData.convertString(); if((keyPos = workstring.find_first_of("?")) != string::npos){ string escData; tmpmyData = workstring.substr(0, keyPos); escData = workstring.substr(keyPos+1, string::npos); EscObj = new EmbeddedObj(escData); myData = tmpmyData; } Data userInfo; Data urlType = myData.parse(":", &parseFailed); if(parseFailed) { cpLog(LOG_DEBUG, "parse failed: could not find ':' separating URL type from body: %s", myData.logData()); return false; } if (!isEqualNoCase(urlType, "sip") ) { cpLog(LOG_DEBUG, "parse failed: scheme not SIP: %s", myData.logData()); return false; } //set it. schemeName = urlType; // now, either user or host, depending char matchedChar; Data tmpData; bool ret; tmpData = myData.matchChar("@", &matchedChar); if(matchedChar == '@') { // this really is a user userInfo = tmpData; userValid = true; // the next thing must be a host, optionally followed by a port //Check to see if the address is a IPV6 address host = myData.matchChar("[", &matchedChar); if(matchedChar == '[') { //Ok this is a IPv6 address ret = parseIpv6Address(myData); if(!ret) return ret; } if(host.length()) { //It was a IPV6 address //eat away extra :; Data eData = myData.matchChar(":;", &matchedChar); hostValid = true; } else { //Take the address to be IPV4 address host = myData.matchChar(":;", &matchedChar); if(host.length()) hostValid = true; } if (matchedChar == ':') { // the next bit is a port port = myData.matchChar(";", &matchedChar); portValid = true; if(matchedChar == ';') { // the rest is fine } else { // no match -- the rest of myData must be a port port = myData; myData.erase(); } } else if(matchedChar == ';') { } else { // maybe there is no separator, so the rest has to be a host host = myData; myData.erase(); hostValid = true; } } else { //No user part, so parse the host tmpData = myData.matchChar("[", &matchedChar); if(matchedChar == '[') { //Ok this is a IPv6 address ret = parseIpv6Address(myData); if(!ret) return ret; hostValid = true; } if(host.length()) { //Since it was already IPV6 address //eat away extra :; Data eData = myData.matchChar(":;", &matchedChar); } else { host = myData.matchChar(":;", &matchedChar); if(host.length()) hostValid = true; } if (matchedChar == ':') { // this is not a user -- this is a host port = myData.matchChar(";", &matchedChar); if(matchedChar == ';') { // this is a port, if there is anything portValid = true; } else { // myData must contain the port port = myData; myData.erase(); portValid = true; } } else if (matchedChar == ';') { //No port do nothing } else if(!hostValid) { host = myData; hostValid = true; myData.erase(); } } if (!hostValid) { return false; } if (portValid) { for (int i=0; i<port.length(); i++) { if (!isdigit(port[i])) { return false; } } } // now, look for options, if there are any bool done = false; bool matchedParam = false; while(!done) { // look for an equal sign Data key = myData.matchChar("=", &matchedChar); Data value; if(matchedChar == '=') { matchedParam = true; // find the value value = myData.matchChar(";?", &matchedChar); if((matchedChar != ';') && (matchedChar != '?')) { // did not match, so this must be the last parameter value = myData; myData.erase(); } else if(matchedChar == '?') { //Rest of it is Headers headers = myData; myData.erase(); matchedParam = false; } // do something with the key-value pair key.removeSpaces(); if(key == "user") { // do something here userParamValid = true; userParam = value; } else if(key == "transport") { // do something here transportParam = value; } else if(key == "ttl") { ttlParam = value; } else if(key == "maddr") { maddrParam = value; } else if(key == "method") { methodParam = value; } else if (matchedParam) { if (userParam == "phone") {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -