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

流媒体/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 RtspServer_cxx_Version =
  51.     "$Id: RtspServer.cxx,v 1.31 2001/05/15 20:26:08 bko Exp $";
  52. #include "RtspServer.hxx"
  53. #include "RtspConfiguration.hxx"
  54. #include "RtspSessionManager.hxx"
  55. #include "RtspRtpProcessor.hxx"
  56. #include "OpTeardown.hxx"
  57. // singelton object definition
  58. RtspServer* RtspServer::myInstance = 0;
  59. RtspServer&
  60. RtspServer::instance( const int port )
  61. {
  62.     if( myInstance == 0 )
  63.     {
  64.         myInstance = new RtspServer( port );
  65.     }
  66.     return *myInstance;
  67. }
  68. RtspServer::RtspServer( const int port )
  69.     : myMsgInterface( port )
  70. {
  71. #if defined (_linux_)    
  72.     // register destroy function to delete singelton
  73.     if( atexit( RtspServer::destroy ) < 0 )
  74.     {
  75.         cpLog( LOG_ALERT, "Failed to register with atexit()" );
  76.     }
  77. #endif
  78.     // save hostname into networkAddress
  79.     char hostName[256];
  80.     if( gethostname( hostName, 255 ) != 0 )
  81.     {
  82.         cpLog( LOG_ALERT, "Failed to get the RTSP server host name, reason %s",
  83.                strerror( errno ) );
  84.         assert( 0 );
  85.     }
  86.     myNetworkAddress.setHostName( hostName );
  87.     myNetworkAddress.setPort( port );
  88.     // create singleton of state machine
  89.     StateMachine& stateMachine = StateMachine::instance();
  90.     cpLog( LOG_DEBUG, "%s created", stateMachine.name() );
  91.     // read configuration file
  92.     RtspConfiguration& cfg = RtspConfiguration::instance();
  93.     // limit number of supported sessions
  94.     RtspSessionManager::instance().maxSessions( cfg.maxSessions );
  95.     // build rtp processor
  96.     RtspRtpProcessor::instance().buildRtpPortList( cfg.rtpPortRangeMin,
  97.                                                    cfg.rtpPortRangeMax );
  98.     // start rtp processor thread
  99.     RtspRtpProcessor::instance().startThread();
  100. }
  101. RtspServer::~RtspServer()
  102. {
  103. }
  104. void
  105. RtspServer::destroy()
  106. {
  107.     delete RtspServer::myInstance;
  108.     RtspServer::myInstance = 0;
  109. }
  110. void
  111. RtspServer::run()
  112. {
  113.     cpLog( LOG_DEBUG, "RtspServer thread is running" );
  114.     while( 1 )
  115.     {
  116.         // get next rtsp message (blocking)
  117.         Sptr<RtspMsg> msg = myMsgInterface.getNext();
  118.         cpLog( LOG_DEBUG, "Processing new msg from fifo" );
  119.         Sptr<RtspRequest> request;
  120.         request.dynamicCast(msg);
  121.         // check if msg is a rtsp request
  122.         if( request == 0 )
  123.         {
  124.             cpLog( LOG_DEBUG, "Non request rtsp message received, ignoring" );
  125.             continue;
  126.         }
  127.         else
  128.         {
  129.             if (RtspConfiguration::instance().logStatistics)
  130.             {
  131.                 myStatsMutex.lock();
  132.                 myStats.myTotalReqRecvd++;
  133.                 myStatsMutex.unlock();
  134.             }
  135.             // this has to be called to trigger the parsing for startline
  136.             u_int32_t mthd = request->getMethod();
  137.             if( ( mthd == RTSP_UNKNOWN_MTHD ) || ( mthd == RTSP_NULL_MTHD ) )
  138.             {
  139.                 // throw away this msg
  140.                 if (RtspConfiguration::instance().logStatistics)
  141.                 {
  142.                     myStatsMutex.lock();
  143.                     myStats.myTotalNonSuccessReqRecvd++;
  144.                     myStatsMutex.unlock();
  145.                 }
  146.                 continue;
  147.             }
  148.         }
  149.         // process session request differently
  150.         if( request->isSessionRequest() )
  151.         {
  152.             if( !processRequest( request ) )
  153.             {
  154.                 break;
  155.             }
  156.         }
  157.         else
  158.         {
  159.             if( !processSessionRequest( request ) )
  160.             {
  161.                 break;
  162.             }
  163.         }
  164.     }
  165.     stop();
  166.     cpLog( LOG_DEBUG, "RtspServer thread is stopped" );
  167.     return;
  168. }
  169. void
  170. RtspServer::stop( const int delay )
  171. {
  172.     cpLog( LOG_DEBUG, "Shutting down rtsp server" );
  173.     RtspSessionManager& sessionManager = RtspSessionManager::instance();
  174.     // teardown and shutdown each session
  175.     Sptr<RtspSession> session = sessionManager.getRtspSession();
  176.     while( session != 0 )
  177.     {
  178.         // send teardown to client
  179.         //TODO
  180.         //sendRequest( msg );
  181.         // teardown session
  182.         OpTeardown::process2( session );
  183.         // set next while() iterator
  184.         session = sessionManager.getRtspSession();
  185.     }
  186.     // reject all other messages in msg fifo
  187.     while( myMsgInterface.messageAvailable() )
  188.     {
  189.         Sptr<RtspMsg> msg = myMsgInterface.getNext();
  190.         Sptr<RtspRequest> request;
  191.         request.dynamicCast(msg);
  192.         if( request != 0 )
  193.         {
  194.             cpLog( LOG_DEBUG, "Server going down, reply 503" );
  195.             Sptr<RtspResponse> response = new RtspResponse( request, RTSP_503_STATUS );
  196.             sendResponse( response );
  197.         }
  198.     }
  199.     // stop rtp processor thread
  200.     RtspRtpProcessor::instance().stopThread();
  201.     // stop tcp connection thread
  202.     //TODO
  203. }
  204. bool
  205. RtspServer::processRequest( Sptr<RtspRequest> msg )
  206. {
  207.     cpLog( LOG_DEBUG, "Processing non-session request" );
  208.     StateMachine& stateMachine = StateMachine::instance();
  209.     Sptr<StateEvent> newEvent = new StateEvent( msg );
  210.     Sptr<State> startState = stateMachine.findState( "StateInit" );
  211.     Sptr<State> resultState = stateMachine.process( startState, newEvent );
  212.     if( resultState == NEXT_STATE )
  213.     {
  214.         if (RtspConfiguration::instance().logStatistics)
  215.         {
  216.             myStatsMutex.lock();
  217.             myStats.myTotalNonSuccessReqRecvd++;
  218.             myStatsMutex.unlock();
  219.         }
  220.         cpLog( LOG_DEBUG, "Unknown RTSP method, reply 400" );
  221.         Sptr<RtspResponse> response = new RtspResponse( msg, RTSP_400_STATUS );
  222.         sendResponse( response );
  223.         return true;
  224.     }
  225.     else if( resultState == FATAL_STATE )
  226.     {
  227.         cpLog( LOG_DEBUG, "Fatal state occured, shutdown server" );
  228.         return false;
  229.     }
  230.     return true;
  231. }
  232. bool
  233. RtspServer::processSessionRequest( Sptr<RtspRequest> msg )
  234. {
  235.     cpLog( LOG_DEBUG, "Processing session request" );
  236.     Sptr<RtspSession> session = RtspSessionManager::instance().
  237.                                 getRtspSession( msg->getSessionId() );
  238.     if( session == 0 )
  239.     {
  240.         if( msg->getSessionId() == "Global" )
  241.         {
  242.             return processServerRequest( msg );
  243.         }
  244.  
  245.         if (RtspConfiguration::instance().logStatistics)
  246.         {
  247.             myStatsMutex.lock();
  248.             myStats.myTotalNonSuccessReqRecvd++;
  249.             myStatsMutex.unlock();
  250.         }
  251.         cpLog( LOG_DEBUG, "SessionId not found, reply 454" );
  252.         Sptr<RtspResponse> response = new RtspResponse( msg, RTSP_454_STATUS );
  253.         sendResponse( response );
  254.         return true;
  255.     }
  256.     StateMachine& stateMachine = StateMachine::instance();
  257.     Sptr<StateEvent> newEvent = new StateEvent( msg );
  258.     Sptr<State> startState = session->state();
  259.     Sptr<State> resultState = stateMachine.process( startState, newEvent );
  260.     if( resultState == NEXT_STATE )
  261.     {
  262.         if (RtspConfiguration::instance().logStatistics)
  263.         {
  264.             myStatsMutex.lock();
  265.             myStats.myTotalNonSuccessReqRecvd++;
  266.             myStatsMutex.unlock();
  267.         }
  268.         cpLog( LOG_DEBUG, "Unknown RTSP method, reply 400" );
  269.         Sptr<RtspResponse> response = new RtspResponse( msg, RTSP_400_STATUS );
  270.         sendResponse( response );
  271.         return true;
  272.     }
  273.     else if( resultState == FATAL_STATE )
  274.     {
  275.         cpLog( LOG_DEBUG, "Fatal state occured, shutdown server" );
  276.         return false;
  277.     }
  278.     return true;
  279. }
  280. bool
  281. RtspServer::processServerRequest( Sptr<RtspRequest> msg )
  282. {
  283.     Sptr< RtspTcpBuffer > tcpBuffer = msg->getTransConnPtr();
  284.     assert( tcpBuffer != 0 );
  285.     Connection conn = tcpBuffer->getConnection();
  286.     if( conn.getIp() != networkAddress().getIpName() )
  287.     {
  288.         cpLog( LOG_ERR,
  289.                "Rejecting server request because ip check failed" );
  290.         return true;
  291.     }
  292.     u_int32_t mthd = msg->getMethod();
  293.     switch( mthd )
  294.     {
  295.         case RTSP_TEARDOWN_MTHD:
  296.         {
  297.             cpLog( LOG_DEBUG, "Handling TEARDOWN, shutdown server" );
  298.             if (RtspConfiguration::instance().logStatistics)
  299.             {
  300.                 myStats.report();
  301.             }
  302.             // return false to break out of while() loop
  303.             return false;
  304.             break;
  305.         }
  306.         default:
  307.             assert( 0 );
  308.     }
  309.     return true;
  310. }
  311. void
  312. RtspServer::sendResponse( Sptr<RtspResponse> response )
  313. {
  314.     if (RtspConfiguration::instance().logStatistics)
  315.     {
  316.         myStatsMutex.lock();
  317.         myStats.myTotalRespSent++;
  318.         myStatsMutex.unlock();
  319.     }
  320.     myMsgInterface.send( response );
  321. }
  322. /* Local Variables: */
  323. /* c-file-style: "stroustrup" */
  324. /* indent-tabs-mode: nil */
  325. /* c-file-offsets: ((access-label . -) (inclass . ++)) */
  326. /* c-basic-offset: 4 */
  327. /* End: */