RtspMsgParser.cxx
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:12k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. /* ====================================================================
  2.  * The Vovida Software License, Version 1.0 
  3.  * 
  4.  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
  5.  * 
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  * 
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in
  15.  *    the documentation and/or other materials provided with the
  16.  *    distribution.
  17.  * 
  18.  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
  19.  *    and "Vovida Open Communication Application Library (VOCAL)" must
  20.  *    not be used to endorse or promote products derived from this
  21.  *    software without prior written permission. For written
  22.  *    permission, please contact vocal@vovida.org.
  23.  *
  24.  * 4. Products derived from this software may not be called "VOCAL", nor
  25.  *    may "VOCAL" appear in their name, without prior written
  26.  *    permission of Vovida Networks, Inc.
  27.  * 
  28.  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
  29.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
  31.  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
  32.  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
  33.  * IN EXCESS OF 281421,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
  34.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  35.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  36.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  37.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  38.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  39.  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  40.  * DAMAGE.
  41.  * 
  42.  * ====================================================================
  43.  * 
  44.  * This software consists of voluntary contributions made by Vovida
  45.  * Networks, Inc. and many individuals on behalf of Vovida Networks,
  46.  * Inc.  For more information on Vovida Networks, Inc., please see
  47.  * <http://www.vovida.org/>.
  48.  *
  49.  */
  50. static const char* const RtspMsgParser_cxx_Version =
  51.     "$Id: RtspMsgParser.cxx,v 1.15 2001/05/15 20:26:12 bko Exp $";
  52. #include <stdio.h>
  53. #include "RtspMsgParser.hxx"
  54. #include "CharDataParser.hxx"
  55. #include "Data.hxx"
  56. #include "cpLog.h"
  57. #include "RtspDescribeMsg.hxx"
  58. #include "RtspAnnounceMsg.hxx"
  59. #include "RtspPlayMsg.hxx"
  60. #include "RtspRecordMsg.hxx"
  61. #include "RtspSetupMsg.hxx"
  62. #include "RtspPauseMsg.hxx"
  63. #include "RtspTeardownMsg.hxx"
  64. #include "RtspOptionsMsg.hxx"
  65. #include "RtspSetParameterMsg.hxx"
  66. #include "RtspRequest.hxx"
  67. #include "RtspResponse.hxx"
  68. // need to remove all the cpLogs for performance after debuging period
  69. Sptr< RtspMsg >
  70. RtspMsgParser::preParse( const char* data, 
  71.                          int bytesNeedtoDecode,
  72.                          int& bytesDecoded,
  73.                          Sptr< RtspMsg > savedMsg) 
  74.             throw (RtspBadDataException&)
  75. {
  76. //    Data dump(data, bytesNeedtoDecode);
  77. //    cpLog(LOG_DEBUG, "Get data: n%s", dump.getData());
  78.     Sptr< RtspMsg > msg = 0;
  79.     if (savedMsg == 0)
  80.     {
  81.         cpLog(LOG_DEBUG_STACK, "create new msg.");
  82.         msg = createRtspMsg(data, bytesNeedtoDecode);
  83.         assert(msg != 0);
  84.     }
  85.     else
  86.     {
  87.         assert(savedMsg->getCompletionFlag() != RTSP_MSG_COMPLETE);
  88.         msg = savedMsg;
  89.         cpLog(LOG_DEBUG_STACK, "append to the saved msg.");
  90.     }
  91.         
  92.     CharData stream(data, bytesNeedtoDecode);
  93.     CharDataParser charParser(&stream);
  94.     CharData aLine;
  95.     int result;
  96.    
  97.     int advance = 0;
  98.     if (msg->myCompletionFlag < RTSP_MSG_STRTLINE_COMPLETE)
  99.     {
  100.         result = charParser.getNextLine(&aLine);
  101.     
  102.         Data startline(aLine.getPtr(), aLine.getLen());
  103.         msg->myStartLine += startline;
  104.         cpLog(LOG_DEBUG_STACK, "Startline is:%s", (msg->myStartLine).getData());
  105.         bytesDecoded += aLine.getLen();
  106.         advance += aLine.getLen();
  107.     
  108.         if (result == 0)
  109.         {
  110.             msg->myCompletionFlag = RTSP_MSG_NEW;
  111.             cpLog(LOG_DEBUG_STACK, "The startline is not finished.");
  112.             return msg;
  113.         }
  114.         else
  115.             msg->myCompletionFlag = RTSP_MSG_STRTLINE_COMPLETE;
  116.     }
  117.     bool foundEmptyLine = true;
  118.     if (msg->myCompletionFlag < RTSP_MSG_HEADERS_COMPLETE)
  119.         foundEmptyLine = false;
  120.     const char* hdrStart = data + advance;
  121.     int hdrsLen = 0;
  122.     int hdrIndex = msg->myNumHeader;
  123.     int newHdrOffset = (msg->myHeaders).length() - 
  124.                        (msg->myIncompHeader).length();
  125.     while (!foundEmptyLine && (bytesDecoded < bytesNeedtoDecode))
  126.     {
  127.         result = charParser.getNextLine(&aLine);
  128.         if (result == 0)
  129.         {
  130.             Data incompHdr(aLine.getPtr(), aLine.getLen());
  131.             msg->myIncompHeader = incompHdr;
  132.             bytesDecoded += aLine.getLen();
  133.             advance += aLine.getLen();
  134.             hdrsLen += aLine.getLen();
  135.             Data hdrs(hdrStart, hdrsLen);
  136.             msg->myHeaders += hdrs;
  137.             cpLog(LOG_DEBUG_STACK, "Incomplete Headers is: %s",
  138.                   (msg->myHeaders).getData());
  139.             msg->myNumHeader = hdrIndex;
  140. //            msg->myCompletionFlag = RTSP_MSG_STRTLINE_COMPLETE;
  141.             return msg;
  142.         }
  143.         else
  144.         {
  145.             bytesDecoded += aLine.getLen();
  146.             advance += aLine.getLen();
  147.             hdrsLen += aLine.getLen();
  148.             if( (msg->myIncompHeader).length() != 0 )
  149.             {
  150.                 Data halfHdr(aLine.getPtr(), aLine.getLen());
  151.                 msg->myIncompHeader += halfHdr;
  152.                 aLine.set((msg->myIncompHeader).getDataBuf(),
  153.                           (msg->myIncompHeader).length());
  154.             }
  155.             else
  156.             {
  157.                 hdrIndex++;
  158.             }
  159.             CharDataParser lineParser(&aLine);
  160.         
  161.             if (aLine.isEmptyLine())
  162.             {
  163.                 foundEmptyLine = true;
  164.                 Data hdrs(hdrStart, hdrsLen);
  165.                 msg->myHeaders += hdrs;
  166.                 cpLog(LOG_DEBUG_STACK, "Complete Headers is: %s", 
  167.                       (msg->myHeaders).getData());
  168.                 msg->myNumHeader = hdrIndex;
  169.                 msg->myCompletionFlag = RTSP_MSG_HEADERS_COMPLETE;
  170.             }
  171.             else
  172.             {
  173.                 cpLog(LOG_DEBUG_STACK, "The hdrline len is:%d", aLine.getLen());
  174.        
  175.                 CharData aHeader;
  176.                 lineParser.getNextWord(&aHeader);
  177.                 cpLog(LOG_DEBUG_STACK, "aHeader len is: %d", aHeader.getLen());
  178.               
  179.                 u_int32_t headerNum;
  180.                 headerNum = RtspUtil::getHeaderInNumber(aHeader);
  181.                 cpLog(LOG_DEBUG_STACK, "headerNum is: %d", headerNum);
  182.                 if (headerNum != RTSP_UNKNOWN_HDR)
  183.                 {
  184.                     int hdrBdyOffset = newHdrOffset + aHeader.getLen();
  185.                     CharData tmpData;
  186.                     HeaderValueData hv;
  187.       
  188.                     if ( lineParser.parseThru(&tmpData, ':') == 0 )
  189.                     {
  190.                         hv.offset = -1;
  191.                         hv.len = 0;
  192.                     }
  193.                     else
  194.                     {
  195.                         hdrBdyOffset += tmpData.getLen();
  196.      
  197.                         lineParser.getThruSpaces(&tmpData);
  198.                         hdrBdyOffset += tmpData.getLen();
  199.     
  200.                         hv.offset = hdrBdyOffset;
  201.                         hv.len = newHdrOffset + aLine.getLen() - hdrBdyOffset;
  202.                     }
  203.                     msg->setHeadersMap(headerNum, hv); 
  204.                     cpLog(LOG_DEBUG_STACK, "** Offset %d, length",
  205.                           hv.offset, hv.len);
  206.                 }
  207.                 else
  208.                 {
  209.                     char tmpHeader[32];
  210.                     for (u_int32_t j = 0; j < aHeader.getLen(); j++)
  211.                         tmpHeader[j] = aHeader[j];
  212.                     tmpHeader[aHeader.getLen()] = '';
  213.                     cpLog(LOG_INFO, "unknown header: %s", tmpHeader);
  214.                 }
  215.             }
  216.             newHdrOffset += aLine.getLen();
  217.             (msg->myIncompHeader).erase();
  218.         }
  219.     }
  220.     int contentLen = msg->getContentLength();
  221.     cpLog(LOG_DEBUG_STACK, "Content-Length is: %d", contentLen);
  222.     if (foundEmptyLine)
  223.     {
  224.         if (contentLen > 0)
  225.         {
  226.             if ( (contentLen - (msg->myMsgBody).length()) > 
  227.                  (bytesNeedtoDecode - bytesDecoded) )
  228.             {
  229.                 msg->myCompletionFlag = RTSP_MSG_HEADERS_COMPLETE;
  230.                 cpLog(LOG_DEBUG_STACK, "The msgBody not complete");
  231.                 contentLen = bytesNeedtoDecode - bytesDecoded;
  232.             }
  233.             else
  234.             {
  235.                 //if the msg already has some msgBody, contenLen need to 
  236.                 // subtract that portion since it has been parsed already
  237.                 contentLen -= (msg->myMsgBody).length();
  238.                 msg->myCompletionFlag = RTSP_MSG_COMPLETE;
  239.                 cpLog(LOG_DEBUG_STACK, "The msgBody is complete");
  240.             }
  241.             Data msgBody(data + advance, contentLen);
  242.             msg->setHasBody(true);
  243.             msg->myMsgBody += msgBody;
  244.             cpLog(LOG_DEBUG_STACK, "Msgbody is: %s",
  245.                   (msg->myMsgBody).getData());
  246.             bytesDecoded += contentLen;
  247.         }
  248.         else
  249.         {
  250.             msg->myCompletionFlag = RTSP_MSG_COMPLETE;
  251.             msg->setHasBody(false);
  252.             cpLog(LOG_DEBUG_STACK, "There is no msgbody.");
  253.         }
  254.     }
  255.     else
  256.     {
  257.         // should not come to here
  258.         throw RtspBadDataException( "Bad RTSP message", __FILE__, __LINE__, 0 );
  259.     }
  260.     return msg;
  261. }
  262. Sptr< RtspMsg > 
  263. RtspMsgParser::createRtspMsg(const char* data, int bytesNeedtoDecode)
  264. {
  265.     Sptr< RtspMsg > msg = 0;
  266.     CharData strtLine;
  267.     strtLine.set(data, bytesNeedtoDecode);
  268.     CharDataParser charParser(&strtLine);
  269.     CharData firstWord;
  270.     charParser.getNextWord(&firstWord);
  271.     if (firstWord.isEqualNoCase("RTSP",4))
  272.     {
  273.         msg = new RtspResponse();
  274.     }
  275.     else
  276.     {
  277.         u_int32_t method;
  278.         method = RtspUtil::getMethodInNumber(firstWord);
  279.         switch (method)
  280.         {
  281.             case RTSP_ANNOUNCE_MTHD:
  282.                 msg = new RtspAnnounceMsg();
  283.                 break;
  284.             case RTSP_DESCRIBE_MTHD:
  285.                 msg = new RtspDescribeMsg();
  286.                 break;
  287.             case RTSP_PLAY_MTHD:
  288.                 msg = new RtspPlayMsg();
  289.                 break;
  290.             case RTSP_RECORD_MTHD:
  291.                 msg = new RtspRecordMsg();
  292.                 break;
  293.             case RTSP_PAUSE_MTHD:
  294.                 msg = new RtspPauseMsg();
  295.                 break;
  296.             case RTSP_SETUP_MTHD:
  297.                 msg = new RtspSetupMsg();
  298.                 break;
  299.             case RTSP_TEARDOWN_MTHD:
  300.                 msg = new RtspTeardownMsg();
  301.                 break;
  302.             case RTSP_GET_PARAMETER_MTHD:
  303.                 msg = new RtspRequest();
  304.                 break;
  305.             case RTSP_OPTIONS_MTHD:
  306.                 msg = new RtspOptionsMsg();
  307.                 break;
  308.             case RTSP_REDIRECT_MTHD:
  309.                 msg = new RtspRequest();
  310.                 break;
  311.             case RTSP_SET_PARAMETER_MTHD:
  312.                 msg = new RtspSetParameterMsg();
  313.                 break;
  314.             default :
  315.                 msg = new RtspMsg();
  316.                 msg->setFirstWordUnknown(true);
  317.                 break;
  318.         }
  319.     }
  320.     return msg;
  321.     
  322. }
  323. /* Local Variables: */
  324. /* c-file-style: "stroustrup" */
  325. /* indent-tabs-mode: nil */
  326. /* c-file-offsets: ((access-label . -) (inclass . ++)) */
  327. /* c-basic-offset: 4 */
  328. /* End: */