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
This commit is contained in:
Dag Gullberg 2016-11-21 16:02:39 +01:00 committed by Tim-Philipp Müller
parent 9777e4dcd6
commit f00ac2daf2

View file

@ -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,
@ -2140,6 +2146,47 @@ handle_keymgmt (GstRTSPClient * client, GstRTSPContext * ctx, gchar * keymgmt)
return TRUE;
}
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)
{
@ -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;
}