reSIProcate/stack  9694
Via.cxx
Go to the documentation of this file.
00001 #if defined(HAVE_CONFIG_H)
00002 #include "config.h"
00003 #endif
00004 
00005 #include "resip/stack/Via.hxx"
00006 #include "rutil/DnsUtil.hxx"
00007 #include "rutil/Logger.hxx"
00008 #include "rutil/ParseBuffer.hxx"
00009 //#include "rutil/WinLeakCheck.hxx"  // not compatible with placement new used below
00010 
00011 using namespace resip;
00012 using namespace std;
00013 
00014 #define RESIPROCATE_SUBSYSTEM Subsystem::SIP
00015 
00016 
00017 //====================
00018 // Via:
00019 //====================
00020 Via::Via() 
00021    : ParserCategory(), 
00022      mProtocolName(Data::Share,Symbols::ProtocolName),
00023      mProtocolVersion(Data::Share,Symbols::ProtocolVersion),
00024      mTransport(),
00025      mSentHost(),
00026      mSentPort(0) 
00027 {
00028    // insert a branch in all Vias (default constructor)
00029    this->param(p_branch);
00030    this->param(p_rport); // add the rport parameter by default as per rfc 3581
00031 }
00032 
00033 Via::Via(const HeaderFieldValue& hfv, 
00034          Headers::Type type,
00035          PoolBase* pool) 
00036    : ParserCategory(hfv, type, pool),
00037      mProtocolName(Data::Share,Symbols::ProtocolName),
00038      mProtocolVersion(Data::Share,Symbols::ProtocolVersion),
00039      mTransport(Data::Share,Symbols::UDP), // !jf! 
00040      mSentHost(),
00041      mSentPort(-1) 
00042 {}
00043 
00044 Via::Via(const Via& rhs,
00045          PoolBase* pool)
00046    : ParserCategory(rhs, pool),
00047      mProtocolName(rhs.mProtocolName),
00048      mProtocolVersion(rhs.mProtocolVersion),
00049      mTransport(rhs.mTransport),
00050      mSentHost(rhs.mSentHost),
00051      mSentPort(rhs.mSentPort)
00052 {
00053 }
00054 
00055 Via&
00056 Via::operator=(const Via& rhs)
00057 {
00058    if (this != &rhs)
00059    {
00060       ParserCategory::operator=(rhs);
00061       mProtocolName = rhs.mProtocolName;
00062       mProtocolVersion = rhs.mProtocolVersion;
00063       mTransport = rhs.mTransport;
00064       mSentHost = rhs.mSentHost;
00065       mSentPort = rhs.mSentPort;
00066    }
00067    return *this;
00068 }
00069 
00070 ParserCategory *
00071 Via::clone() const
00072 {
00073    return new Via(*this);
00074 }
00075 
00076 ParserCategory *
00077 Via::clone(void* location) const
00078 {
00079    return new (location) Via(*this);
00080 }
00081 
00082 ParserCategory* 
00083 Via::clone(PoolBase* pool) const
00084 {
00085    return new (pool) Via(*this, pool);
00086 }
00087 
00088 Data& 
00089 Via::protocolName()
00090 {
00091    checkParsed(); 
00092    return mProtocolName;
00093 }
00094 
00095 const Data& 
00096 Via::protocolName() const 
00097 {
00098    checkParsed(); 
00099    return mProtocolName;
00100 }
00101 
00102 Data& 
00103 Via::protocolVersion()
00104 {
00105    checkParsed(); 
00106    return mProtocolVersion;
00107 }
00108 
00109 const Data& 
00110 Via::protocolVersion() const 
00111 {
00112    checkParsed(); 
00113    return mProtocolVersion;
00114 }
00115 
00116 Data& Via::
00117 transport()
00118 {
00119    checkParsed(); 
00120    return mTransport;
00121 }
00122 
00123 const Data& Via::
00124 transport() const 
00125 {
00126    checkParsed(); 
00127    return mTransport;
00128 }
00129 
00130 Data& 
00131 Via::sentHost()
00132 {
00133    checkParsed(); 
00134    return mSentHost;
00135 }
00136 
00137 const Data&
00138  Via::sentHost() const
00139 {
00140    checkParsed(); 
00141    return mSentHost;
00142 }
00143 
00144 int& 
00145 Via::sentPort()
00146 {
00147    checkParsed(); 
00148    return mSentPort;
00149 }
00150 
00151 int
00152 Via::sentPort() const 
00153 {
00154    checkParsed(); 
00155    return mSentPort;
00156 }
00157 
00158 void
00159 Via::parse(ParseBuffer& pb)
00160 {
00161    const char* startMark;
00162    startMark = pb.skipWhitespace();
00163    static std::bitset<256> wos=Data::toBitset("\r\n\t /");
00164    pb.skipToOneOf(wos);
00165    pb.data(mProtocolName, startMark);
00166    pb.skipToChar('/');
00167    pb.skipChar();
00168    startMark = pb.skipWhitespace();
00169    pb.skipToOneOf(wos);
00170    pb.data(mProtocolVersion, startMark);
00171 
00172    pb.skipToChar('/');
00173    pb.skipChar();
00174    startMark = pb.skipWhitespace();
00175 
00176    // !jf! this should really be skipTokenChar() since for instance, if the
00177    // protocol token is missing it will read the rest of the Via into this field
00178    pb.skipNonWhitespace(); 
00179    pb.data(mTransport, startMark);
00180    
00181    startMark = pb.skipWhitespace();
00182    pb.assertNotEof();
00183    if (*startMark == '[')
00184    {
00185       startMark = pb.skipChar();
00186       pb.skipToChar(']');
00187       pb.data(mSentHost, startMark);
00188       // .bwc. We do not save this canonicalization, since we weren't doing so
00189       // before. This may change soon.
00190       Data canonicalizedHost=DnsUtil::canonicalizeIpV6Address(mSentHost);
00191       if(canonicalizedHost.empty())
00192       {
00193          // .bwc. So the V6 addy is garbage.
00194          throw ParseException("Unparsable V6 address (note, this might"
00195                                     " be unparsable because IPV6 support is not"
00196                                     " enabled)", "Via",
00197                                        __FILE__,
00198                                        __LINE__);
00199       }
00200       pb.skipChar();
00201    }
00202    else
00203    {
00204       // .bwc. If we hit whitespace, we have the host.
00205       static std::bitset<256> delimiter=Data::toBitset(";: \t\r\n");
00206       pb.skipToOneOf(delimiter);
00207       pb.data(mSentHost, startMark);
00208    }
00209 
00210    pb.skipToOneOf(";:");
00211    
00212    if (!pb.eof() && *pb.position() == ':')
00213    {
00214       startMark = pb.skipChar(':');
00215       mSentPort = pb.integer();
00216       static std::bitset<256> delimiter=Data::toBitset("; \t\r\n");
00217       pb.skipToOneOf(delimiter);
00218    }
00219    else
00220    {
00221       mSentPort = 0;
00222    }
00223    parseParameters(pb);
00224 }
00225 
00226 EncodeStream&
00227 Via::encodeParsed(EncodeStream& str) const
00228 {
00229    str << mProtocolName << Symbols::SLASH << mProtocolVersion << Symbols::SLASH << mTransport 
00230        << Symbols::SPACE;
00231 
00232    if (DnsUtil::isIpV6Address(mSentHost))
00233    {
00234       str << '[' << mSentHost << ']';
00235    }
00236    else
00237    {
00238       str << mSentHost;
00239    }
00240    
00241    if (mSentPort != 0)
00242    {
00243       str << Symbols::COLON << mSentPort;
00244    }
00245    encodeParameters(str);
00246    return str;
00247 }
00248 
00249 ParameterTypes::Factory Via::ParameterFactories[ParameterTypes::MAX_PARAMETER]={0};
00250 
00251 Parameter* 
00252 Via::createParam(ParameterTypes::Type type, ParseBuffer& pb, const std::bitset<256>& terminators, PoolBase* pool)
00253 {
00254    if(type > ParameterTypes::UNKNOWN && type < ParameterTypes::MAX_PARAMETER && ParameterFactories[type])
00255    {
00256       return ParameterFactories[type](type, pb, terminators, pool);
00257    }
00258    return 0;
00259 }
00260 
00261 bool 
00262 Via::exists(const Param<Via>& paramType) const
00263 {
00264     checkParsed();
00265     bool ret = getParameterByEnum(paramType.getTypeNum()) != NULL;
00266     return ret;
00267 }
00268 
00269 void 
00270 Via::remove(const Param<Via>& paramType)
00271 {
00272     checkParsed();
00273     removeParameterByEnum(paramType.getTypeNum());
00274 }
00275 
00276 #define defineParam(_enum, _name, _type, _RFC_ref_ignored)                                                      \
00277 _enum##_Param::DType&                                                                                           \
00278 Via::param(const _enum##_Param& paramType)                                                           \
00279 {                                                                                                               \
00280    checkParsed();                                                                                               \
00281    _enum##_Param::Type* p =                                                                                     \
00282       static_cast<_enum##_Param::Type*>(getParameterByEnum(paramType.getTypeNum()));                            \
00283    if (!p)                                                                                                      \
00284    {                                                                                                            \
00285       p = new _enum##_Param::Type(paramType.getTypeNum());                                                      \
00286       mParameters.push_back(p);                                                                                 \
00287    }                                                                                                            \
00288    return p->value();                                                                                           \
00289 }                                                                                                               \
00290                                                                                                                 \
00291 const _enum##_Param::DType&                                                                                     \
00292 Via::param(const _enum##_Param& paramType) const                                                     \
00293 {                                                                                                               \
00294    checkParsed();                                                                                               \
00295    _enum##_Param::Type* p =                                                                                     \
00296       static_cast<_enum##_Param::Type*>(getParameterByEnum(paramType.getTypeNum()));                            \
00297    if (!p)                                                                                                      \
00298    {                                                                                                            \
00299       InfoLog(<< "Missing parameter " _name " " << ParameterTypes::ParameterNames[paramType.getTypeNum()]);     \
00300       DebugLog(<< *this);                                                                                       \
00301       throw Exception("Missing parameter " _name, __FILE__, __LINE__);                                          \
00302    }                                                                                                            \
00303    return p->value();                                                                                           \
00304 }
00305 
00306 defineParam(branch, "branch", BranchParameter, "RFC 3261");
00307 defineParam(comp, "comp", DataParameter, "RFC 3486");
00308 defineParam(received, "received", DataParameter, "RFC 3261");
00309 defineParam(rport, "rport", RportParameter, "RFC 3581");
00310 defineParam(ttl, "ttl", UInt32Parameter, "RFC 3261");
00311 defineParam(sigcompId, "sigcomp-id", QuotedDataParameter, "RFC 5049");
00312 defineParam(maddr, "maddr", DataParameter, "RFC 3261");
00313 
00314 #undef defineParam
00315 
00316 /* ====================================================================
00317  * The Vovida Software License, Version 1.0 
00318  * 
00319  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00320  * 
00321  * Redistribution and use in source and binary forms, with or without
00322  * modification, are permitted provided that the following conditions
00323  * are met:
00324  * 
00325  * 1. Redistributions of source code must retain the above copyright
00326  *    notice, this list of conditions and the following disclaimer.
00327  * 
00328  * 2. Redistributions in binary form must reproduce the above copyright
00329  *    notice, this list of conditions and the following disclaimer in
00330  *    the documentation and/or other materials provided with the
00331  *    distribution.
00332  * 
00333  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00334  *    and "Vovida Open Communication Application Library (VOCAL)" must
00335  *    not be used to endorse or promote products derived from this
00336  *    software without prior written permission. For written
00337  *    permission, please contact vocal@vovida.org.
00338  *
00339  * 4. Products derived from this software may not be called "VOCAL", nor
00340  *    may "VOCAL" appear in their name, without prior written
00341  *    permission of Vovida Networks, Inc.
00342  * 
00343  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00344  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00345  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00346  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00347  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00348  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00349  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00350  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00351  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00352  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00353  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00354  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00355  * DAMAGE.
00356  * 
00357  * ====================================================================
00358  * 
00359  * This software consists of voluntary contributions made by Vovida
00360  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00361  * Inc.  For more information on Vovida Networks, Inc., please see
00362  * <http://www.vovida.org/>.
00363  *
00364  */