rtsp-client: make sure sessmedia will not get freed while used

handle_*_request() functions were all retrieving the session media from
the session by calling gst_rtsp_session_get_media () which is a transfer-none
call. If a session timeout happens at that time, the session media may get freed
making the pointer invalid..

Fixes #757

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1053>
This commit is contained in:
Ognyan Tonchev 2021-10-03 23:25:23 +02:00 committed by GStreamer Marge Bot
parent ce76a286ed
commit 7ba665995f
3 changed files with 72 additions and 17 deletions

View file

@ -1447,7 +1447,7 @@ handle_teardown_request (GstRTSPClient * client, GstRTSPContext * ctx)
path = klass->make_path_from_uri (client, ctx->uri); path = klass->make_path_from_uri (client, ctx->uri);
/* get a handle to the configuration of the media in the session */ /* get a handle to the configuration of the media in the session */
sessmedia = gst_rtsp_session_get_media (session, path, &matched); sessmedia = gst_rtsp_session_dup_media (session, path, &matched);
if (!sessmedia) if (!sessmedia)
goto not_found; goto not_found;
@ -1482,6 +1482,7 @@ handle_teardown_request (GstRTSPClient * client, GstRTSPContext * ctx)
/* unmanage the media in the session, returns false if all media session /* unmanage the media in the session, returns false if all media session
* are torn down. */ * are torn down. */
keep_session = gst_rtsp_session_release_media (session, sessmedia); keep_session = gst_rtsp_session_release_media (session, sessmedia);
g_object_unref (sessmedia);
/* construct the response now */ /* construct the response now */
code = GST_RTSP_STS_OK; code = GST_RTSP_STS_OK;
@ -1532,6 +1533,7 @@ no_aggregate:
send_generic_response (client, send_generic_response (client,
GST_RTSP_STS_ONLY_AGGREGATE_OPERATION_ALLOWED, ctx); GST_RTSP_STS_ONLY_AGGREGATE_OPERATION_ALLOWED, ctx);
g_free (path); g_free (path);
g_object_unref (sessmedia);
return FALSE; return FALSE;
} }
sig_failed: sig_failed:
@ -1541,6 +1543,7 @@ sig_failed:
send_generic_response (client, sig_result, ctx); send_generic_response (client, sig_result, ctx);
gst_rtsp_media_unlock (media); gst_rtsp_media_unlock (media);
g_object_unref (media); g_object_unref (media);
g_object_unref (sessmedia);
return FALSE; return FALSE;
} }
} }
@ -1699,7 +1702,7 @@ handle_pause_request (GstRTSPClient * client, GstRTSPContext * ctx)
path = klass->make_path_from_uri (client, ctx->uri); path = klass->make_path_from_uri (client, ctx->uri);
/* get a handle to the configuration of the media in the session */ /* get a handle to the configuration of the media in the session */
sessmedia = gst_rtsp_session_get_media (session, path, &matched); sessmedia = gst_rtsp_session_dup_media (session, path, &matched);
if (!sessmedia) if (!sessmedia)
goto not_found; goto not_found;
@ -1746,6 +1749,7 @@ handle_pause_request (GstRTSPClient * client, GstRTSPContext * ctx)
/* the state is now READY */ /* the state is now READY */
gst_rtsp_session_media_set_rtsp_state (sessmedia, GST_RTSP_STATE_READY); gst_rtsp_session_media_set_rtsp_state (sessmedia, GST_RTSP_STATE_READY);
g_object_unref (sessmedia);
g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_PAUSE_REQUEST], 0, ctx); g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_PAUSE_REQUEST], 0, ctx);
@ -1779,6 +1783,7 @@ no_aggregate:
GST_ERROR ("client %p: no aggregate path %s", client, path); GST_ERROR ("client %p: no aggregate path %s", client, path);
send_generic_response (client, send_generic_response (client,
GST_RTSP_STS_ONLY_AGGREGATE_OPERATION_ALLOWED, ctx); GST_RTSP_STS_ONLY_AGGREGATE_OPERATION_ALLOWED, ctx);
g_object_unref (sessmedia);
g_free (path); g_free (path);
return FALSE; return FALSE;
} }
@ -1788,6 +1793,7 @@ sig_failed:
gst_rtsp_status_as_text (sig_result)); gst_rtsp_status_as_text (sig_result));
send_generic_response (client, sig_result, ctx); send_generic_response (client, sig_result, ctx);
gst_rtsp_media_unlock (media); gst_rtsp_media_unlock (media);
g_object_unref (sessmedia);
g_object_unref (media); g_object_unref (media);
return FALSE; return FALSE;
} }
@ -1797,6 +1803,7 @@ invalid_state:
send_generic_response (client, GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE, send_generic_response (client, GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE,
ctx); ctx);
gst_rtsp_media_unlock (media); gst_rtsp_media_unlock (media);
g_object_unref (sessmedia);
g_object_unref (media); g_object_unref (media);
return FALSE; return FALSE;
} }
@ -1805,6 +1812,7 @@ not_supported:
GST_ERROR ("client %p: pausing not supported", client); GST_ERROR ("client %p: pausing not supported", client);
send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, ctx); send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, ctx);
gst_rtsp_media_unlock (media); gst_rtsp_media_unlock (media);
g_object_unref (sessmedia);
g_object_unref (media); g_object_unref (media);
return FALSE; return FALSE;
} }
@ -2068,7 +2076,7 @@ handle_play_request (GstRTSPClient * client, GstRTSPContext * ctx)
path = klass->make_path_from_uri (client, uri); path = klass->make_path_from_uri (client, uri);
/* get a handle to the configuration of the media in the session */ /* get a handle to the configuration of the media in the session */
sessmedia = gst_rtsp_session_get_media (session, path, &matched); sessmedia = gst_rtsp_session_dup_media (session, path, &matched);
if (!sessmedia) if (!sessmedia)
goto not_found; goto not_found;
@ -2163,6 +2171,7 @@ handle_play_request (GstRTSPClient * client, GstRTSPContext * ctx)
gst_rtsp_session_media_set_state (sessmedia, GST_STATE_PLAYING); gst_rtsp_session_media_set_state (sessmedia, GST_STATE_PLAYING);
gst_rtsp_session_media_set_rtsp_state (sessmedia, GST_RTSP_STATE_PLAYING); gst_rtsp_session_media_set_rtsp_state (sessmedia, GST_RTSP_STATE_PLAYING);
g_object_unref (sessmedia);
g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_PLAY_REQUEST], 0, ctx); g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_PLAY_REQUEST], 0, ctx);
@ -2195,6 +2204,7 @@ no_aggregate:
GST_ERROR ("client %p: no aggregate path %s", client, path); GST_ERROR ("client %p: no aggregate path %s", client, path);
send_generic_response (client, send_generic_response (client,
GST_RTSP_STS_ONLY_AGGREGATE_OPERATION_ALLOWED, ctx); GST_RTSP_STS_ONLY_AGGREGATE_OPERATION_ALLOWED, ctx);
g_object_unref (sessmedia);
g_free (path); g_free (path);
return FALSE; return FALSE;
} }
@ -2205,6 +2215,7 @@ sig_failed:
send_generic_response (client, sig_result, ctx); send_generic_response (client, sig_result, ctx);
gst_rtsp_media_unlock (media); gst_rtsp_media_unlock (media);
g_object_unref (media); g_object_unref (media);
g_object_unref (sessmedia);
return FALSE; return FALSE;
} }
invalid_state: invalid_state:
@ -2214,6 +2225,7 @@ invalid_state:
ctx); ctx);
gst_rtsp_media_unlock (media); gst_rtsp_media_unlock (media);
g_object_unref (media); g_object_unref (media);
g_object_unref (sessmedia);
return FALSE; return FALSE;
} }
pipeline_error: pipeline_error:
@ -2223,6 +2235,7 @@ pipeline_error:
ctx); ctx);
gst_rtsp_media_unlock (media); gst_rtsp_media_unlock (media);
g_object_unref (media); g_object_unref (media);
g_object_unref (sessmedia);
return FALSE; return FALSE;
} }
unsuspend_failed: unsuspend_failed:
@ -2231,6 +2244,7 @@ unsuspend_failed:
send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, ctx); send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, ctx);
gst_rtsp_media_unlock (media); gst_rtsp_media_unlock (media);
g_object_unref (media); g_object_unref (media);
g_object_unref (sessmedia);
return FALSE; return FALSE;
} }
invalid_mode: invalid_mode:
@ -2239,6 +2253,7 @@ invalid_mode:
send_generic_response (client, code, ctx); send_generic_response (client, code, ctx);
gst_rtsp_media_unlock (media); gst_rtsp_media_unlock (media);
g_object_unref (media); g_object_unref (media);
g_object_unref (sessmedia);
return FALSE; return FALSE;
} }
unsupported_mode: unsupported_mode:
@ -2247,6 +2262,7 @@ unsupported_mode:
send_generic_response (client, GST_RTSP_STS_METHOD_NOT_ALLOWED, ctx); send_generic_response (client, GST_RTSP_STS_METHOD_NOT_ALLOWED, ctx);
gst_rtsp_media_unlock (media); gst_rtsp_media_unlock (media);
g_object_unref (media); g_object_unref (media);
g_object_unref (sessmedia);
return FALSE; return FALSE;
} }
get_rates_error: get_rates_error:
@ -2255,6 +2271,7 @@ get_rates_error:
send_generic_response (client, GST_RTSP_STS_INTERNAL_SERVER_ERROR, ctx); send_generic_response (client, GST_RTSP_STS_INTERNAL_SERVER_ERROR, ctx);
gst_rtsp_media_unlock (media); gst_rtsp_media_unlock (media);
g_object_unref (media); g_object_unref (media);
g_object_unref (sessmedia);
return FALSE; return FALSE;
} }
adjust_play_response_failed: adjust_play_response_failed:
@ -2263,6 +2280,7 @@ adjust_play_response_failed:
send_generic_response (client, code, ctx); send_generic_response (client, code, ctx);
gst_rtsp_media_unlock (media); gst_rtsp_media_unlock (media);
g_object_unref (media); g_object_unref (media);
g_object_unref (sessmedia);
return FALSE; return FALSE;
} }
rtp_info_error: rtp_info_error:
@ -2271,6 +2289,7 @@ rtp_info_error:
send_generic_response (client, GST_RTSP_STS_INTERNAL_SERVER_ERROR, ctx); send_generic_response (client, GST_RTSP_STS_INTERNAL_SERVER_ERROR, ctx);
gst_rtsp_media_unlock (media); gst_rtsp_media_unlock (media);
g_object_unref (media); g_object_unref (media);
g_object_unref (sessmedia);
return FALSE; return FALSE;
} }
} }

