[vlc-commits] commit: rtsp: implement session timeouts (Pierre Ynard )

git at videolan.org git at videolan.org
Sat Nov 27 01:34:27 CET 2010


vlc | branch: master | Pierre Ynard <linkfanel at yahoo.fr> | Sat Nov 27 01:32:43 2010 +0100| [e59ca64643cb0769467f923667279cb83257e85c] | committer: Pierre Ynard 

rtsp: implement session timeouts

Based on keep-alive RTSP requests

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=e59ca64643cb0769467f923667279cb83257e85c
---

 modules/stream_out/rtp.c  |    8 +++
 modules/stream_out/rtsp.c |  104 ++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 105 insertions(+), 7 deletions(-)

diff --git a/modules/stream_out/rtp.c b/modules/stream_out/rtp.c
index d829974..ebb3330 100644
--- a/modules/stream_out/rtp.c
+++ b/modules/stream_out/rtp.c
@@ -167,6 +167,12 @@ static const char *const ppsz_protocols[] = {
     "interfaces (address 0.0.0.0), on port 554, with no path.\nTo listen " \
     "only on the local interface, use \"localhost\" as address." )
 
+#define RTSP_TIMEOUT_TEXT N_( "RTSP session timeout (s)" )
+#define RTSP_TIMEOUT_LONGTEXT N_( "RTSP sessions will be closed after " \
+    "not receiving any RTSP request for this long. Setting it to a " \
+    "negative value or zero disables timeouts. The default is 60 (one " \
+    "minute)." )
+
 static int  Open ( vlc_object_t * );
 static void Close( vlc_object_t * );
 
@@ -240,6 +246,8 @@ vlc_module_begin ()
     add_shortcut( "rtsp" )
     add_string ( "rtsp-host", NULL, RTSP_HOST_TEXT,
                  RTSP_HOST_LONGTEXT, true )
+    add_integer( "rtsp-timeout", 60, RTSP_TIMEOUT_TEXT,
+                 RTSP_TIMEOUT_LONGTEXT, true )
 
 vlc_module_end ()
 
diff --git a/modules/stream_out/rtsp.c b/modules/stream_out/rtsp.c
index 2e00424..dcefe7c 100644
--- a/modules/stream_out/rtsp.c
+++ b/modules/stream_out/rtsp.c
@@ -68,6 +68,9 @@ struct rtsp_stream_t
 
     int             sessionc;
     rtsp_session_t **sessionv;
+
+    int             timeout;
+    vlc_timer_t     timer;
 };
 
 
@@ -79,6 +82,8 @@ static int  RtspCallbackId( httpd_callback_sys_t *p_args,
                             const httpd_message_t *query );
 static void RtspClientDel( rtsp_stream_t *rtsp, rtsp_session_t *session );
 
