diff options
author | John Lindgren <john.lindgren@avasure.com> | 2020-11-05 16:02:49 -0500 |
---|---|---|
committer | John Lindgren <21949-jlindgren90@users.noreply.gitlab.freedesktop.org> | 2020-12-23 19:45:13 +0000 |
commit | c4762da9b702a205c78d9ea6b75447d0edd0d0fd (patch) | |
tree | 651da8235221eb2963f31f647634f0a308dd6533 | |
parent | 9f42f941d7cc579813e45444e37de76290cebe69 (diff) |
Make a mount point of "/" work correctly.
As far as I can tell, this is neither explicitly allowed nor
forbidden by RFC 7826.
Meanwhile, URLs such as rtsp://<IP>:554 or rtsp://<IP>:554/ are in
use in the wild (presumably with non-GStreamer servers).
GStreamer's prior behavior was confusing, in that
gst_rtsp_mount_points_add_factory() would appear to accept a mount
path of "" or "/", but later connection attempts would fail with a
"media not found" error.
This commit makes a mount path of "/" work for either form of URL,
while an empty mount path ("") is rejected and logs a warning.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-rtsp-server/-/merge_requests/168>
-rw-r--r-- | gst/rtsp-server/rtsp-client.c | 20 | ||||
-rw-r--r-- | gst/rtsp-server/rtsp-mount-points.c | 14 | ||||
-rw-r--r-- | gst/rtsp-server/rtsp-session-media.c | 6 |
3 files changed, 31 insertions, 9 deletions
diff --git a/gst/rtsp-server/rtsp-client.c b/gst/rtsp-server/rtsp-client.c index 8a34e1d..a83725c 100644 --- a/gst/rtsp-server/rtsp-client.c +++ b/gst/rtsp-server/rtsp-client.c @@ -1320,10 +1320,12 @@ default_make_path_from_uri (GstRTSPClient * client, const GstRTSPUrl * uri) { gchar *path; - if (uri->query) + if (uri->query) { path = g_strconcat (uri->abspath, "?", uri->query, NULL); - else - path = g_strdup (uri->abspath); + } else { + /* normalize rtsp://<IP>:<PORT> to rtsp://<IP>:<PORT>/ */ + path = g_strdup (uri->abspath[0] ? uri->abspath : "/"); + } return path; } @@ -2763,9 +2765,15 @@ handle_setup_request (GstRTSPClient * client, GstRTSPContext * ctx) } } else { /* path is what matched. */ - path[matched] = '\0'; + gchar *newpath = g_strndup (path, matched); /* control is remainder */ - control = &path[matched + 1]; + if (matched == 1 && path[0] == '/') + control = g_strdup (&path[1]); + else + control = g_strdup (&path[matched + 1]); + + g_free (path); + path = newpath; /* find the stream now using the control part */ stream = gst_rtsp_media_find_stream (media, control); @@ -2977,6 +2985,7 @@ handle_setup_request (GstRTSPClient * client, GstRTSPContext * ctx) g_object_unref (media); g_object_unref (session); g_free (path); + g_free (control); return TRUE; @@ -3109,6 +3118,7 @@ keymgmt_error: g_object_unref (session); cleanup_path: g_free (path); + g_free (control); return FALSE; } } diff --git a/gst/rtsp-server/rtsp-mount-points.c b/gst/rtsp-server/rtsp-mount-points.c index 1011983..145c5ac 100644 --- a/gst/rtsp-server/rtsp-mount-points.c +++ b/gst/rtsp-server/rtsp-mount-points.c @@ -171,7 +171,8 @@ gst_rtsp_mount_points_new (void) static gchar * default_make_path (GstRTSPMountPoints * mounts, const GstRTSPUrl * url) { - return g_strdup (url->abspath); + /* normalize rtsp://<IP>:<PORT> to rtsp://<IP>:<PORT>/ */ + return g_strdup (url->abspath[0] ? url->abspath : "/"); } /** @@ -210,6 +211,10 @@ has_prefix (DataItem * str, DataItem * prefix) if (str->len < prefix->len) return FALSE; + /* special case when "/" is the entire prefix */ + if (prefix->len == 1 && prefix->path[0] == '/' && str->path[0] == '/') + return TRUE; + /* if str is larger, it there should be a / following the prefix */ if (str->len > prefix->len && str->path[prefix->len] != '/') return FALSE; @@ -331,7 +336,8 @@ gst_rtsp_mount_points_remove_factory_unlocked (GstRTSPMountPoints * mounts, * * Attach @factory to the mount point @path in @mounts. * - * @path is of the form (/node)+. Any previous mount point will be freed. + * @path is either of the form (/node)+ or the root path '/'. (An empty path is + * not allowed.) Any previous mount point will be freed. * * Ownership is taken of the reference on @factory so that @factory should not be * used after calling this function. @@ -345,7 +351,7 @@ gst_rtsp_mount_points_add_factory (GstRTSPMountPoints * mounts, g_return_if_fail (GST_IS_RTSP_MOUNT_POINTS (mounts)); g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory)); - g_return_if_fail (path != NULL); + g_return_if_fail (path != NULL && path[0] == '/'); priv = mounts->priv; @@ -374,7 +380,7 @@ gst_rtsp_mount_points_remove_factory (GstRTSPMountPoints * mounts, GstRTSPMountPointsPrivate *priv; g_return_if_fail (GST_IS_RTSP_MOUNT_POINTS (mounts)); - g_return_if_fail (path != NULL); + g_return_if_fail (path != NULL && path[0] == '/'); priv = mounts->priv; diff --git a/gst/rtsp-server/rtsp-session-media.c b/gst/rtsp-server/rtsp-session-media.c index 6b4bb14..8fdb7e2 100644 --- a/gst/rtsp-server/rtsp-session-media.c +++ b/gst/rtsp-server/rtsp-session-media.c @@ -194,6 +194,12 @@ gst_rtsp_session_media_matches (GstRTSPSessionMedia * media, if (len < priv->path_len) return FALSE; + /* special case when "/" is the entire path */ + if (priv->path_len == 1 && priv->path[0] == '/' && path[0] == '/') { + *matched = 1; + return TRUE; + } + /* if media path is larger, it there should be a / following the path */ if (len > priv->path_len && path[priv->path_len] != '/') return FALSE; |