reSIProcate/stack  9694
BranchParameter.cxx
Go to the documentation of this file.
00001 #if defined(HAVE_CONFIG_H)
00002 #include "config.h"
00003 #endif
00004 
00005 #include <cassert>
00006 #include "resip/stack/BranchParameter.hxx"
00007 #include "resip/stack/Symbols.hxx"
00008 #include "rutil/ParseBuffer.hxx"
00009 #include "rutil/Random.hxx"
00010 #include "rutil/Coders.hxx"
00011 #include "rutil/ParseException.hxx"
00012 
00013 #include "rutil/Logger.hxx"
00014 #include "rutil/WinLeakCheck.hxx"
00015 
00016 using namespace resip;
00017 using namespace std;
00018 
00019 #define RESIPROCATE_SUBSYSTEM Subsystem::SIP
00020 
00021 BranchParameter::BranchParameter(ParameterTypes::Type type,
00022                                  ParseBuffer& pb, 
00023                                  const std::bitset<256>& terminators)
00024    : Parameter(type), 
00025      mHasMagicCookie(false),
00026      mIsMyBranch(false),
00027      mTransactionId(),
00028      mTransportSeq(1),
00029      mClientData(),
00030      mInteropMagicCookie(0),
00031      mSigcompCompartment()
00032 {
00033    try
00034    {
00035       pb.skipWhitespace();
00036       pb.skipChar(Symbols::EQUALS[0]);
00037       pb.skipWhitespace();
00038       if(memcmp(pb.position(), Symbols::MagicCookie, 7) == 0)
00039       {
00040          mHasMagicCookie=true;
00041          pb.skipN(7);
00042       }
00043       // !bwc! This no-case comparison is expensive; only do it if the case-
00044       // sensitive comparison fails.
00045       else if(strncasecmp(pb.position(), Symbols::MagicCookie, 7) == 0)
00046       {
00047          mHasMagicCookie=true;
00048          mInteropMagicCookie = new Data(pb.position(), 7);
00049          pb.skipN(7);
00050       }
00051       
00052       const char* start = pb.position();
00053       static std::bitset<256> delimiter=Data::toBitset("\r\n\t ;=?>");
00054 
00055       if (mHasMagicCookie &&
00056           (pb.end() - start > 8) &&
00057           // look for prefix cookie (maybe make this bigger?)
00058           memcmp(start, Symbols::resipCookie, 8) == 0)
00059       {
00060          // ?bwc? Wrap this stuff in try/catch, just in case of false positives?
00061          const char* curr=start;
00062          mIsMyBranch = true;
00063          pb.skipN(8);
00064 
00065          mTransportSeq=pb.uInt32();
00066 
00067          curr=pb.skipChar('-');
00068          pb.skipToChar('-');
00069          Data encoded;
00070          pb.data(encoded, curr);
00071          if(!encoded.empty())
00072          {
00073             // !bwc! Expensive! Also, Base64 isn't case-insensitive.
00074             mClientData = encoded.base64decode();
00075          }
00076 
00077          curr=pb.skipChar('-');
00078          pb.skipToChar('-');
00079          pb.data(encoded,curr);
00080          if(!encoded.empty())
00081          {
00082             // !bwc! Expensive! Also, Base64 isn't case-insensitive.
00083             mSigcompCompartment = encoded.base64decode();
00084          }
00085 
00086          start=pb.skipChar('-');
00087       }
00088       pb.skipToOneOf(delimiter);
00089       pb.data(mTransactionId, start);
00090    }
00091    catch(resip::ParseException& e)
00092    {
00093       mTransactionId=Random::getRandomHex(8);
00094       throw e;
00095    }
00096 }
00097 
00098 BranchParameter::BranchParameter(ParameterTypes::Type type)
00099    : Parameter(type),
00100      mHasMagicCookie(true),
00101      mIsMyBranch(true),
00102      mTransactionId(Random::getRandomHex(8)),
00103      mTransportSeq(1),
00104      mInteropMagicCookie(0),
00105      mSigcompCompartment()
00106 {
00107 }
00108 
00109 BranchParameter::BranchParameter(const BranchParameter& other)
00110    : Parameter(other), 
00111      mHasMagicCookie(other.mHasMagicCookie),
00112      mIsMyBranch(other.mIsMyBranch),
00113      mTransactionId(other.mTransactionId),
00114      mTransportSeq(other.mTransportSeq),
00115      mClientData(other.mClientData),
00116      mSigcompCompartment(other.mSigcompCompartment)
00117 {
00118    if (other.mInteropMagicCookie)
00119    {
00120       mInteropMagicCookie = new Data(*other.mInteropMagicCookie);
00121    }
00122    else
00123    {
00124       mInteropMagicCookie = 0;
00125    }
00126 }
00127 
00128 BranchParameter::~BranchParameter()
00129 {
00130    delete mInteropMagicCookie;
00131 }
00132 
00133 BranchParameter& 
00134 BranchParameter::operator=(const BranchParameter& other)
00135 {
00136    if (this != &other)
00137    {
00138       mHasMagicCookie = other.mHasMagicCookie;
00139       mIsMyBranch = other.mIsMyBranch;
00140       mTransactionId = other.mTransactionId;
00141       mTransportSeq = other.mTransportSeq;
00142       mClientData = other.mClientData;
00143       mSigcompCompartment = other.mSigcompCompartment;
00144       if (other.mInteropMagicCookie)
00145       {
00146          delete mInteropMagicCookie;         
00147          mInteropMagicCookie = new Data(*other.mInteropMagicCookie);
00148       }
00149       else
00150       {
00151          delete mInteropMagicCookie;
00152          mInteropMagicCookie = 0;
00153       }
00154    }
00155    return *this;
00156 }
00157 
00158 bool
00159 BranchParameter::operator==(const BranchParameter& other)
00160 {
00161    if (mIsMyBranch != other.mIsMyBranch ||
00162        mHasMagicCookie != other.mHasMagicCookie ||
00163        mTransportSeq != other.mTransportSeq ||
00164        mTransactionId != other.mTransactionId ||
00165        mClientData != other.mClientData ||
00166        mSigcompCompartment != other.mSigcompCompartment)
00167    {
00168       return false;
00169    }
00170    return true;
00171 }
00172 
00173 bool
00174 BranchParameter::hasMagicCookie() const
00175 {
00176    return mHasMagicCookie;
00177 }
00178 
00179 const Data& 
00180 BranchParameter::getTransactionId() const
00181 {
00182    return mTransactionId;
00183 }
00184 
00185 void
00186 BranchParameter::incrementTransportSequence()
00187 {
00188    assert(mIsMyBranch);
00189    mTransportSeq++;
00190 }
00191 
00192 Data&
00193 BranchParameter::clientData()
00194 {
00195     return mClientData;
00196 }
00197 
00198 const Data&
00199 BranchParameter::clientData() const
00200 {
00201     return mClientData;
00202 }
00203 
00207 void
00208 BranchParameter::setSigcompCompartment(const Data &id)
00209 {
00210   if (id.size() == 0)
00211   {
00212     mSigcompCompartment = Data::Empty;
00213   }
00214 
00215   // These will often (but not always) be UUID URNs in angle brackets;
00216   // e.g.: <urn:uuid:fa33c72d-121f-47e8-42e2-1eb6e24aba64>
00217 
00218   // Ideally, we would detect this, strip out everything that isn't
00219   // hex, and convert the hex to raw data.
00220 
00221   mSigcompCompartment = id;
00222 }
00223 
00224 Data
00225 BranchParameter::getSigcompCompartment() const
00226 {
00227   return mSigcompCompartment;
00228 }
00229 
00230 void
00231 BranchParameter::reset(const Data& transactionId)
00232 {
00233    mHasMagicCookie = true;
00234    mIsMyBranch = true;
00235    delete mInteropMagicCookie;
00236    mInteropMagicCookie = 0;   
00237 
00238    mSigcompCompartment = Data::Empty;
00239 
00240    mTransportSeq = 1;
00241    if (!transactionId.empty())
00242    {
00243       mTransactionId = transactionId;
00244    }
00245    else
00246    {
00247       mTransactionId = Random::getRandomHex(8);
00248    }
00249 }
00250 
00251 Parameter* 
00252 BranchParameter::clone() const
00253 {
00254    return new BranchParameter(*this);
00255 }
00256 
00257 EncodeStream& 
00258 BranchParameter::encode(EncodeStream& stream) const
00259 {
00260    stream << getName() << Symbols::EQUALS;
00261    if (mHasMagicCookie)
00262    {
00263       if (mInteropMagicCookie)
00264       {
00265          stream << *mInteropMagicCookie;         
00266       }
00267       else
00268       {
00269          stream << Symbols::MagicCookie;
00270       }
00271    }
00272    if (mIsMyBranch)
00273    {
00274       stream << Symbols::resipCookie;
00275       stream << mTransportSeq;
00276       stream << Symbols::DASH;
00277       if(!mClientData.empty()) // base64encode() makes copies
00278       {
00279          // !bwc! We should be using hex encoding; branch params are supposed to
00280          // be case-insensitive.
00281          stream << mClientData.base64encode(true/*safe URL*/);
00282       }
00283       stream << Symbols::DASH;
00284       if(!mSigcompCompartment.empty()) // base64encode() makes copies
00285       {
00286          // !bwc! We should be using hex encoding; branch params are supposed to
00287          // be case-insensitive.
00288          stream << mSigcompCompartment.base64encode(true);
00289       }
00290       stream << Symbols::DASH;
00291    }
00292    stream << mTransactionId;
00293       
00294    return stream;
00295 }
00296 
00297 
00298 /* ====================================================================
00299  * The Vovida Software License, Version 1.0 
00300  * 
00301  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00302  * 
00303  * Redistribution and use in source and binary forms, with or without
00304  * modification, are permitted provided that the following conditions
00305  * are met:
00306  * 
00307  * 1. Redistributions of source code must retain the above copyright
00308  *    notice, this list of conditions and the following disclaimer.
00309  * 
00310  * 2. Redistributions in binary form must reproduce the above copyright
00311  *    notice, this list of conditions and the following disclaimer in
00312  *    the documentation and/or other materials provided with the
00313  *    distribution.
00314  * 
00315  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00316  *    and "Vovida Open Communication Application Library (VOCAL)" must
00317  *    not be used to endorse or promote products derived from this
00318  *    software without prior written permission. For written
00319  *    permission, please contact vocal@vovida.org.
00320  *
00321  * 4. Products derived from this software may not be called "VOCAL", nor
00322  *    may "VOCAL" appear in their name, without prior written
00323  *    permission of Vovida Networks, Inc.
00324  * 
00325  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00326  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00327  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00328  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00329  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00330  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00331  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00332  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00333  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00334  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00335  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00336  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00337  * DAMAGE.
00338  * 
00339  * ====================================================================
00340  * 
00341  * This software consists of voluntary contributions made by Vovida
00342  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00343  * Inc.  For more information on Vovida Networks, Inc., please see
00344  * <http://www.vovida.org/>.
00345  *
00346  */