mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-29 13:11:06 +00:00
rtspconnection: support redirect when using tunnel
- Support HTTP redirect codes (301,302,307,308) on response to GET. "Location" field is extracted and used for following GET and POST. - Notify caller a redirect took place using return value - log source and destination url on redirect Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5222>
This commit is contained in:
parent
f1ad885c9b
commit
13c5406747
3 changed files with 187 additions and 41 deletions
|
@ -2997,6 +2997,9 @@ UTC times will be converted to nanoseconds since 1900.</doc>
|
|||
<member name="ok" value="0" c:identifier="GST_RTSP_OK" glib:nick="ok">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/rtsp/gstrtspdefs.h">no error</doc>
|
||||
</member>
|
||||
<member name="ok_redirect" value="1" c:identifier="GST_RTSP_OK_REDIRECT" version="1.24" glib:nick="ok-redirect">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/rtsp/gstrtspdefs.h">RTSP request is successful, but was redirected.</doc>
|
||||
</member>
|
||||
<member name="error" value="-1" c:identifier="GST_RTSP_ERROR" glib:nick="error">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/rtsp/gstrtspdefs.h">some unspecified error occurred</doc>
|
||||
</member>
|
||||
|
@ -3094,6 +3097,12 @@ UTC times will be converted to nanoseconds since 1900.</doc>
|
|||
</member>
|
||||
<member name="use_proxy" value="305" c:identifier="GST_RTSP_STS_USE_PROXY" glib:nick="use-proxy">
|
||||
</member>
|
||||
<member name="redirect_temporarily" value="307" c:identifier="GST_RTSP_STS_REDIRECT_TEMPORARILY" version="1.24" glib:nick="redirect-temporarily">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/rtsp/gstrtspdefs.h">RTSP request is temporarily redirected</doc>
|
||||
</member>
|
||||
<member name="redirect_permanently" value="308" c:identifier="GST_RTSP_STS_REDIRECT_PERMANENTLY" version="1.24" glib:nick="redirect-permanently">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/rtsp/gstrtspdefs.h">RTSP request is permanently redirected</doc>
|
||||
</member>
|
||||
<member name="bad_request" value="400" c:identifier="GST_RTSP_STS_BAD_REQUEST" glib:nick="bad-request">
|
||||
</member>
|
||||
<member name="unauthorized" value="401" c:identifier="GST_RTSP_STS_UNAUTHORIZED" glib:nick="unauthorized">
|
||||
|
|
|
@ -362,6 +362,26 @@ socket_client_event (GSocketClient * client, GSocketClientEvent event,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
stream0_reset (GstRTSPConnection * conn)
|
||||
{
|
||||
if (conn->stream0) {
|
||||
g_object_unref (conn->stream0);
|
||||
conn->stream0 = NULL;
|
||||
conn->socket0 = NULL;
|
||||
}
|
||||
conn->input_stream = NULL;
|
||||
conn->output_stream = NULL;
|
||||
g_free (conn->remote_ip);
|
||||
|
||||
conn->remote_ip = NULL;
|
||||
conn->read_socket = NULL;
|
||||
conn->write_socket = NULL;
|
||||
conn->read_socket_used = FALSE;
|
||||
conn->write_socket_used = FALSE;
|
||||
conn->control_stream = NULL;
|
||||
}
|
||||
|
||||
/* transfer full */
|
||||
static GCancellable *
|
||||
get_cancellable (GstRTSPConnection * conn)
|
||||
|
@ -892,7 +912,7 @@ add_extra_headers (GstRTSPMessage * msg, GArray * headers)
|
|||
}
|
||||
|
||||
static GstRTSPResult
|
||||
setup_tunneling (GstRTSPConnection * conn, gint64 timeout, gchar * uri,
|
||||
setup_tunneling (GstRTSPConnection * conn, gint64 timeout, gchar ** req_uri,
|
||||
GstRTSPMessage * response)
|
||||
{
|
||||
gint i;
|
||||
|
@ -909,6 +929,10 @@ setup_tunneling (GstRTSPConnection * conn, gint64 timeout, gchar * uri,
|
|||
gchar *request_uri = NULL;
|
||||
gchar *host = NULL;
|
||||
GCancellable *cancellable;
|
||||
gchar *uri;
|
||||
|
||||
g_return_val_if_fail (req_uri != NULL, GST_RTSP_EINVAL);
|
||||
uri = *req_uri;
|
||||
|
||||
url = conn->url;
|
||||
|
||||
|
@ -952,10 +976,35 @@ setup_tunneling (GstRTSPConnection * conn, gint64 timeout, gchar * uri,
|
|||
read_failed);
|
||||
conn->manual_http = old_http;
|
||||
|
||||
if (response->type != GST_RTSP_MESSAGE_HTTP_RESPONSE ||
|
||||
response->type_data.response.code != GST_RTSP_STS_OK)
|
||||
if (response->type != GST_RTSP_MESSAGE_HTTP_RESPONSE)
|
||||
goto wrong_result;
|
||||
|
||||
switch (response->type_data.response.code) {
|
||||
case GST_RTSP_STS_OK:
|
||||
break;
|
||||
case GST_RTSP_STS_MOVED_PERMANENTLY:
|
||||
case GST_RTSP_STS_MOVE_TEMPORARILY:
|
||||
case GST_RTSP_STS_REDIRECT_TEMPORARILY:
|
||||
case GST_RTSP_STS_REDIRECT_PERMANENTLY:
|
||||
{
|
||||
gchar *location_val = NULL;
|
||||
gst_rtsp_message_get_header (response, GST_RTSP_HDR_LOCATION,
|
||||
&location_val, 0);
|
||||
|
||||
if (location_val != NULL) {
|
||||
GST_TRACE ("redirect (%d) to %s",
|
||||
response->type_data.response.code, location_val);
|
||||
g_free (uri);
|
||||
uri = g_strdup (location_val);
|
||||
*req_uri = uri;
|
||||
res = GST_RTSP_OK_REDIRECT;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
default:
|
||||
goto wrong_result;
|
||||
}
|
||||
|
||||
if (!conn->ignore_x_server_reply &&
|
||||
gst_rtsp_message_get_header (response, GST_RTSP_HDR_X_SERVER_IP_ADDRESS,
|
||||
&value, 0) == GST_RTSP_OK) {
|
||||
|
@ -1102,15 +1151,17 @@ GstRTSPResult
|
|||
gst_rtsp_connection_connect_with_response_usec (GstRTSPConnection * conn,
|
||||
gint64 timeout, GstRTSPMessage * response)
|
||||
{
|
||||
GstRTSPResult res;
|
||||
GstRTSPResult res = GST_RTSP_OK;
|
||||
GSocketConnection *connection;
|
||||
GSocket *socket;
|
||||
GError *error = NULL;
|
||||
gchar *connection_uri, *request_uri, *remote_ip;
|
||||
gchar *connection_uri, *request_uri, *remote_ip, *query = NULL, *path = NULL;
|
||||
GstClockTime to;
|
||||
guint16 url_port;
|
||||
GstRTSPUrl *url;
|
||||
GCancellable *cancellable;
|
||||
guint redirect_cnt = 0;
|
||||
GstUri *uri = NULL;
|
||||
|
||||
g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL);
|
||||
g_return_val_if_fail (conn->url != NULL, GST_RTSP_EINVAL);
|
||||
|
@ -1130,54 +1181,110 @@ gst_rtsp_connection_connect_with_response_usec (GstRTSPConnection * conn,
|
|||
connection_uri = gst_rtsp_url_get_request_uri (url);
|
||||
}
|
||||
|
||||
cancellable = get_cancellable (conn);
|
||||
while (res == GST_RTSP_OK) {
|
||||
cancellable = get_cancellable (conn);
|
||||
|
||||
if (conn->proxy_host) {
|
||||
connection = g_socket_client_connect_to_host (conn->client,
|
||||
conn->proxy_host, conn->proxy_port, cancellable, &error);
|
||||
request_uri = g_strdup (connection_uri);
|
||||
} else {
|
||||
connection = g_socket_client_connect_to_uri (conn->client,
|
||||
connection_uri, url_port, cancellable, &error);
|
||||
if (conn->proxy_host) {
|
||||
connection = g_socket_client_connect_to_host (conn->client,
|
||||
conn->proxy_host, conn->proxy_port, cancellable, &error);
|
||||
request_uri = g_strdup (connection_uri);
|
||||
} else {
|
||||
if (uri != NULL) {
|
||||
url_port = gst_uri_get_port (uri);
|
||||
}
|
||||
connection = g_socket_client_connect_to_uri (conn->client,
|
||||
connection_uri, url_port, cancellable, &error);
|
||||
|
||||
/* use the relative component of the uri for non-proxy connections */
|
||||
request_uri = g_strdup_printf ("%s%s%s", url->abspath,
|
||||
url->query ? "?" : "", url->query ? url->query : "");
|
||||
}
|
||||
if (uri == NULL) {
|
||||
/* Use the relative component of the uri for non-proxy connections.
|
||||
* Note: request_uri is not a complete URI, it only contain path +
|
||||
* query.*/
|
||||
request_uri = g_strdup_printf ("%s%s%s", url->abspath,
|
||||
url->query ? "?" : "", url->query ? url->query : "");
|
||||
} else {
|
||||
path = gst_uri_get_path (uri);
|
||||
query = gst_uri_get_query_string (uri);
|
||||
request_uri = g_strdup_printf ("%s%s%s",
|
||||
path, query ? "?" : "", query ? query : "");
|
||||
}
|
||||
g_free (path);
|
||||
g_free (query);
|
||||
}
|
||||
|
||||
g_clear_object (&cancellable);
|
||||
g_clear_object (&cancellable);
|
||||
|
||||
if (connection == NULL)
|
||||
goto connect_failed;
|
||||
if (connection == NULL)
|
||||
goto connect_failed;
|
||||
|
||||
/* get remote address */
|
||||
socket = g_socket_connection_get_socket (connection);
|
||||
/* get remote address */
|
||||
socket = g_socket_connection_get_socket (connection);
|
||||
|
||||
if (!collect_addresses (socket, &remote_ip, NULL, TRUE, &error))
|
||||
goto remote_address_failed;
|
||||
if (!collect_addresses (socket, &remote_ip, NULL, TRUE, &error))
|
||||
goto remote_address_failed;
|
||||
|
||||
g_free (conn->remote_ip);
|
||||
conn->remote_ip = remote_ip;
|
||||
conn->stream0 = G_IO_STREAM (connection);
|
||||
conn->socket0 = socket;
|
||||
/* this is our read socket */
|
||||
conn->read_socket = conn->socket0;
|
||||
conn->write_socket = conn->socket0;
|
||||
conn->read_socket_used = FALSE;
|
||||
conn->write_socket_used = FALSE;
|
||||
conn->input_stream = g_io_stream_get_input_stream (conn->stream0);
|
||||
conn->output_stream = g_io_stream_get_output_stream (conn->stream0);
|
||||
conn->control_stream = NULL;
|
||||
g_free (conn->remote_ip);
|
||||
conn->remote_ip = remote_ip;
|
||||
conn->stream0 = G_IO_STREAM (connection);
|
||||
conn->socket0 = socket;
|
||||
/* this is our read socket */
|
||||
conn->read_socket = conn->socket0;
|
||||
conn->write_socket = conn->socket0;
|
||||
conn->read_socket_used = FALSE;
|
||||
conn->write_socket_used = FALSE;
|
||||
conn->input_stream = g_io_stream_get_input_stream (conn->stream0);
|
||||
conn->output_stream = g_io_stream_get_output_stream (conn->stream0);
|
||||
conn->control_stream = NULL;
|
||||
|
||||
if (conn->tunneled) {
|
||||
res = setup_tunneling (conn, timeout, request_uri, response);
|
||||
if (res != GST_RTSP_OK)
|
||||
goto tunneling_failed;
|
||||
if (conn->tunneled) {
|
||||
res = setup_tunneling (conn, timeout, &request_uri, response);
|
||||
if (res != GST_RTSP_OK) {
|
||||
if (res == GST_RTSP_OK_REDIRECT) {
|
||||
if (conn->proxy_host) {
|
||||
GST_TRACE ("redirect behind proxy is not supported");
|
||||
res = GST_RTSP_ERROR;
|
||||
goto tunneling_failed;
|
||||
}
|
||||
|
||||
GST_LOG ("redirect from %s to %s.", connection_uri, request_uri);
|
||||
|
||||
stream0_reset (conn);
|
||||
connection_uri = request_uri;
|
||||
gst_uri_unref (uri);
|
||||
|
||||
uri = gst_uri_from_string (connection_uri);
|
||||
if (uri == NULL) {
|
||||
GST_TRACE ("failed to parse redirect uri");
|
||||
res = GST_RTSP_ERROR;
|
||||
goto tunneling_failed;
|
||||
}
|
||||
|
||||
conn->url->abspath = gst_uri_get_path (uri);
|
||||
conn->url->host = g_strdup (gst_uri_get_host (uri));
|
||||
conn->url->port = gst_uri_get_port (uri);
|
||||
conn->url->query = gst_uri_get_query_string (uri);
|
||||
res = GST_RTSP_OK;
|
||||
|
||||
/* at most allow 5 redirect */
|
||||
if (redirect_cnt++ > 4) {
|
||||
GST_TRACE ("redirect max reached");
|
||||
res = GST_RTSP_ERROR;
|
||||
goto tunneling_failed;
|
||||
}
|
||||
} else {
|
||||
goto tunneling_failed;
|
||||
}
|
||||
} else {
|
||||
/* Caller must be informed */
|
||||
res = GST_RTSP_OK_REDIRECT;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_free (connection_uri);
|
||||
g_free (request_uri);
|
||||
|
||||
return GST_RTSP_OK;
|
||||
return res;
|
||||
|
||||
/* ERRORS */
|
||||
connect_failed:
|
||||
|
|
|
@ -65,6 +65,7 @@ G_STMT_START { \
|
|||
/**
|
||||
* GstRTSPResult:
|
||||
* @GST_RTSP_OK: no error
|
||||
* @GST_RTSP_OK_REDIRECT: no error, but redirected
|
||||
* @GST_RTSP_ERROR: some unspecified error occurred
|
||||
* @GST_RTSP_EINVAL: invalid arguments were provided to a function
|
||||
* @GST_RTSP_EINTR: an operation was canceled
|
||||
|
@ -87,6 +88,16 @@ G_STMT_START { \
|
|||
*/
|
||||
typedef enum {
|
||||
GST_RTSP_OK = 0,
|
||||
|
||||
/**
|
||||
* GST_RTSP_OK_REDIRECT:
|
||||
*
|
||||
* RTSP request is successful, but was redirected.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
GST_RTSP_OK_REDIRECT = 1,
|
||||
|
||||
/* errors */
|
||||
GST_RTSP_ERROR = -1,
|
||||
GST_RTSP_EINVAL = -2,
|
||||
|
@ -365,6 +376,25 @@ typedef enum {
|
|||
GST_RTSP_STS_SEE_OTHER = 303,
|
||||
GST_RTSP_STS_NOT_MODIFIED = 304,
|
||||
GST_RTSP_STS_USE_PROXY = 305,
|
||||
|
||||
/**
|
||||
* GST_RTSP_STS_REDIRECT_TEMPORARILY:
|
||||
*
|
||||
* RTSP request is temporarily redirected
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
GST_RTSP_STS_REDIRECT_TEMPORARILY = 307,
|
||||
|
||||
/**
|
||||
* GST_RTSP_STS_REDIRECT_PERMANENTLY:
|
||||
*
|
||||
* RTSP request is permanently redirected
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
GST_RTSP_STS_REDIRECT_PERMANENTLY = 308,
|
||||
|
||||
GST_RTSP_STS_BAD_REQUEST = 400,
|
||||
GST_RTSP_STS_UNAUTHORIZED = 401,
|
||||
GST_RTSP_STS_PAYMENT_REQUIRED = 402,
|
||||
|
|
Loading…
Reference in a new issue