/* used to cache the media in the last requested DESCRIBE so that
* we can pick it up in the next SETUP immediately */
- GstRTSPUrl *uri;
+ gchar *path;
GstRTSPMedia *media;
GList *transports;
if (priv->auth)
g_object_unref (priv->auth);
- if (priv->uri)
- gst_rtsp_url_free (priv->uri);
+ if (priv->path)
+ g_free (priv->path);
if (priv->media) {
gst_rtsp_media_unprepare (priv->media);
g_object_unref (priv->media);
static gboolean
-compare_uri (const GstRTSPUrl * uri1, const GstRTSPUrl * uri2)
+paths_are_equal (const gchar * path1, const gchar * path2, gint len2)
{
- if (uri1 == NULL || uri2 == NULL)
+ if (path1 == NULL || path2 == NULL)
+ return FALSE;
+
+ if (strlen (path1) != len2)
return FALSE;
- if (strcmp (uri1->abspath, uri2->abspath))
+ if (strncmp (path1, path2, len2))
return FALSE;
return TRUE;
* but is cached for when the same client (without breaking the connection) is
* doing a setup for the exact same url. */
static GstRTSPMedia *
-find_media (GstRTSPClient * client, GstRTSPClientState * state)
+find_media (GstRTSPClient * client, GstRTSPClientState * state, gint * matched)
{
GstRTSPClientPrivate *priv = client->priv;
GstRTSPMediaFactory *factory;
GstRTSPMedia *media;
GstRTSPAuth *auth;
+ gchar *path;
+ gint path_len;
+
+ if (!priv->mount_points)
+ goto no_mount_points;
+
+ path = state->uri->abspath;
+
+ /* find the longest matching factory for the uri first */
+ if (!(factory = gst_rtsp_mount_points_match (priv->mount_points,
+ path, matched)))
+ goto no_factory;
+
+ if (matched)
+ path_len = *matched;
+ else
+ path_len = strlen (path);
- if (!compare_uri (priv->uri, state->uri)) {
+ if (!paths_are_equal (priv->path, path, path_len)) {
/* remove any previously cached values before we try to construct a new
* media for uri */
- if (priv->uri)
- gst_rtsp_url_free (priv->uri);
- priv->uri = NULL;
+ if (priv->path)
+ g_free (priv->path);
+ priv->path = NULL;
if (priv->media) {
gst_rtsp_media_unprepare (priv->media);
g_object_unref (priv->media);
}
priv->media = NULL;
- if (!priv->mount_points)
- goto no_mount_points;
-
- /* find the factory for the uri first */
- if (!(factory = gst_rtsp_mount_points_match (priv->mount_points,
- state->uri->abspath, NULL)))
- goto no_factory;
-
/* check if we have access to the factory */
if ((auth = gst_rtsp_media_factory_get_auth (factory))) {
state->factory = factory;
if (!(media = gst_rtsp_media_factory_construct (factory, state->uri)))
goto no_media;
- g_object_unref (factory);
- factory = NULL;
-
/* prepare the media */
if (!(gst_rtsp_media_prepare (media)))
goto no_prepare;
/* now keep track of the uri and the media */
- priv->uri = gst_rtsp_url_copy (state->uri);
+ priv->path = g_strndup (path, path_len);
priv->media = media;
state->media = media;
} else {
- /* we have seen this uri before, used cached media */
+ /* we have seen this path before, used cached media */
media = priv->media;
state->media = media;
- GST_INFO ("reusing cached media %p", media);
+ GST_INFO ("reusing cached media %p for path %s", media, priv->path);
}
+ g_object_unref (factory);
+
if (media)
g_object_ref (media);
}
no_factory:
{
- GST_ERROR ("client %p: no factory for uri", client);
+ GST_ERROR ("client %p: no factory for uri %s", client, path);
send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
return NULL;
}
GST_ERROR ("client %p: can't prepare media", client);
send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, state);
g_object_unref (media);
+ g_object_unref (factory);
return NULL;
}
}
GstRTSPStatusCode code;
GstRTSPSession *session;
GstRTSPStreamTransport *trans;
- gchar *trans_str, *pos;
- guint streamid;
+ gchar *trans_str;
GstRTSPSessionMedia *sessmedia;
GstRTSPMedia *media;
GstRTSPStream *stream;
GstRTSPState rtspstate;
GstRTSPClientClass *klass;
- const gchar *path;
+ gchar *path, *control;
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
- * parse the stream we need to configure, look for the stream in the abspath
- * first and then in the query. */
- if (uri->abspath == NULL || !(pos = strstr (uri->abspath, "/stream="))) {
- if (uri->query == NULL || !(pos = strstr (uri->query, "/stream=")))
- goto bad_request;
- }
-
- /* we can mofify the parsed uri in place */
- *pos = '\0';
-
- pos += strlen ("/stream=");
- if (sscanf (pos, "%u", &streamid) != 1)
- goto bad_request;
+ path = uri->abspath;
/* parse the transport */
res =
if (res != GST_RTSP_OK)
goto no_transport;
- gst_rtsp_transport_new (&ct);
-
- /* our supported transports */
- supported = GST_RTSP_LOWER_TRANS_UDP |
- GST_RTSP_LOWER_TRANS_UDP_MCAST | GST_RTSP_LOWER_TRANS_TCP;
-
- /* parse and find a usable supported transport */
- if (!parse_transport (transport, supported, ct))
- goto unsupported_transports;
-
/* we create the session after parsing stuff so that we don't make
* a session for malformed requests */
if (priv->session_pool == NULL)
* return NULL if this is a new url to manage in this session. */
sessmedia = gst_rtsp_session_get_media (session, path, &matched);
} else {
+ /* we need a new media configuration in this session */
+ sessmedia = NULL;
+ }
+
+ /* we have no session media, find one and manage it */
+ if (sessmedia == NULL) {
+ /* get a handle to the configuration of the media in the session */
+ media = find_media (client, state, &matched);
+ } else {
+ if ((media = gst_rtsp_session_media_get_media (sessmedia)))
+ g_object_ref (media);
+ }
+ /* no media, not found then */
+ if (media == NULL)
+ goto media_not_found;
+
+ /* path is what matched. We can modify the parsed uri in place */
+ path[matched] = '\0';
+ /* control is remainder */
+ control = &path[matched + 1];
+
+ /* find the stream now using the control part */
+ stream = gst_rtsp_media_find_stream (media, control);
+ if (stream == NULL)
+ goto stream_not_found;
+
+ /* now we have a uri identifying a valid media and stream */
+ state->stream = stream;
+ state->media = media;
+
+ if (session == NULL) {
/* create a session if this fails we probably reached our session limit or
* something. */
if (!(session = gst_rtsp_session_pool_create (priv->session_pool)))
session);
state->session = session;
-
- /* we need a new media configuration in this session */
- sessmedia = NULL;
}
- /* we have no media, find one and manage it */
if (sessmedia == NULL) {
- /* 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, path, media);
- }
+ /* manage the media in our session now, if not done already */
+ sessmedia = gst_rtsp_session_manage_media (session, path, media);
+ /* if we stil have no media, error */
+ if (sessmedia == NULL)
+ goto sessmedia_unavailable;
+ } else {
+ g_object_unref (media);
}
- /* if we stil have no media, error */
- if (sessmedia == NULL)
- goto not_found;
-
state->sessmedia = sessmedia;
- state->media = media = gst_rtsp_session_media_get_media (sessmedia);
-
- /* now get the stream */
- stream = gst_rtsp_media_get_stream (media, streamid);
- if (stream == NULL)
- goto not_found;
-
- state->stream = stream;
/* set blocksize on this stream */
if (!handle_blocksize (media, stream, state->request))
goto invalid_blocksize;
+ gst_rtsp_transport_new (&ct);
+
+ /* our supported transports */
+ supported = GST_RTSP_LOWER_TRANS_UDP |
+ GST_RTSP_LOWER_TRANS_UDP_MCAST | GST_RTSP_LOWER_TRANS_TCP;
+
+ /* parse and find a usable supported transport */
+ if (!parse_transport (transport, supported, ct))
+ goto unsupported_transports;
+
/* update the client transport */
klass = GST_RTSP_CLIENT_GET_CLASS (client);
if (!klass->configure_client_transport (client, state, ct))
send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, state);
return FALSE;
}
-bad_request:
+no_transport:
{
- GST_ERROR ("client %p: bad request", client);
- send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, state);
+ GST_ERROR ("client %p: no transport", client);
+ send_generic_response (client, GST_RTSP_STS_UNSUPPORTED_TRANSPORT, state);
return FALSE;
}
-not_found:
+no_pool:
{
- GST_ERROR ("client %p: media not found", client);
+ GST_ERROR ("client %p: no session pool configured", client);
+ send_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, state);
+ return FALSE;
+ }
+media_not_found:
+ {
+ GST_ERROR ("client %p: media '%s' not found", client, path);
send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
- g_object_unref (session);
- gst_rtsp_transport_free (ct);
return FALSE;
}
-invalid_blocksize:
+stream_not_found:
{
- GST_ERROR ("client %p: invalid blocksize", client);
- send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, state);
- g_object_unref (session);
- gst_rtsp_transport_free (ct);
+ GST_ERROR ("client %p: stream '%s' not found", client, control);
+ send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
+ g_object_unref (media);
return FALSE;
}
-unsupported_client_transport:
+service_unavailable:
{
- GST_ERROR ("client %p: unsupported client transport", client);
- send_generic_response (client, GST_RTSP_STS_UNSUPPORTED_TRANSPORT, state);
+ GST_ERROR ("client %p: can't create session", client);
+ send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, state);
+ g_object_unref (media);
+ return FALSE;
+ }
+sessmedia_unavailable:
+ {
+ GST_ERROR ("client %p: can't create session media", client);
+ send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, state);
+ g_object_unref (media);
g_object_unref (session);
- gst_rtsp_transport_free (ct);
return FALSE;
}
-no_transport:
+invalid_blocksize:
{
- GST_ERROR ("client %p: no transport", client);
- send_generic_response (client, GST_RTSP_STS_UNSUPPORTED_TRANSPORT, state);
+ GST_ERROR ("client %p: invalid blocksize", client);
+ send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, state);
+ g_object_unref (session);
return FALSE;
}
unsupported_transports:
GST_ERROR ("client %p: unsupported transports", client);
send_generic_response (client, GST_RTSP_STS_UNSUPPORTED_TRANSPORT, state);
gst_rtsp_transport_free (ct);
+ g_object_unref (session);
return FALSE;
}
-no_pool:
- {
- GST_ERROR ("client %p: no session pool configured", client);
- send_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, state);
- gst_rtsp_transport_free (ct);
- return FALSE;
- }
-service_unavailable:
+unsupported_client_transport:
{
- GST_ERROR ("client %p: can't create session", client);
- send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, state);
+ GST_ERROR ("client %p: unsupported client transport", client);
+ send_generic_response (client, GST_RTSP_STS_UNSUPPORTED_TRANSPORT, state);
gst_rtsp_transport_free (ct);
+ g_object_unref (session);
return FALSE;
}
}
}
/* find the media object for the uri */
- if (!(media = find_media (client, state)))
+ if (!(media = find_media (client, state, NULL)))
goto no_media;
/* create an SDP for the media object on this client */