+static void RtspTimeOut( void *data );
+
 rtsp_stream_t *RtspSetup( vlc_object_t *owner, vod_media_t *media,
                           const vlc_url_t *url )
 {
@@ -100,6 +105,13 @@ rtsp_stream_t *RtspSetup( vlc_object_t *owner, vod_media_t *media,
     rtsp->track_id = 0;
     vlc_mutex_init( &rtsp->lock );
 
+    rtsp->timeout = var_InheritInteger(owner, "rtsp-timeout");
+    if (rtsp->timeout > 0)
+    {
+        if (vlc_timer_create(&rtsp->timer, RtspTimeOut, rtsp))
+            goto error;
+    }
+
     rtsp->port = (url->i_port > 0) ? url->i_port : 554;
     rtsp->psz_path = strdup( ( url->psz_path != NULL ) ? url->psz_path : "/" );
     if( rtsp->psz_path == NULL )
@@ -138,11 +150,14 @@ void RtspUnsetup( rtsp_stream_t *rtsp )
     if( rtsp->url )
         httpd_UrlDelete( rtsp->url );
 
+    if( rtsp->host )
+        httpd_HostDelete( rtsp->host );
+
     while( rtsp->sessionc > 0 )
         RtspClientDel( rtsp, rtsp->sessionv[0] );
 
-    if( rtsp->host )
-        httpd_HostDelete( rtsp->host );
+    if (rtsp->timeout > 0)
+        vlc_timer_destroy(rtsp->timer);
 
     free( rtsp->psz_path );
     vlc_mutex_destroy( &rtsp->lock );
@@ -172,6 +187,7 @@ struct rtsp_session_t
 {
     rtsp_stream_t *stream;
     uint64_t       id;
+    mtime_t        last_seen; /* for timeouts */
     bool           vod_started; /* true if the VoD media instance was created */
 
     /* output (id-access) */
@@ -289,6 +305,49 @@ void RtspDelId( rtsp_stream_t *rtsp, rtsp_stream_id_t *id )
 
 
 /** rtsp must be locked */
+static void RtspUpdateTimer( rtsp_stream_t *rtsp )
+{
+    if (rtsp->timeout <= 0)
+        return;
+
+    mtime_t timeout = 0;
+    for (int i = 0; i < rtsp->sessionc; i++)
+    {
+        if (timeout == 0 || rtsp->sessionv[i]->last_seen < timeout)
+            timeout = rtsp->sessionv[i]->last_seen;
+    }
+    if (timeout != 0)
+        timeout += rtsp->timeout * CLOCK_FREQ;
+    vlc_timer_schedule(rtsp->timer, true, timeout, 0);
+}
+
+
+static void RtspTimeOut( void *data )
+{
+    rtsp_stream_t *rtsp = data;
+
+    vlc_mutex_lock(&rtsp->lock);
+    mtime_t now = mdate();
+    for (int i = rtsp->sessionc - 1; i >= 0; i--)
+    {
+        if (rtsp->sessionv[i]->last_seen + rtsp->timeout * CLOCK_FREQ < now)
+        {
+            if (rtsp->vod_media != NULL)
+            {
+                char psz_sesbuf[17];
+                snprintf( psz_sesbuf, sizeof( psz_sesbuf ), "%"PRIx64,
+                          rtsp->sessionv[i]->id );
+                vod_stop(rtsp->vod_media, psz_sesbuf);
+            }
+            RtspClientDel(rtsp, rtsp->sessionv[i]);
+        }
+    }
+    RtspUpdateTimer(rtsp);
+    vlc_mutex_unlock(&rtsp->lock);
+}
+
+
+/** rtsp must be locked */
 static
 rtsp_session_t *RtspClientNew( rtsp_stream_t *rtsp )
 {
@@ -349,6 +408,17 @@ void RtspClientDel( rtsp_stream_t *rtsp, rtsp_session_t *session )
 }
 
 
+/** rtsp must be locked */
+static void RtspClientAlive( rtsp_session_t *session )
+{
+    if (session->stream->timeout <= 0)
+        return;
+
+    session->last_seen = mdate();
+    RtspUpdateTimer(session->stream);
+}
+
+
 /* Attach a starting VoD RTP id to its RTSP track, and let it
  * initialize with the parameters of the SETUP request */
 int RtspTrackAttach( rtsp_stream_t *rtsp, const char *name,
@@ -764,6 +834,7 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
                             continue;
                         }
                     }
+                    RtspClientAlive(ses);
 
                     INSERT_ELEM( ses->trackv, ses->trackc, ses->trackc,
                                  track );
@@ -825,6 +896,7 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
                               + sizeof("url=/trackID=123;seq=65535;"
                                        "rtptime=4294967295, ") ) + 1];
                 size_t infolen = 0;
+                RtspClientAlive(ses);
 
                 sout_stream_id_t *sout_id = NULL;
                 if (vod)
@@ -927,7 +999,10 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
             vlc_mutex_lock( &rtsp->lock );
             ses = RtspClientGet( rtsp, psz_session );
             if (ses != NULL)
+            {
                 vod_pause(rtsp->vod_media, psz_session);
+                RtspClientAlive(ses);
+            }
             vlc_mutex_unlock( &rtsp->lock );
             break;
         }
@@ -941,6 +1016,11 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
 
             psz_session = httpd_MsgGet( query, "Session" );
             answer->i_status = 200;
+            vlc_mutex_lock( &rtsp->lock );
+            rtsp_session_t *ses = RtspClientGet( rtsp, psz_session );
+            if (ses != NULL)
+                RtspClientAlive(ses);
+            vlc_mutex_unlock( &rtsp->lock );
             break;
 
         case HTTPD_MSG_TEARDOWN:
@@ -960,15 +1040,19 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
                     RtspClientDel( rtsp, ses );
                     if (vod)
                         vod_stop(rtsp->vod_media, psz_session);
+                    RtspUpdateTimer(rtsp);
                 }
                 else /* Delete one track from the session */
-                for( int i = 0; i < ses->trackc; i++ )
                 {
-                    if( ses->trackv[i].id == id )
+                    for( int i = 0; i < ses->trackc; i++ )
                     {
-                        RtspTrackClose( &ses->trackv[i] );
-                        REMOVE_ELEM( ses->trackv, ses->trackc, i );
+                        if( ses->trackv[i].id == id )
+                        {
+                            RtspTrackClose( &ses->trackv[i] );
+                            REMOVE_ELEM( ses->trackv, ses->trackc, i );
+                        }
                     }
+                    RtspClientAlive(ses);
                 }
             }
             vlc_mutex_unlock( &rtsp->lock );
@@ -980,7 +1064,13 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
     }
 
     if( psz_session )
-        httpd_MsgAdd( answer, "Session", "%s"/*;timeout=5*/, psz_session );
+    {
+        if (rtsp->timeout > 0)
+            httpd_MsgAdd( answer, "Session", "%s;timeout=%d", psz_session,
+                                                              rtsp->timeout );
+        else
+            httpd_MsgAdd( answer, "Session", "%s", psz_session );
+    }
 
     httpd_MsgAdd( answer, "Content-Length", "%d", answer->i_body );
     httpd_MsgAdd( answer, "Cache-Control", "no-cache" );



More information about the vlc-commits mailing list