rtspconnection: Consistently translate GIOError to GstRTSPResult

The users of this API need to be able to differentiate between EINTR
and ERROR. For example, in rtspsrc, gst_rtsp_conninfo_connect()
behaves differently when gst_rtsp_connection_connect_with_response_usec()
returns an ERROR or EINTR. The former is an element error while the
latter is simple a GST_ERROR since it was a user cancellation of the
connection attempt.

Due to this, rtspsrc was incorrectly emitting element errors while
going to NULL, which would or would not reach the application in
a racy manner.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/1069>
This commit is contained in:
Nirbheek Chauhan 2021-03-15 19:05:44 +05:30 committed by GStreamer Marge Bot
parent f4a1428a69
commit 9b01036664

View file

@ -256,6 +256,28 @@ build_reset (GstRTSPBuilder * builder)
memset (builder, 0, sizeof (GstRTSPBuilder));
}
static GstRTSPResult
gst_rtsp_result_from_g_io_error (GError * error, GstRTSPResult default_res)
{
if (error == NULL)
return GST_RTSP_OK;
if (error->domain != G_IO_ERROR)
return default_res;
switch (error->code) {
case G_IO_ERROR_TIMED_OUT:
return GST_RTSP_ETIMEOUT;
case G_IO_ERROR_INVALID_ARGUMENT:
return GST_RTSP_EINVAL;
case G_IO_ERROR_CANCELLED:
case G_IO_ERROR_WOULD_BLOCK:
return GST_RTSP_EINTR;
default:
return default_res;
}
}
static gboolean
tls_accept_certificate (GTlsConnection * conn, GTlsCertificate * peer_cert,
GTlsCertificateFlags errors, GstRTSPConnection * rtspconn)
@ -470,8 +492,9 @@ gst_rtsp_connection_create_from_socket (GSocket * socket, const gchar * ip,
getnameinfo_failed:
{
GST_ERROR ("failed to get local address: %s", err->message);
res = gst_rtsp_result_from_g_io_error (err, GST_RTSP_ERROR);
g_clear_error (&err);
return GST_RTSP_ERROR;
return res;
}
newconn_failed:
{
@ -526,19 +549,21 @@ gst_rtsp_connection_accept (GSocket * socket, GstRTSPConnection ** conn,
accept_failed:
{
GST_DEBUG ("Accepting client failed: %s", err->message);
ret = gst_rtsp_result_from_g_io_error (err, GST_RTSP_ESYS);
g_clear_error (&err);
return GST_RTSP_ESYS;
return ret;
}
getnameinfo_failed:
{
GST_DEBUG ("getnameinfo failed: %s", err->message);
ret = gst_rtsp_result_from_g_io_error (err, GST_RTSP_ERROR);
g_clear_error (&err);
if (!g_socket_close (client_sock, &err)) {
GST_DEBUG ("Closing socket failed: %s", err->message);
g_clear_error (&err);
}
g_object_unref (client_sock);
return GST_RTSP_ERROR;
return ret;
}
}
@ -941,16 +966,17 @@ wrong_result:
connect_failed:
{
GST_ERROR ("failed to connect: %s", error->message);
res = GST_RTSP_ERROR;
res = gst_rtsp_result_from_g_io_error (error, GST_RTSP_ERROR);
g_clear_error (&error);
goto exit;
}
remote_address_failed:
{
GST_ERROR ("failed to resolve address: %s", error->message);
res = gst_rtsp_result_from_g_io_error (error, GST_RTSP_ERROR);
g_object_unref (connection);
g_clear_error (&error);
return GST_RTSP_ERROR;
return res;
}
}
@ -1050,19 +1076,21 @@ gst_rtsp_connection_connect_with_response_usec (GstRTSPConnection * conn,
connect_failed:
{
GST_ERROR ("failed to connect: %s", error->message);
res = gst_rtsp_result_from_g_io_error (error, GST_RTSP_ERROR);
g_clear_error (&error);
g_free (connection_uri);
g_free (request_uri);
return GST_RTSP_ERROR;
return res;
}
remote_address_failed:
{
GST_ERROR ("failed to connect: %s", error->message);
res = gst_rtsp_result_from_g_io_error (error, GST_RTSP_ERROR);
g_object_unref (connection);
g_clear_error (&error);
g_free (connection_uri);
g_free (request_uri);
return GST_RTSP_ERROR;
return res;
}
tunneling_failed:
{
@ -1211,6 +1239,7 @@ write_bytes (GOutputStream * stream, const guint8 * buffer, guint * idx,
{
guint left;
gssize r;
GstRTSPResult res;
GError *err = NULL;
if (G_UNLIKELY (*idx > size))
@ -1244,18 +1273,9 @@ error:
else
GST_DEBUG ("%s", err->message);
if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
g_clear_error (&err);
return GST_RTSP_EINTR;
} else if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
g_clear_error (&err);
return GST_RTSP_EINTR;
} else if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_TIMED_OUT)) {
g_clear_error (&err);
return GST_RTSP_ETIMEOUT;
}
res = gst_rtsp_result_from_g_io_error (err, GST_RTSP_ESYS);
g_clear_error (&err);
return GST_RTSP_ESYS;
return res;
}
}
@ -1267,6 +1287,7 @@ writev_bytes (GOutputStream * stream, GOutputVector * vectors, gint n_vectors,
{
gsize _bytes_written = 0;
gsize written;
GstRTSPResult ret;
GError *err = NULL;
GPollableReturn res = G_POLLABLE_RETURN_OK;
@ -1318,19 +1339,14 @@ error:
if (res == G_POLLABLE_RETURN_WOULD_BLOCK) {
g_assert (!err);
return GST_RTSP_EINTR;
} else if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
g_clear_error (&err);
return GST_RTSP_EINTR;
} else if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_TIMED_OUT)) {
g_clear_error (&err);
return GST_RTSP_ETIMEOUT;
} else if (G_UNLIKELY (written == 0)) {
g_clear_error (&err);
return GST_RTSP_EEOF;
}
ret = gst_rtsp_result_from_g_io_error (err, GST_RTSP_ESYS);
g_clear_error (&err);
return GST_RTSP_ESYS;
return ret;
}
}
#else
@ -1458,6 +1474,7 @@ read_bytes (GstRTSPConnection * conn, guint8 * buffer, guint * idx, guint size,
{
guint left;
gint r;
GstRTSPResult res;
GError *err = NULL;
if (G_UNLIKELY (*idx > size))
@ -1482,18 +1499,9 @@ error:
return GST_RTSP_EEOF;
GST_DEBUG ("%s", err->message);
if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
g_clear_error (&err);
return GST_RTSP_EINTR;
} else if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
g_clear_error (&err);
return GST_RTSP_EINTR;
} else if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_TIMED_OUT)) {
g_clear_error (&err);
return GST_RTSP_ETIMEOUT;
}
res = gst_rtsp_result_from_g_io_error (err, GST_RTSP_ESYS);
g_clear_error (&err);
return GST_RTSP_ESYS;
return res;
}
}