From 5a833f503eb22a25b73646d9a82ecc3f0e9406f9 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 3 Jul 2013 12:37:48 +0200 Subject: [PATCH] session: use path matching for session media Use a path string instead of a uri to lookup session media in the sessions. Also use path matching to find the largest possible path that matches. --- gst/rtsp-server/rtsp-client.c | 28 +++++++++++---- gst/rtsp-server/rtsp-session-media.c | 53 +++++++++++++++++++--------- gst/rtsp-server/rtsp-session-media.h | 15 +++----- gst/rtsp-server/rtsp-session.c | 40 +++++++++++++-------- gst/rtsp-server/rtsp-session.h | 5 +-- 5 files changed, 92 insertions(+), 49 deletions(-) diff --git a/gst/rtsp-server/rtsp-client.c b/gst/rtsp-server/rtsp-client.c index b61efaa62c..09d6daceb5 100644 --- a/gst/rtsp-server/rtsp-client.c +++ b/gst/rtsp-server/rtsp-client.c @@ -502,8 +502,7 @@ find_media (GstRTSPClient * client, GstRTSPClientState * state) goto no_mount_points; /* find the factory for the uri first */ - if (!(factory = - gst_rtsp_mount_points_match (priv->mount_points, + if (!(factory = gst_rtsp_mount_points_match (priv->mount_points, state->uri->abspath, NULL))) goto no_factory; @@ -698,6 +697,8 @@ handle_teardown_request (GstRTSPClient * client, GstRTSPClientState * state) GstRTSPSession *session; GstRTSPSessionMedia *sessmedia; GstRTSPStatusCode code; + const gchar *path; + gint matched; if (!state->session) goto no_session; @@ -707,8 +708,10 @@ handle_teardown_request (GstRTSPClient * client, GstRTSPClientState * state) if (!state->uri) goto no_uri; + path = state->uri->abspath; + /* get a handle to the configuration of the media in the session */ - sessmedia = gst_rtsp_session_get_media (session, state->uri); + sessmedia = gst_rtsp_session_get_media (session, path, &matched); if (!sessmedia) goto not_found; @@ -863,6 +866,8 @@ handle_pause_request (GstRTSPClient * client, GstRTSPClientState * state) GstRTSPSessionMedia *sessmedia; GstRTSPStatusCode code; GstRTSPState rtspstate; + const gchar *path; + gint matched; if (!(session = state->session)) goto no_session; @@ -870,8 +875,10 @@ handle_pause_request (GstRTSPClient * client, GstRTSPClientState * state) if (!state->uri) goto no_uri; + path = state->uri->abspath; + /* get a handle to the configuration of the media in the session */ - sessmedia = gst_rtsp_session_get_media (session, state->uri); + sessmedia = gst_rtsp_session_get_media (session, path, &matched); if (!sessmedia) goto not_found; @@ -946,6 +953,8 @@ handle_play_request (GstRTSPClient * client, GstRTSPClientState * state) GstRTSPResult res; GstRTSPState rtspstate; GstRTSPRangeUnit unit = GST_RTSP_RANGE_NPT; + const gchar *path; + gint matched; if (!(session = state->session)) goto no_session; @@ -953,8 +962,10 @@ handle_play_request (GstRTSPClient * client, GstRTSPClientState * state) if (!state->uri) goto no_uri; + path = state->uri->abspath; + /* get a handle to the configuration of the media in the session */ - sessmedia = gst_rtsp_session_get_media (session, state->uri); + sessmedia = gst_rtsp_session_get_media (session, path, &matched); if (!sessmedia) goto not_found; @@ -1290,11 +1301,14 @@ handle_setup_request (GstRTSPClient * client, GstRTSPClientState * state) GstRTSPStream *stream; GstRTSPState rtspstate; GstRTSPClientClass *klass; + const gchar *path; + gint matched; if (!state->uri) goto no_uri; uri = state->uri; + path = state->uri->abspath; /* the uri contains the stream number we added in the SDP config, which is * always /stream=%d so we need to strip that off @@ -1340,7 +1354,7 @@ handle_setup_request (GstRTSPClient * client, GstRTSPClientState * state) g_object_ref (session); /* get a handle to the configuration of the media in the session, this can * return NULL if this is a new url to manage in this session. */ - sessmedia = gst_rtsp_session_get_media (session, uri); + sessmedia = gst_rtsp_session_get_media (session, path, &matched); } else { /* create a session if this fails we probably reached our session limit or * something. */ @@ -1365,7 +1379,7 @@ handle_setup_request (GstRTSPClient * client, GstRTSPClientState * state) /* get a handle to the configuration of the media in the session */ if ((media = find_media (client, state))) { /* manage the media in our session now */ - sessmedia = gst_rtsp_session_manage_media (session, uri, media); + sessmedia = gst_rtsp_session_manage_media (session, path, media); } } diff --git a/gst/rtsp-server/rtsp-session-media.c b/gst/rtsp-server/rtsp-session-media.c index c475f8f481..57f4473d97 100644 --- a/gst/rtsp-server/rtsp-session-media.c +++ b/gst/rtsp-server/rtsp-session-media.c @@ -26,7 +26,8 @@ struct _GstRTSPSessionMediaPrivate { GMutex lock; - GstRTSPUrl *url; /* unmutable */ + gchar *path; /* unmutable */ + gint path_len; /* unmutable */ GstRTSPMedia *media; /* unmutable */ GstRTSPState state; /* protected by lock */ guint counter; /* protected by lock */ @@ -88,7 +89,7 @@ gst_rtsp_session_media_finalize (GObject * obj) g_ptr_array_unref (priv->transports); - gst_rtsp_url_free (priv->url); + g_free (priv->path); g_object_unref (priv->media); g_mutex_clear (&priv->lock); @@ -104,24 +105,24 @@ free_session_media (gpointer data) /** * gst_rtsp_session_media_new: - * @url: the #GstRTSPUrl + * @path: the path * @media: the #GstRTSPMedia * * Create a new #GstRTPSessionMedia that manages the streams - * in @media for @url. @media should be prepared. + * in @media for @path. @media should be prepared. * * Ownership is taken of @media. * * Returns: a new #GstRTSPSessionMedia. */ GstRTSPSessionMedia * -gst_rtsp_session_media_new (const GstRTSPUrl * url, GstRTSPMedia * media) +gst_rtsp_session_media_new (const gchar * path, GstRTSPMedia * media) { GstRTSPSessionMediaPrivate *priv; GstRTSPSessionMedia *result; guint n_streams; - g_return_val_if_fail (url != NULL, NULL); + g_return_val_if_fail (path != NULL, NULL); g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL); g_return_val_if_fail (gst_rtsp_media_get_status (media) == GST_RTSP_MEDIA_STATUS_PREPARED, NULL); @@ -129,7 +130,8 @@ gst_rtsp_session_media_new (const GstRTSPUrl * url, GstRTSPMedia * media) result = g_object_new (GST_TYPE_RTSP_SESSION_MEDIA, NULL); priv = result->priv; - priv->url = gst_rtsp_url_copy ((GstRTSPUrl *) url); + priv->path = g_strdup (path); + priv->path_len = strlen (path); priv->media = media; /* prealloc the streams now, filled with NULL */ @@ -141,22 +143,41 @@ gst_rtsp_session_media_new (const GstRTSPUrl * url, GstRTSPMedia * media) } /** - * gst_rtsp_session_media_matches_url: + * gst_rtsp_session_media_matches: * @media: a #GstRTSPSessionMedia - * @url: a #GstRTSPUrl + * @path: a path + * @matched: the amount of matched characters of @path * - * Check if the url of @media matches @url. + * Check if the path of @media matches @path. It @path matches, the amount of + * matched characters is returned in @matched. * - * Returns: %TRUE when @url matches the url of @media. + * Returns: %TRUE when @path matches the path of @media. */ gboolean -gst_rtsp_session_media_matches_url (GstRTSPSessionMedia * media, - const GstRTSPUrl * url) +gst_rtsp_session_media_matches (GstRTSPSessionMedia * media, + const gchar * path, gint * matched) { - g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), FALSE); - g_return_val_if_fail (url != NULL, FALSE); + GstRTSPSessionMediaPrivate *priv; + gint len; - return g_str_equal (media->priv->url->abspath, url->abspath); + g_return_val_if_fail (GST_IS_RTSP_SESSION_MEDIA (media), FALSE); + g_return_val_if_fail (path != NULL, FALSE); + g_return_val_if_fail (matched != NULL, FALSE); + + priv = media->priv; + len = strlen (path); + + /* path needs to be smaller than the media path */ + if (len < priv->path_len) + return FALSE; + + /* if media path is larger, it there should be a / following the path */ + if (len > priv->path_len && path[priv->path_len] != '/') + return FALSE; + + *matched = priv->path_len; + + return strncmp (path, priv->path, priv->path_len) == 0; } /** diff --git a/gst/rtsp-server/rtsp-session-media.h b/gst/rtsp-server/rtsp-session-media.h index 167c0aaba5..2cbc60282e 100644 --- a/gst/rtsp-server/rtsp-session-media.h +++ b/gst/rtsp-server/rtsp-session-media.h @@ -41,14 +41,8 @@ typedef struct _GstRTSPSessionMediaPrivate GstRTSPSessionMediaPrivate; /** * GstRTSPSessionMedia: - * @url: the url of the media - * @media: the pipeline for the media - * @state: the server state - * @counter: counter for channels - * @transports: array of #GstRTSPStreamTransport with the configuration - * for the transport for each selected stream from @media. * - * State of a client session regarding a specific media identified by uri. + * State of a client session regarding a specific media identified by path. */ struct _GstRTSPSessionMedia { @@ -64,11 +58,12 @@ struct _GstRTSPSessionMediaClass GType gst_rtsp_session_media_get_type (void); -GstRTSPSessionMedia * gst_rtsp_session_media_new (const GstRTSPUrl *url, +GstRTSPSessionMedia * gst_rtsp_session_media_new (const gchar *path, GstRTSPMedia *media); -gboolean gst_rtsp_session_media_matches_url (GstRTSPSessionMedia *media, - const GstRTSPUrl *url); +gboolean gst_rtsp_session_media_matches (GstRTSPSessionMedia *media, + const gchar *path, + gint * matched); GstRTSPMedia * gst_rtsp_session_media_get_media (GstRTSPSessionMedia *media); GstClockTime gst_rtsp_session_media_get_base_time (GstRTSPSessionMedia *media); diff --git a/gst/rtsp-server/rtsp-session.c b/gst/rtsp-server/rtsp-session.c index 87d03ffd05..fe93a5f260 100644 --- a/gst/rtsp-server/rtsp-session.c +++ b/gst/rtsp-server/rtsp-session.c @@ -162,10 +162,10 @@ gst_rtsp_session_set_property (GObject * object, guint propid, /** * gst_rtsp_session_manage_media: * @sess: a #GstRTSPSession - * @uri: the uri for the media + * @path: the path for the media * @media: (transfer full): a #GstRTSPMedia * - * Manage the media object @obj in @sess. @uri will be used to retrieve this + * Manage the media object @obj in @sess. @path will be used to retrieve this * media from the session with gst_rtsp_session_get_media(). * * Ownership is taken from @media. @@ -173,21 +173,21 @@ gst_rtsp_session_set_property (GObject * object, guint propid, * Returns: (transfer none): a new @GstRTSPSessionMedia object. */ GstRTSPSessionMedia * -gst_rtsp_session_manage_media (GstRTSPSession * sess, const GstRTSPUrl * uri, +gst_rtsp_session_manage_media (GstRTSPSession * sess, const gchar * path, GstRTSPMedia * media) { GstRTSPSessionPrivate *priv; GstRTSPSessionMedia *result; g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), NULL); - g_return_val_if_fail (uri != NULL, NULL); + g_return_val_if_fail (path != NULL, NULL); g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL); g_return_val_if_fail (gst_rtsp_media_get_status (media) == GST_RTSP_MEDIA_STATUS_PREPARED, NULL); priv = sess->priv; - result = gst_rtsp_session_media_new (uri, media); + result = gst_rtsp_session_media_new (path, media); g_mutex_lock (&priv->lock); priv->medias = g_list_prepend (priv->medias, result); @@ -236,36 +236,48 @@ gst_rtsp_session_release_media (GstRTSPSession * sess, /** * gst_rtsp_session_get_media: * @sess: a #GstRTSPSession - * @url: the url for the media + * @path: the path for the media + * @matched: the amount of matched characters * - * Get the session media of the @url. + * Get the session media for @path. @matched will contain the number of matched + * characters of @path. * - * Returns: (transfer none): the configuration for @url in @sess. + * Returns: (transfer none): the configuration for @path in @sess. */ GstRTSPSessionMedia * -gst_rtsp_session_get_media (GstRTSPSession * sess, const GstRTSPUrl * url) +gst_rtsp_session_get_media (GstRTSPSession * sess, const gchar * path, + gint * matched) { GstRTSPSessionPrivate *priv; GstRTSPSessionMedia *result; GList *walk; + gint best; g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), NULL); - g_return_val_if_fail (url != NULL, NULL); + g_return_val_if_fail (path != NULL, NULL); priv = sess->priv; result = NULL; + best = 0; g_mutex_lock (&priv->lock); for (walk = priv->medias; walk; walk = g_list_next (walk)) { - result = (GstRTSPSessionMedia *) walk->data; + GstRTSPSessionMedia *test; - if (gst_rtsp_session_media_matches_url (result, url)) - break; + test = (GstRTSPSessionMedia *) walk->data; - result = NULL; + /* find largest match */ + if (gst_rtsp_session_media_matches (test, path, matched)) { + if (best < *matched) { + result = test; + best = *matched; + } + } } g_mutex_unlock (&priv->lock); + *matched = best; + return result; } diff --git a/gst/rtsp-server/rtsp-session.h b/gst/rtsp-server/rtsp-session.h index 844795d27f..e206032735 100644 --- a/gst/rtsp-server/rtsp-session.h +++ b/gst/rtsp-server/rtsp-session.h @@ -95,13 +95,14 @@ gboolean gst_rtsp_session_is_expired (GstRTSPSession *se /* handle media in a session */ GstRTSPSessionMedia * gst_rtsp_session_manage_media (GstRTSPSession *sess, - const GstRTSPUrl *uri, + const gchar *path, GstRTSPMedia *media); gboolean gst_rtsp_session_release_media (GstRTSPSession *sess, GstRTSPSessionMedia *media); /* get media in a session */ GstRTSPSessionMedia * gst_rtsp_session_get_media (GstRTSPSession *sess, - const GstRTSPUrl *url); + const gchar *path, + gint * matched); /** * GstRTSPSessionFilterFunc: