reSIProcate/stack  9694
SipFrag.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/MsgHeaderScanner.hxx"
00006 #include "resip/stack/SipFrag.hxx"
00007 #include "resip/stack/SipMessage.hxx"
00008 #include "rutil/Logger.hxx"
00009 #include "rutil/ParseBuffer.hxx"
00010 #include "rutil/WinLeakCheck.hxx"
00011 
00012 using namespace resip;
00013 using namespace std;
00014 
00015 #define RESIPROCATE_SUBSYSTEM Subsystem::SIP
00016 
00017 bool
00018 SipFrag::init()
00019 {
00020    static ContentsFactory<SipFrag> factory;
00021    (void)factory;
00022    return true;
00023 }
00024 
00025 SipFrag::SipFrag(const Mime& contentsType)
00026    : Contents(contentsType),
00027      mMessage(new SipMessage())
00028 {}
00029 
00030 SipFrag::SipFrag(const HeaderFieldValue& hfv, const Mime& contentsType)
00031    : Contents(hfv, HeaderFieldValue::CopyPadding, contentsType),
00032      mMessage(0)
00033 {
00034 }
00035 
00036 SipFrag::SipFrag(const SipFrag& rhs)
00037    : Contents(rhs,HeaderFieldValue::CopyPadding),
00038      mMessage(rhs.mMessage ? new SipMessage(*rhs.mMessage) : 0)
00039 {
00040 }
00041 
00042 SipFrag::~SipFrag()
00043 {
00044    delete mMessage;
00045 }
00046 
00047 SipFrag&
00048 SipFrag::operator=(const SipFrag& rhs)
00049 {
00050    if (this != &rhs)
00051    {
00052       Contents::operator=(rhs);
00053       delete mMessage;
00054       if (rhs.mMessage)
00055       {
00056          mMessage = new SipMessage(*rhs.mMessage);
00057       }
00058       else
00059       {
00060          mMessage = 0;
00061       }
00062    }
00063    
00064    return *this;
00065 }
00066 
00067 Contents* 
00068 SipFrag::clone() const
00069 {
00070    return new SipFrag(*this);
00071 }
00072 
00073 const Mime& 
00074 SipFrag::getStaticType() 
00075 {
00076    static Mime type("message", "sipfrag");
00077    //static Mime type("application", "sipfrag");
00078    return type;
00079 }
00080 
00081 SipMessage& 
00082 SipFrag::message() 
00083 {
00084    checkParsed(); 
00085    return *mMessage;
00086 }
00087 
00088 const SipMessage& 
00089 SipFrag::message() const 
00090 {
00091    checkParsed(); 
00092    return *mMessage;
00093 }
00094 
00095 EncodeStream& 
00096 SipFrag::encodeParsed(EncodeStream& str) const
00097 {
00098    mMessage->encodeSipFrag(str);
00099 
00100    return str;
00101 }
00102 
00103 bool 
00104 SipFrag::hasStartLine(char* buffer, int size)
00105 {
00106 #if 0
00107 
00108    //difficult. Better here than in the MsgHeaderScanner. There's also proabably a
00109    //way to make a header that matches the requestLine check which isn't a
00110    //request line.
00111 
00112    ParseBuffer pbCheck(buffer, size);
00113    pbCheck.skipWhitespace(); //gratuitous?
00114 
00116    if ((pbCheck.end() - pbCheck.position()) > 4 &&
00117       strncmp(pbCheck.position(), "SIP/", 4) == 0)
00118    {
00119       return true;
00120    }
00121    else
00122    {
00123       pbCheck.skipToChars(Symbols::CRLF);
00124       if (pbCheck.eof()) 
00125       {
00126          //false positive, let MsgHeaderScanner sort the exact error out
00127          return true; 
00128       }
00129       
00130       pbCheck.skipBackToChar(Symbols::SPACE[0]);
00131       if (pbCheck.position() == pbCheck.start()) 
00132       {
00133          return false;
00134       }
00135          
00136       if ((pbCheck.end() - pbCheck.position()) > 4 &&
00137           strncmp(pbCheck.position(), "SIP/", 4) == 0)
00138       {
00139          return true;
00140       }
00141       else
00142       {
00143          return false;
00144       }
00145    }
00146 #else   
00147 
00148    ParseBuffer pbCheck(buffer, size);
00149    pbCheck.skipWhitespace(); //gratuitous?
00150    pbCheck.skipToOneOf(" \t:\r\n");
00151    while(!pbCheck.eof())
00152    {
00153       switch(*pbCheck.position())
00154       {
00155          case ':':
00156             return false;
00157          case ' ':
00158          case '\t':
00159             pbCheck.skipChar();
00160             break;             
00161          case '\r':
00162          case '\n':
00163             return false;
00164          default:
00165             return true;
00166       }
00167    }
00168    return true;  //false positive, let MsgHeaderScanner sort the exact error out
00169 #endif
00170 }
00171 
00172 void 
00173 SipFrag::parse(ParseBuffer& pb)
00174 {
00175 //   DebugLog(<< "SipFrag::parse: " << pb.position());
00176 
00177    mMessage = new SipMessage();
00178 
00179    pb.assertNotEof();
00180    const char *constBuffer = pb.position();
00181    char *buffer = const_cast<char *>(constBuffer);
00182 
00183    size_t size = pb.end() - pb.position();
00184 
00185    // !ah! removed size check .. process() cannot process more
00186    // than size bytes of the message.
00187 
00188 
00189    MsgHeaderScanner msgHeaderScanner;
00190    msgHeaderScanner.prepareForFrag(mMessage, hasStartLine(buffer, (int)size));
00191    enum { sentinelLength = 4 };  // Two carriage return / line feed pairs.
00192    //char saveTermCharArray[sentinelLength];
00193    static const char* sentinel="\r\n\r\n";
00194    char *termCharArray = buffer + size;
00195    memcpy(scratchpad,termCharArray,4);
00196    
00197    /*saveTermCharArray[0] = termCharArray[0];
00198    saveTermCharArray[1] = termCharArray[1];
00199    saveTermCharArray[2] = termCharArray[2];
00200    saveTermCharArray[3] = termCharArray[3];*/
00201    
00202    memcpy(termCharArray,sentinel,4);
00203    /*termCharArray[0] = '\r';
00204    termCharArray[1] = '\n';
00205    termCharArray[2] = '\r';
00206    termCharArray[3] = '\n';*/
00207    char *scanTermCharPtr;
00208    MsgHeaderScanner::ScanChunkResult scanChunkResult =
00209        msgHeaderScanner.scanChunk(buffer,
00210                                   (unsigned int)(size + sentinelLength),
00211                                   &scanTermCharPtr);
00212    
00213    memcpy(termCharArray,scratchpad,4);
00214    /*termCharArray[0] = saveTermCharArray[0];
00215    termCharArray[1] = saveTermCharArray[1];
00216    termCharArray[2] = saveTermCharArray[2];
00217    termCharArray[3] = saveTermCharArray[3];*/
00218    
00219    // !dlb! not at all clear what to do here
00220    // see: "// tests end of message problem (MsgHeaderScanner?)"
00221    //      in test/testSipFrag.cxx
00222    if (false && scanChunkResult != MsgHeaderScanner::scrEnd) 
00223    {
00224       CerrLog(<< "not MsgHeaderScanner::scrEnd");
00225       pb.fail(__FILE__, __LINE__);
00226    } 
00227    else 
00228    {
00229       size_t used = scanTermCharPtr - buffer;
00230 
00231       // !ah! I think this is broken .. if we are UDP then the 
00232       // remainder is the SigFrag, not the Content-Length... ??
00233       if (mMessage->exists(h_ContentLength))
00234       {
00235          mMessage->setBody(scanTermCharPtr,
00236                            static_cast<int>(size - used));
00237       }
00238       else
00239       {
00240          // !ah! So the headers weren't complete. Why are we here?
00241          // !dlb! 
00242          if (mMessage->exists(h_ContentLength))
00243          {
00244             pb.reset(buffer + used);
00245             pb.skipChars(Symbols::CRLF);
00246             mMessage->setBody(pb.position(),int(pb.end()-pb.position()) );
00247          }
00248       }
00249       pb.reset(pb.end());
00250    }
00251 }
00252 
00253 /* ====================================================================
00254  * The Vovida Software License, Version 1.0 
00255  * 
00256  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00257  * 
00258  * Redistribution and use in source and binary forms, with or without
00259  * modification, are permitted provided that the following conditions
00260  * are met:
00261  * 
00262  * 1. Redistributions of source code must retain the above copyright
00263  *    notice, this list of conditions and the following disclaimer.
00264  * 
00265  * 2. Redistributions in binary form must reproduce the above copyright
00266  *    notice, this list of conditions and the following disclaimer in
00267  *    the documentation and/or other materials provided with the
00268  *    distribution.
00269  * 
00270  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00271  *    and "Vovida Open Communication Application Library (VOCAL)" must
00272  *    not be used to endorse or promote products derived from this
00273  *    software without prior written permission. For written
00274  *    permission, please contact vocal@vovida.org.
00275  *
00276  * 4. Products derived from this software may not be called "VOCAL", nor
00277  *    may "VOCAL" appear in their name, without prior written
00278  *    permission of Vovida Networks, Inc.
00279  * 
00280  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00281  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00282  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00283  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00284  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00285  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00286  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00287  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00288  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00289  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00290  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00291  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00292  * DAMAGE.
00293  * 
00294  * ====================================================================
00295  * 
00296  * This software consists of voluntary contributions made by Vovida
00297  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00298  * Inc.  For more information on Vovida Networks, Inc., please see
00299  * <http://www.vovida.org/>.
00300  *
00301  */