[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