mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-14 05:12:09 +00:00
rtsp-client: add property post-session-timeout
This is a TCP connection timeout for client connections, in seconds. If a positive value is set for this property, the client connection will be kept alive for this amount of seconds after the last session timeout. For negative values of this property the connection timeout handling is delegated to the system (just as it was before). Fixes #83
This commit is contained in:
parent
0ed32e0d53
commit
aa8126b239
2 changed files with 170 additions and 0 deletions
|
@ -103,6 +103,7 @@ struct _GstRTSPClientPrivate
|
|||
guint sessions_cookie;
|
||||
|
||||
gboolean drop_backlog;
|
||||
gint post_session_timeout;
|
||||
|
||||
guint content_length_limit;
|
||||
|
||||
|
@ -130,6 +131,7 @@ static GHashTable *tunnels; /* protected by tunnels_lock */
|
|||
#define DEFAULT_SESSION_POOL NULL
|
||||
#define DEFAULT_MOUNT_POINTS NULL
|
||||
#define DEFAULT_DROP_BACKLOG TRUE
|
||||
#define DEFAULT_POST_SESSION_TIMEOUT -1
|
||||
|
||||
#define RTSP_CTRL_CB_INTERVAL 1
|
||||
#define RTSP_CTRL_TIMEOUT_VALUE 60
|
||||
|
@ -140,6 +142,7 @@ enum
|
|||
PROP_SESSION_POOL,
|
||||
PROP_MOUNT_POINTS,
|
||||
PROP_DROP_BACKLOG,
|
||||
PROP_POST_SESSION_TIMEOUT,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
|
@ -255,6 +258,26 @@ gst_rtsp_client_class_init (GstRTSPClientClass * klass)
|
|||
"Drop data when the backlog queue is full",
|
||||
DEFAULT_DROP_BACKLOG, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* GstRTSPClient::post-session-timeout:
|
||||
*
|
||||
* An extra tcp timeout ( > 0) after session timeout, in seconds.
|
||||
* The tcp connection will be kept alive until this timeout happens to give
|
||||
* the client a possibility to reuse the connection.
|
||||
* 0 means that the connection will be closed immediately after the session
|
||||
* timeout.
|
||||
*
|
||||
* Default value is -1 seconds, meaning that we let the system close
|
||||
* the connection.
|
||||
*
|
||||
* Since: 1.18
|
||||
*/
|
||||
g_object_class_install_property (gobject_class, PROP_POST_SESSION_TIMEOUT,
|
||||
g_param_spec_int ("post-session-timeout", "Post Session Timeout",
|
||||
"An extra TCP connection timeout after session timeout", G_MININT,
|
||||
G_MAXINT, DEFAULT_POST_SESSION_TIMEOUT,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
gst_rtsp_client_signals[SIGNAL_CLOSED] =
|
||||
g_signal_new ("closed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstRTSPClientClass, closed), NULL, NULL, NULL,
|
||||
|
@ -588,6 +611,7 @@ gst_rtsp_client_init (GstRTSPClient * client)
|
|||
priv->close_seq = 0;
|
||||
priv->data_seqs = g_array_new (FALSE, FALSE, sizeof (DataSeq));
|
||||
priv->drop_backlog = DEFAULT_DROP_BACKLOG;
|
||||
priv->post_session_timeout = DEFAULT_POST_SESSION_TIMEOUT;
|
||||
priv->transports =
|
||||
g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
|
||||
g_object_unref);
|
||||
|
@ -807,6 +831,9 @@ gst_rtsp_client_get_property (GObject * object, guint propid,
|
|||
case PROP_DROP_BACKLOG:
|
||||
g_value_set_boolean (value, priv->drop_backlog);
|
||||
break;
|
||||
case PROP_POST_SESSION_TIMEOUT:
|
||||
g_value_set_int (value, priv->post_session_timeout);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
|
||||
}
|
||||
|
@ -831,6 +858,11 @@ gst_rtsp_client_set_property (GObject * object, guint propid,
|
|||
priv->drop_backlog = g_value_get_boolean (value);
|
||||
g_mutex_unlock (&priv->lock);
|
||||
break;
|
||||
case PROP_POST_SESSION_TIMEOUT:
|
||||
g_mutex_lock (&priv->lock);
|
||||
priv->post_session_timeout = g_value_get_int (value);
|
||||
g_mutex_unlock (&priv->lock);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
|
||||
}
|
||||
|
@ -2531,6 +2563,23 @@ rtsp_ctrl_timeout_cb (gpointer user_data)
|
|||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
rtsp_ctrl_connection_timeout_cb (gpointer user_data)
|
||||
{
|
||||
GstRTSPClient *client = (GstRTSPClient *) user_data;
|
||||
GstRTSPClientPrivate *priv = client->priv;
|
||||
|
||||
GST_DEBUG ("rtsp control connection 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);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
rtsp_ctrl_timeout_remove (GstRTSPClientPrivate * priv)
|
||||
{
|
||||
|
@ -3694,12 +3743,33 @@ client_session_removed (GstRTSPSessionPool * pool, GstRTSPSession * session,
|
|||
GstRTSPClient * client)
|
||||
{
|
||||
GstRTSPClientPrivate *priv = client->priv;
|
||||
GSource *timer_src;
|
||||
|
||||
GST_INFO ("client %p: session %p removed", client, session);
|
||||
|
||||
g_mutex_lock (&priv->lock);
|
||||
client_unwatch_session (client, session, NULL);
|
||||
g_mutex_unlock (&priv->lock);
|
||||
|
||||
if (!priv->sessions && priv->rtsp_ctrl_timeout_id == 0) {
|
||||
if (priv->post_session_timeout > 0) {
|
||||
g_mutex_lock (&priv->lock);
|
||||
|
||||
timer_src = g_timeout_source_new_seconds (priv->post_session_timeout);
|
||||
g_source_set_callback (timer_src, rtsp_ctrl_connection_timeout_cb,
|
||||
client, NULL);
|
||||
priv->rtsp_ctrl_timeout_cnt = 0;
|
||||
priv->rtsp_ctrl_timeout_id = g_source_attach (timer_src,
|
||||
priv->watch_context);
|
||||
g_source_unref (timer_src);
|
||||
GST_DEBUG ("rtsp control setting up connection timeout id=%u.",
|
||||
priv->rtsp_ctrl_timeout_id);
|
||||
|
||||
g_mutex_unlock (&priv->lock);
|
||||
} else if (priv->post_session_timeout == 0) {
|
||||
gst_rtsp_client_close (client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for Require headers. Returns TRUE if there are no Require headers,
|
||||
|
|
|
@ -1643,6 +1643,105 @@ GST_START_TEST (test_play_multithreaded_timeout_session)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
static void
|
||||
new_connection_and_session_timeout_one (GstRTSPClient * client,
|
||||
GstRTSPSession * session, gpointer user_data)
|
||||
{
|
||||
gint ps_timeout = 0;
|
||||
|
||||
g_object_set (G_OBJECT (client), "post-session-timeout", 1, NULL);
|
||||
g_object_get (G_OBJECT (client), "post-session-timeout", &ps_timeout, NULL);
|
||||
fail_unless_equals_int (ps_timeout, 1);
|
||||
|
||||
g_object_set (G_OBJECT (session), "extra-timeout", 0, NULL);
|
||||
gst_rtsp_session_set_timeout (session, 1);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (client,
|
||||
new_connection_and_session_timeout_one, user_data);
|
||||
}
|
||||
|
||||
GST_START_TEST (test_play_timeout_connection)
|
||||
{
|
||||
GstRTSPConnection *conn;
|
||||
GstSDPMessage *sdp_message = NULL;
|
||||
const GstSDPMedia *sdp_media;
|
||||
const gchar *video_control;
|
||||
GstRTSPRange client_port;
|
||||
gchar *session = NULL;
|
||||
GstRTSPTransport *video_transport = NULL;
|
||||
GstRTSPSessionPool *pool;
|
||||
GstRTSPThreadPool *thread_pool;
|
||||
GstRTSPMessage *request;
|
||||
GstRTSPMessage *response;
|
||||
|
||||
thread_pool = gst_rtsp_server_get_thread_pool (server);
|
||||
g_object_unref (thread_pool);
|
||||
|
||||
pool = gst_rtsp_server_get_session_pool (server);
|
||||
g_signal_connect (server, "client-connected",
|
||||
G_CALLBACK (session_connected_new_session_cb),
|
||||
new_connection_and_session_timeout_one);
|
||||
|
||||
start_server (FALSE);
|
||||
|
||||
|
||||
conn = connect_to_server (test_port, TEST_MOUNT_POINT);
|
||||
|
||||
gst_rtsp_connection_set_remember_session_id (conn, FALSE);
|
||||
|
||||
sdp_message = do_describe (conn, TEST_MOUNT_POINT);
|
||||
|
||||
/* get control strings from DESCRIBE response */
|
||||
fail_unless (gst_sdp_message_medias_len (sdp_message) == 2);
|
||||
sdp_media = gst_sdp_message_get_media (sdp_message, 0);
|
||||
video_control = gst_sdp_media_get_attribute_val (sdp_media, "control");
|
||||
|
||||
get_client_ports (&client_port);
|
||||
|
||||
/* do SETUP for video and audio */
|
||||
fail_unless (do_setup (conn, video_control, &client_port, &session,
|
||||
&video_transport) == GST_RTSP_STS_OK);
|
||||
fail_unless (gst_rtsp_session_pool_get_n_sessions (pool) == 1);
|
||||
/* send PLAY request and check that we get 200 OK */
|
||||
fail_unless (do_simple_request (conn, GST_RTSP_PLAY,
|
||||
session) == GST_RTSP_STS_OK);
|
||||
sleep (2);
|
||||
fail_unless (gst_rtsp_session_pool_cleanup (pool) == 1);
|
||||
sleep (2);
|
||||
|
||||
request = create_request (conn, GST_RTSP_TEARDOWN, NULL);
|
||||
|
||||
/* add headers */
|
||||
if (session) {
|
||||
gst_rtsp_message_add_header (request, GST_RTSP_HDR_SESSION, session);
|
||||
}
|
||||
|
||||
/* send request */
|
||||
fail_unless (send_request (conn, request));
|
||||
gst_rtsp_message_free (request);
|
||||
|
||||
iterate ();
|
||||
|
||||
/* read response */
|
||||
response = read_response (conn);
|
||||
fail_unless (response == NULL);
|
||||
|
||||
if (response) {
|
||||
gst_rtsp_message_free (response);
|
||||
}
|
||||
|
||||
/* clean up and iterate so the clean-up can finish */
|
||||
g_object_unref (pool);
|
||||
g_free (session);
|
||||
gst_rtsp_transport_free (video_transport);
|
||||
gst_sdp_message_free (sdp_message);
|
||||
gst_rtsp_connection_free (conn);
|
||||
|
||||
stop_server ();
|
||||
iterate ();
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_no_session_timeout)
|
||||
{
|
||||
|
@ -2631,6 +2730,7 @@ rtspserver_suite (void)
|
|||
tcase_add_test (tc, test_play_multithreaded_block_in_describe);
|
||||
tcase_add_test (tc, test_play_multithreaded_timeout_client);
|
||||
tcase_add_test (tc, test_play_multithreaded_timeout_session);
|
||||
tcase_add_test (tc, test_play_timeout_connection);
|
||||
tcase_add_test (tc, test_no_session_timeout);
|
||||
tcase_add_test (tc, test_play_one_active_stream);
|
||||
tcase_add_test (tc, test_play_disconnect);
|
||||
|
|
Loading…
Reference in a new issue