mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-09-30 07:42:32 +00:00
rtsp-client: handle Require headers and respond with OPTION_NOT_SUPPORTED
Servers must handle Require headers and must report a failure if they don't handle any of the Required options, see RFC 2326, section 12.32: https://tools.ietf.org/html/rfc2326#page-54 https://bugzilla.gnome.org/show_bug.cgi?id=729426
This commit is contained in:
parent
4e29b60048
commit
efd079546a
1 changed files with 81 additions and 0 deletions
|
@ -502,6 +502,25 @@ send_generic_response (GstRTSPClient * client, GstRTSPStatusCode code,
|
||||||
send_message (client, ctx, ctx->response, FALSE);
|
send_message (client, ctx, ctx->response, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
send_option_not_supported_response (GstRTSPClient * client,
|
||||||
|
GstRTSPContext * ctx, const gchar * unsupported_options)
|
||||||
|
{
|
||||||
|
GstRTSPStatusCode code = GST_RTSP_STS_OPTION_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
gst_rtsp_message_init_response (ctx->response, code,
|
||||||
|
gst_rtsp_status_as_text (code), ctx->request);
|
||||||
|
|
||||||
|
if (unsupported_options != NULL) {
|
||||||
|
gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_UNSUPPORTED,
|
||||||
|
unsupported_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->session = NULL;
|
||||||
|
|
||||||
|
send_message (client, ctx, ctx->response, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
paths_are_equal (const gchar * path1, const gchar * path2, gint len2)
|
paths_are_equal (const gchar * path1, const gchar * path2, gint len2)
|
||||||
{
|
{
|
||||||
|
@ -2169,6 +2188,55 @@ client_session_finalized (GstRTSPClient * client, GstRTSPSession * session)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns TRUE if there are no Require headers, otherwise returns FALSE
|
||||||
|
* and also returns a newly-allocated string of (comma-separated) unsupported
|
||||||
|
* options in the unsupported_reqs variable .
|
||||||
|
*
|
||||||
|
* There may be multiple Require headers, but we must send one single
|
||||||
|
* Unsupported header with all the unsupported options as response. If
|
||||||
|
* an incoming Require header contained a comma-separated list of options
|
||||||
|
* GstRtspConnection will already have split that list up into multiple
|
||||||
|
* headers.
|
||||||
|
*
|
||||||
|
* TODO: allow the application to decide what features are supported
|
||||||
|
*/
|
||||||
|
static gboolean
|
||||||
|
check_request_requirements (GstRTSPMessage * msg, gchar ** unsupported_reqs)
|
||||||
|
{
|
||||||
|
GstRTSPResult res;
|
||||||
|
GPtrArray *arr = NULL;
|
||||||
|
gchar *reqs = NULL;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
do {
|
||||||
|
res = gst_rtsp_message_get_header (msg, GST_RTSP_HDR_REQUIRE, &reqs, i++);
|
||||||
|
|
||||||
|
if (res == GST_RTSP_ENOTIMPL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (arr == NULL)
|
||||||
|
arr = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
|
||||||
|
|
||||||
|
g_ptr_array_add (arr, g_strdup (reqs));
|
||||||
|
}
|
||||||
|
while (TRUE);
|
||||||
|
|
||||||
|
/* if we don't have any Require headers at all, all is fine */
|
||||||
|
if (i == 1)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* otherwise we've now processed at all the Require headers */
|
||||||
|
g_ptr_array_add (arr, NULL);
|
||||||
|
|
||||||
|
/* for now we don't commit to supporting anything, so will just report
|
||||||
|
* all of the required options as unsupported */
|
||||||
|
*unsupported_reqs = g_strjoinv (", ", (gchar **) arr->pdata);
|
||||||
|
|
||||||
|
g_ptr_array_unref (arr);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_request (GstRTSPClient * client, GstRTSPMessage * request)
|
handle_request (GstRTSPClient * client, GstRTSPMessage * request)
|
||||||
{
|
{
|
||||||
|
@ -2181,6 +2249,7 @@ handle_request (GstRTSPClient * client, GstRTSPMessage * request)
|
||||||
GstRTSPSession *session = NULL;
|
GstRTSPSession *session = NULL;
|
||||||
GstRTSPContext sctx = { NULL }, *ctx;
|
GstRTSPContext sctx = { NULL }, *ctx;
|
||||||
GstRTSPMessage response = { 0 };
|
GstRTSPMessage response = { 0 };
|
||||||
|
gchar *unsupported_reqs = NULL;
|
||||||
gchar *sessid;
|
gchar *sessid;
|
||||||
|
|
||||||
if (!(ctx = gst_rtsp_context_get_current ())) {
|
if (!(ctx = gst_rtsp_context_get_current ())) {
|
||||||
|
@ -2268,6 +2337,10 @@ handle_request (GstRTSPClient * client, GstRTSPMessage * request)
|
||||||
if (!gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_URL))
|
if (!gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_URL))
|
||||||
goto not_authorized;
|
goto not_authorized;
|
||||||
|
|
||||||
|
/* handle any 'Require' headers */
|
||||||
|
if (!check_request_requirements (ctx->request, &unsupported_reqs))
|
||||||
|
goto unsupported_requirement;
|
||||||
|
|
||||||
/* now see what is asked and dispatch to a dedicated handler */
|
/* now see what is asked and dispatch to a dedicated handler */
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case GST_RTSP_OPTIONS:
|
case GST_RTSP_OPTIONS:
|
||||||
|
@ -2344,6 +2417,14 @@ not_authorized:
|
||||||
/* error reply is already sent */
|
/* error reply is already sent */
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
unsupported_requirement:
|
||||||
|
{
|
||||||
|
GST_ERROR ("client %p: Required option is not supported (%s)", client,
|
||||||
|
unsupported_reqs);
|
||||||
|
send_option_not_supported_response (client, ctx, unsupported_reqs);
|
||||||
|
g_free (unsupported_reqs);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
not_implemented:
|
not_implemented:
|
||||||
{
|
{
|
||||||
GST_ERROR ("client %p: method %d not implemented", client, method);
|
GST_ERROR ("client %p: method %d not implemented", client, method);
|
||||||
|
|
Loading…
Reference in a new issue