From f00ac2daf244fecf59272bfd841685cc0af7d512 Mon Sep 17 00:00:00 2001 From: Dag Gullberg Date: Mon, 21 Nov 2016 16:02:39 +0100 Subject: [PATCH] rtsp-client: add IDLE timeout, before session exists The RTSP server will not timeout an idle RTSP connection (note this is different from doing timeout on a RTSP session). At least for Apache this is a problem when running RTSP over HTTPS since it uses one of the threads (there is a rather limited number) that are available for handling requests. https://bugzilla.gnome.org/show_bug.cgi?id=771830 --- gst/rtsp-server/rtsp-client.c | 65 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/gst/rtsp-server/rtsp-client.c b/gst/rtsp-server/rtsp-client.c index ab6e865..6f59c5e 100644 --- a/gst/rtsp-server/rtsp-client.c +++ b/gst/rtsp-server/rtsp-client.c @@ -90,6 +90,9 @@ struct _GstRTSPClientPrivate guint sessions_cookie; gboolean drop_backlog; + + guint rtsp_ctrl_timeout_id; + guint rtsp_ctrl_timeout_cnt; }; static GMutex tunnels_lock; @@ -103,6 +106,9 @@ static GHashTable *tunnels; /* protected by tunnels_lock */ #define DEFAULT_MOUNT_POINTS NULL #define DEFAULT_DROP_BACKLOG TRUE +#define RTSP_CTRL_CB_INTERVAL 1 +#define RTSP_CTRL_TIMEOUT_VALUE 60 + enum { PROP_0, @@ -2141,6 +2147,47 @@ handle_keymgmt (GstRTSPClient * client, GstRTSPContext * ctx, gchar * keymgmt) } static gboolean +rtsp_ctrl_timeout_cb (gpointer user_data) +{ + gboolean res = G_SOURCE_CONTINUE; + GstRTSPClient *client = (GstRTSPClient *) user_data; + GstRTSPClientPrivate *priv = client->priv; + + priv->rtsp_ctrl_timeout_cnt += RTSP_CTRL_CB_INTERVAL; + + if (priv->rtsp_ctrl_timeout_cnt > RTSP_CTRL_TIMEOUT_VALUE) { + GST_DEBUG ("rtsp control session timeout id=%u expired, closing client.", + priv->rtsp_ctrl_timeout_id); + g_mutex_lock (&priv->lock); + priv->rtsp_ctrl_timeout_id = 0; + priv->rtsp_ctrl_timeout_cnt = 0; + g_mutex_unlock (&priv->lock); + gst_rtsp_client_close (client); + + res = G_SOURCE_REMOVE; + } + + return res; +} + +static void +rtsp_ctrl_timeout_remove (GstRTSPClientPrivate * priv) +{ + g_mutex_lock (&priv->lock); + + if (priv->rtsp_ctrl_timeout_id != 0) { + g_source_destroy (g_main_context_find_source_by_id (priv->watch_context, + priv->rtsp_ctrl_timeout_id)); + GST_DEBUG ("rtsp control session removed timeout id=%u.", + priv->rtsp_ctrl_timeout_id); + priv->rtsp_ctrl_timeout_id = 0; + priv->rtsp_ctrl_timeout_cnt = 0; + } + + g_mutex_unlock (&priv->lock); +} + +static gboolean handle_setup_request (GstRTSPClient * client, GstRTSPContext * ctx) { GstRTSPClientPrivate *priv = client->priv; @@ -2256,6 +2303,8 @@ handle_setup_request (GstRTSPClient * client, GstRTSPContext * ctx) ctx->session = session; } + rtsp_ctrl_timeout_remove (priv); + if (!klass->configure_client_media (client, media, stream, ctx)) goto configure_media_failed_no_reply; @@ -4242,6 +4291,7 @@ client_watch_notify (GstRTSPClient * client) GST_INFO ("client %p: watch destroyed", client); priv->watch = NULL; /* remove all sessions if the media says so and so drop the extra client ref */ + rtsp_ctrl_timeout_remove (priv); gst_rtsp_client_session_filter (client, cleanup_session, &closed); if (closed) g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_CLOSED], 0, NULL); @@ -4266,6 +4316,7 @@ guint gst_rtsp_client_attach (GstRTSPClient * client, GMainContext * context) { GstRTSPClientPrivate *priv; + GSource *timer_src; guint res; g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), 0); @@ -4287,6 +4338,20 @@ gst_rtsp_client_attach (GstRTSPClient * client, GMainContext * context) GST_INFO ("client %p: attaching to context %p", client, context); res = gst_rtsp_watch_attach (priv->watch, context); + /* Setting up a timeout for the RTSP control channel until a session + * is up where it is handling timeouts. */ + rtsp_ctrl_timeout_remove (priv); /* removing old if any */ + g_mutex_lock (&priv->lock); + + timer_src = g_timeout_source_new_seconds (RTSP_CTRL_CB_INTERVAL); + g_source_set_callback (timer_src, rtsp_ctrl_timeout_cb, client, NULL); + priv->rtsp_ctrl_timeout_id = g_source_attach (timer_src, priv->watch_context); + g_source_unref (timer_src); + GST_DEBUG ("rtsp control setting up session timeout id=%u.", + priv->rtsp_ctrl_timeout_id); + + g_mutex_unlock (&priv->lock); + return res; } -- 2.7.4