rtspconnection: Consistently translate GIOError to GstRTSPResult
authorNirbheek Chauhan <nirbheek@centricular.com>
Mon, 15 Mar 2021 13:35:44 +0000 (19:05 +0530)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Tue, 16 Mar 2021 08:18:11 +0000 (08:18 +0000)
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>

gst-libs/gst/rtsp/gstrtspconnection.c

index 574b967..27a2dac 100644 (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;
   }
 }