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

流媒体/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 RtspTransportHdr_cxx_Version =
  51.     "$Id: RtspTransportHdr.cxx,v 1.11 2001/05/15 20:26:12 bko Exp $";
  52. #include <stdio.h>
  53. #include "RtspTransportHdr.hxx"
  54. #include "cpLog.h"
  55. #include "support.hxx"
  56. RtspTransportSpec::RtspTransportSpec()
  57.     : myIsTcp(false),
  58.       myIsMulticast(false),
  59.       myIsRecord(false),
  60.       myIsAppend(false),
  61.       myClientPortA(0),
  62.       myClientPortB(0),
  63.       myServerPortA(0),
  64.       myServerPortB(0)
  65. { }
  66. RtspTransportSpec::RtspTransportSpec(const RtspTransportSpec& x)
  67. {
  68.     myIsTcp = x.myIsTcp;
  69.     myIsMulticast = x.myIsMulticast;
  70.     myIsRecord = x.myIsRecord;
  71.     myIsAppend = x.myIsAppend;
  72.     myClientPortA = x.myClientPortA;
  73.     myClientPortB = x.myClientPortB;
  74.     myServerPortA = x.myServerPortA;
  75.     myServerPortB = x.myServerPortB;
  76.     myDestination = x.myDestination;
  77.     mySource = x.mySource;
  78. }
  79. RtspTransportSpec&
  80. RtspTransportSpec::operator=(const RtspTransportSpec& x)
  81. {
  82.     if (&x != this)
  83.     {
  84.         myIsTcp = x.myIsTcp;
  85.         myIsMulticast = x.myIsMulticast;
  86.         myIsRecord = x.myIsRecord;
  87.         myIsAppend = x.myIsAppend;
  88.         myClientPortA = x.myClientPortA;
  89.         myClientPortB = x.myClientPortB;
  90.         myServerPortA = x.myServerPortA;
  91.         myServerPortB = x.myServerPortB;
  92.         myDestination = x.myDestination;
  93.         mySource = x.mySource;
  94.     }
  95.     return *this;
  96. }
  97. bool
  98. RtspTransportSpec::operator==(const RtspTransportSpec& x) const
  99. {
  100.     return ( (myIsTcp == x.myIsTcp) &&
  101.              (myIsMulticast == x.myIsMulticast) &&
  102.              (myIsRecord == x.myIsRecord) &&
  103.              (myIsAppend == x.myIsAppend) &&
  104.              (myClientPortA == x.myClientPortA) &&
  105.              (myClientPortB == x.myClientPortB) &&
  106.              (myServerPortA == x.myServerPortA) &&
  107.              (myServerPortB == x.myServerPortB) &&
  108.              (myDestination == x.myDestination) &&
  109.              (mySource == x.mySource)
  110.            );
  111. }
  112. void
  113. RtspTransportSpec::reset()
  114. {
  115.     myIsTcp = false;
  116.     myIsMulticast = false;
  117.     myIsRecord = false;
  118.     myIsAppend = false;
  119.     myClientPortA = 0;
  120.     myClientPortB = 0;
  121.     myServerPortA = 0;
  122.     myServerPortB = 0;
  123.     myDestination.erase();
  124.     mySource.erase();
  125. }
  126. void
  127. RtspTransportSpec::parse(CharDataParser& parser)
  128. {
  129.     CharData oneParamData;
  130.     while (parser.parseThru(&oneParamData, ';'))
  131.     {
  132.         CharDataParser paramParser(&oneParamData);
  133.         switch (paramParser.getCurChar())
  134.         {
  135.             case 'R' :
  136.                 parseProtocol(paramParser);
  137.                 break;
  138.             case 'm' :  // may be mode
  139.                 parseMulticastOrMode(paramParser);
  140.                 break;
  141.             case 'u' : 
  142.                 parseUnicast(paramParser);
  143.                 break;
  144.             case 'd' :
  145.                 parseDestination(paramParser);
  146.                 break;
  147.             case 's' :
  148.                 parseSource(paramParser);
  149.                 break;
  150.             case 'a' :
  151.                 parseAppend(paramParser);
  152.                 break;
  153.             case 'c' :
  154.                 parseClientPort(paramParser);
  155.                 break;
  156.             default :
  157.                 break;
  158.         }
  159.         /** To get rid of spaces after ';', and to make sure 
  160.          *  oneParamData start with non spaces
  161.          */
  162.         parser.getThruSpaces(NULL); 
  163.     } 
  164.     
  165.     // parse the last param
  166.     CharDataParser paramParser(&oneParamData);
  167.     switch (paramParser.getCurChar())
  168.     {
  169.         case 'R' :
  170.             parseProtocol(paramParser);
  171.             break;
  172.         case 'm' :  // may be mode
  173.             parseMulticastOrMode(paramParser);
  174.             break;
  175.         case 'u' : 
  176.             parseUnicast(paramParser);
  177.             break;
  178.         case 'd' :
  179.             parseDestination(paramParser);
  180.             break;
  181.         case 's' :
  182.             parseSource(paramParser);
  183.             break;
  184.         case 'a' :
  185.             parseAppend(paramParser);
  186.             break;
  187.         case 'c' :
  188.             parseClientPort(paramParser);
  189.             break;
  190.         default :
  191.             break;
  192.     }
  193. }
  194. void
  195. RtspTransportSpec::parseProtocol(CharDataParser& paramParser)
  196. {
  197.     CharData param;
  198.     paramParser.getNextWord(&param);
  199.     if (param.isEqualNoCase("RTP", 3))
  200.     {
  201.         paramParser.getThruLength(NULL,1); // get thru '/'
  202.         paramParser.getNextWord(&param);
  203.         if (param.isEqualNoCase("AVP", 3))
  204.         {
  205.             paramParser.getThruLength(NULL,1); // get thru '/'
  206.             if (paramParser.getNextWord(&param) != 0)
  207.             {
  208.                 if (param.isEqualNoCase("TCP", 3))
  209.                 {
  210.                     myIsTcp = true;
  211.                 }
  212.             }
  213.         }
  214.         else
  215.         {
  216.             cpLog(LOG_ERR, "Transport hdr: The profile is not AVP.");
  217.         }
  218.     }
  219.     else
  220.     {
  221.         cpLog(LOG_ERR, "Transport hdr: The protocol is not RTP.");
  222.     }
  223. }
  224.  
  225. void
  226. RtspTransportSpec::parseMulticastOrMode(CharDataParser& paramParser)
  227. {
  228.     CharData param;
  229.     paramParser.getNextWord(&param);
  230.     if (param.isEqualNoCase("multicast", 9))
  231.     {
  232.        myIsMulticast = true;
  233.     }
  234.     else
  235.     {
  236.         if (param.isEqualNoCase("mode", 4))
  237.         { 
  238.             // get thru "=""
  239.             paramParser.parseThru(NULL, paramParser.myMaskNonWord);
  240.             paramParser.getNextWord(&param);
  241.             if (param.isEqualNoCase("RECORD", 6))
  242.             {
  243.                 myIsRecord = true;
  244.             }
  245.         }
  246.         else
  247.         {
  248.             cpLog(LOG_ERR, "Transport hdr: unknown m parameter.");
  249.         }
  250.     }
  251. }
  252.             
  253. void
  254. RtspTransportSpec::parseUnicast(CharDataParser& paramParser)
  255. {
  256.     CharData param;
  257.     paramParser.getNextWord(&param);
  258.     if (!(param.isEqualNoCase("unicast", 7)))
  259.         cpLog(LOG_ERR, "Transport hdr: unknown u parameter.");
  260. }
  261. void
  262. RtspTransportSpec::parseDestination(CharDataParser& paramParser)
  263. {
  264.     CharData param;
  265.     paramParser.getNextWord(&param);
  266.     if (param.isEqualNoCase("destination", 11))
  267.     {
  268.         paramParser.getThruLength(NULL, 1); // get thru '='
  269.         paramParser.parseUntil(&param, paramParser.myMaskEolSpace);
  270.         if (param[param.getLen() - 1] == ';')
  271.         {
  272.             // get rid of the last ';' in the host
  273.             param.setLen(param.getLen() - 1);
  274.         }
  275.         Data host(param.getPtr(), param.getLen());
  276.         myDestination = host;
  277.     }
  278.     else
  279.     {
  280.         cpLog(LOG_ERR, "Transport hdr: unknown d parameter.");
  281.     }
  282. }
  283. void
  284. RtspTransportSpec::parseSource(CharDataParser& paramParser)
  285. {
  286.     CharData param;
  287.     paramParser.getNextWord(&param);
  288.     if (param.isEqualNoCase("source",6))
  289.     {
  290.         paramParser.getThruLength(NULL, 1); // get thru '='
  291.         paramParser.parseUntil(&param, paramParser.myMaskEolSpace);
  292.         if (param[param.getLen() - 1] == ';')
  293.         {
  294.             // get rid of the last ';' in the host
  295.             param.setLen(param.getLen() - 1);
  296.         }
  297.         Data host(param.getPtr(), param.getLen());
  298.         mySource = host;
  299.     }
  300.     else
  301.     {
  302.         cpLog(LOG_ERR, "Transport hdr: unknown s  parameter.");
  303.     }
  304. }
  305. void
  306. RtspTransportSpec::parseAppend(CharDataParser& paramParser)
  307. {
  308.     CharData param;
  309.     paramParser.getNextWord(&param);
  310.     if (!(param.isEqualNoCase("append", 6)))
  311.         cpLog(LOG_ERR, "Transport hdr: unknown a parameter.");
  312.     else
  313.         myIsAppend = true;
  314.     
  315. }
  316. void
  317. RtspTransportSpec::parseClientPort(CharDataParser& paramParser)
  318. {
  319.     CharData param;
  320.     paramParser.getNextWord(&param);
  321.     if (param.isEqualNoCase("client_port", 11))
  322.     {
  323.         paramParser.getThruLength(NULL, 1); // get thru '='
  324.         u_int32_t clientPort;
  325.         if( paramParser.getNextInteger(clientPort) )
  326.         {
  327.             myClientPortA = clientPort;
  328.             paramParser.getThruLength(NULL, 1); // get thru '-'
  329.             if( paramParser.getNextInteger(clientPort) )
  330.             {
  331.                 myClientPortB = clientPort;
  332.             }
  333.         }
  334.         else
  335.         {
  336.             cpLog(LOG_ERR, "Transport hdr: error read client port.");
  337.         }
  338.     }
  339.     else
  340.     {
  341.         cpLog(LOG_ERR, "Transport hdr: unknown c parameter.");
  342.     }
  343. }
  344. Data
  345. RtspTransportSpec::encode()
  346. {
  347.     Data specData;
  348.     if ((!myIsTcp) && (!myIsMulticast))
  349.         specData = "RTP/AVP;unicast;";
  350.     else
  351.         if (myIsTcp)
  352.             specData = "RTP/AVP/TCP;unicast;";
  353.         else
  354.             specData = "RTP/AVP;multicast;";
  355.     
  356.     if (myDestination.length() > 0)
  357.     {
  358.         specData += "destination=";
  359.         specData += myDestination;
  360.         specData += ";";
  361.     }
  362.     if (mySource.length() > 0)
  363.     {
  364.         specData += "source=";
  365.         specData += mySource;
  366.         specData += ";";
  367.     }
  368.     if (myIsAppend)
  369.     {
  370.         specData += "append;";
  371.     }
  372.     if (myClientPortA)
  373.     {
  374.         specData += "client_port=";
  375.         specData += itos(myClientPortA);
  376.         if (myClientPortB)
  377.         {
  378.             specData += "-";
  379.             specData += itos(myClientPortB);
  380.         }
  381.         specData += ";";
  382.     }
  383.     if (myServerPortA)
  384.     {
  385.         specData += "server_port=";
  386.         specData += itos(myServerPortA);
  387.         if (myServerPortB)
  388.         {
  389.             specData += "-";
  390.             specData += itos(myServerPortB);
  391.         }
  392.         specData += ";";
  393.     }
  394.     if (myIsRecord)
  395.     {
  396.         specData += "mode="RECORD"";
  397.     }
  398.     else
  399.     {
  400.         specData += "mode="PLAY"";
  401.     }
  402.     return specData;
  403. }
  404. bool
  405. RtspTransportHdr::isSuitableSpec(Sptr< RtspTransportSpec > spec)
  406. {
  407.     //TODO need to add API, because server should be able to tell 
  408.     // if it is prefer TCP or multicast
  409.     if( spec->myIsTcp | spec->myIsMulticast )
  410.     {
  411.         if (spec->myIsTcp)
  412.            cpLog(LOG_DEBUG_STACK, "TCP for transport media is not suported.");
  413.         else
  414.            cpLog(LOG_DEBUG_STACK, "Multicast for transport is not supported.");
  415.         return false;
  416.     }
  417.     if( spec->myClientPortA == 0 )
  418.     {
  419.         cpLog(LOG_DEBUG, "Client port is not provided");
  420.         return false;
  421.     }
  422.     return true;
  423. }
  424. Sptr< RtspTransportSpec >
  425. RtspTransportHdr::parseTransportHeader(CharDataParser& parser)
  426. {
  427.     Sptr< RtspTransportSpec > spec = new RtspTransportSpec();
  428.     bool found = false;
  429.     CharData oneSpecData;
  430.     while ( (!found) && (parser.parseThru(&oneSpecData, ',')) )
  431.     {
  432.         CharDataParser specParser(&oneSpecData);
  433.         spec->parse(specParser);
  434.         if (isSuitableSpec(spec))
  435.         {
  436.             found = true;
  437.         }
  438.         else
  439.         {
  440.             /** To get rid of spaces after ',', and to make sure 
  441.              *  oneSpecData start with non spaces
  442.              */
  443.             parser.getThruSpaces(NULL);
  444.             spec->reset();
  445.         }
  446.     } 
  447.     if( !found )
  448.     {
  449.         spec->reset();
  450.         CharDataParser specParser(&oneSpecData);
  451.         spec->parse(specParser);
  452.         if (isSuitableSpec(spec))
  453.         {
  454.             found = true;
  455.         }
  456.     }
  457.     if (!found)
  458.     {
  459. //        delete spec;
  460.           spec = 0; //should invoke destructor
  461.     }
  462.     return spec;
  463.     
  464. }
  465. void
  466. RtspTransportHdr::appendTransportSpec(Sptr< RtspTransportSpec > transSpec)
  467. {
  468.     assert (transSpec != 0);
  469.     if (myTransport.length() == 0)
  470.     {
  471.         myTransport = "Transport: ";
  472.     }
  473.     else
  474.     {
  475.         myTransport += ",";
  476.     }
  477.     myTransport += transSpec->encode();
  478. }
  479. /* Local Variables: */
  480. /* c-file-style: "stroustrup" */
  481. /* indent-tabs-mode: nil */
  482. /* c-file-offsets: ((access-label . -) (inclass . ++)) */
  483. /* c-basic-offset: 4 */
  484. /* End: */