View file

@ -343,20 +343,9 @@ gst_rtsp_session_release_media (GstRTSPSession * sess,
return more; return more;
} }
/** static GstRTSPSessionMedia *
* gst_rtsp_session_get_media: _gst_rtsp_session_get_media (GstRTSPSession * sess, const gchar * path,
* @sess: a #GstRTSPSession gint * matched, gboolean dup)
* @path: the path for the media
* @matched: (out): the amount of matched characters
*
* Get the session media for @path. @matched will contain the number of matched
* characters of @path.
*
* Returns: (transfer none) (nullable): the configuration for @path in @sess.
*/
GstRTSPSessionMedia *
gst_rtsp_session_get_media (GstRTSPSession * sess, const gchar * path,
gint * matched)
{ {
GstRTSPSessionPrivate *priv; GstRTSPSessionPrivate *priv;
GstRTSPSessionMedia *result; GstRTSPSessionMedia *result;
@ -384,6 +373,9 @@ gst_rtsp_session_get_media (GstRTSPSession * sess, const gchar * path,
} }
} }
} }
if (result && dup)
result = g_object_ref (result);
g_mutex_unlock (&priv->lock); g_mutex_unlock (&priv->lock);
*matched = best; *matched = best;
@ -391,6 +383,45 @@ gst_rtsp_session_get_media (GstRTSPSession * sess, const gchar * path,
return result; return result;
} }
/**
* gst_rtsp_session_get_media:
* @sess: a #GstRTSPSession
* @path: the path for the media
* @matched: (out): the amount of matched characters
*
* Gets the session media for @path. @matched will contain the number of matched
* characters of @path.
*
* Returns: (transfer none) (nullable): the configuration for @path in @sess.
*/
GstRTSPSessionMedia *
gst_rtsp_session_get_media (GstRTSPSession * sess, const gchar * path,
gint * matched)
{
return _gst_rtsp_session_get_media (sess, path, matched, FALSE);
}
/**
* gst_rtsp_session_dup_media:
* @sess: a #GstRTSPSession
* @path: the path for the media
* @matched: (out): the amount of matched characters
*
* Gets the session media for @path, increasing its reference count. @matched
* will contain the number of matched characters of @path.
*
* Returns: (transfer full) (nullable): the configuration for @path in @sess,
* should be unreferenced when no longer needed.
*
* Since: 1.20
*/
GstRTSPSessionMedia *
gst_rtsp_session_dup_media (GstRTSPSession * sess, const gchar * path,
gint * matched)
{
return _gst_rtsp_session_get_media (sess, path, matched, TRUE);
}
/** /**
* gst_rtsp_session_filter: * gst_rtsp_session_filter:
* @sess: a #GstRTSPSession * @sess: a #GstRTSPSession

View file

@ -141,7 +141,12 @@ GST_RTSP_SERVER_API
GstRTSPSessionMedia * gst_rtsp_session_get_media (GstRTSPSession *sess, GstRTSPSessionMedia * gst_rtsp_session_get_media (GstRTSPSession *sess,
const gchar *path, const gchar *path,
gint * matched); gint * matched);
/* get media in a session, increasing its reference count */
GST_RTSP_SERVER_API
GstRTSPSessionMedia * gst_rtsp_session_dup_media (GstRTSPSession *sess,
const gchar *path,
gint * matched);
/** /**
* GstRTSPSessionFilterFunc: * GstRTSPSessionFilterFunc:
* @sess: a #GstRTSPSession object * @sess: a #GstRTSPSession object