From 549fd8fcb68d8dbb7ad8d15e99fbffcb2dfbacaa Mon Sep 17 00:00:00 2001
From: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
Date: Fri, 4 Sep 2015 15:15:32 -0400
Subject: [PATCH] socket_pair: fix system socket

This patch tries to fix read errors on system socket when
no data available.

Issue: #80094
Change-Id: I7306bb32402983a939e9eca6cc4dbcc4d854685c
---
 src/media/socket_pair.cpp | 63 +++++++++++++++++++++++----------------
 1 file changed, 38 insertions(+), 25 deletions(-)

diff --git a/src/media/socket_pair.cpp b/src/media/socket_pair.cpp
index 90b34a8df5..9873a247ee 100644
--- a/src/media/socket_pair.cpp
+++ b/src/media/socket_pair.cpp
@@ -71,6 +71,8 @@ namespace ring {
 static constexpr int NET_POLL_TIMEOUT = 100; /* poll() timeout in ms */
 static constexpr int RTP_MAX_PACKET_LENGTH = 2048;
 
+enum class DataType : unsigned { RTP=1<<0, RTCP=1<<1 };
+
 class SRTPProtoContext {
 public:
     SRTPProtoContext(const char* out_suite, const char* out_key,
@@ -293,8 +295,8 @@ SocketPair::openSockets(const char* uri, int local_rtp_port)
         throw std::runtime_error("Socket creation failed");
     }
 
-    RING_WARN("SocketPair: local{%d,%d}, remote{%d,%d}",
-              local_rtp_port, local_rtcp_port, rtp_port, rtcp_port);
+    RING_WARN("SocketPair: local{%d,%d} / %s{%d,%d}",
+              local_rtp_port, local_rtcp_port, hostname, rtp_port, rtcp_port);
 }
 
 MediaIOHandle*
@@ -322,9 +324,17 @@ SocketPair::waitForData()
             struct pollfd p[2] = { {rtpHandle_, POLLIN, 0},
                                    {rtcpHandle_, POLLIN, 0} };
             ret = poll(p, 2, NET_POLL_TIMEOUT);
-        } while (ret < 0 and errno == EAGAIN);
+            if (ret > 0) {
+                ret = 0;
+                if (p[0].revents & POLLIN)
+                    ret |= static_cast<int>(DataType::RTP);
+                if (p[1].revents & POLLIN)
+                    ret |= static_cast<int>(DataType::RTCP);
+            }
+        } while (!ret or (ret < 0 and errno == EAGAIN));
 
         return ret;
+
     }
 
     // work with IceSocket
@@ -338,7 +348,7 @@ SocketPair::waitForData()
         return -1;
     }
 
-    return 0;
+    return static_cast<int>(DataType::RTP) | static_cast<int>(DataType::RTCP);
 }
 
 int
@@ -396,33 +406,36 @@ SocketPair::readRtcpData(void* buf, int buf_size)
 int
 SocketPair::readCallback(uint8_t* buf, int buf_size)
 {
-    while (1) {
-        auto ret = waitForData();
-        if (ret < 0)
-            return ret;
+    auto datatype = waitForData();
+    if (datatype < 0)
+        return datatype;
 
-        // Priority to RTCP as its less invasive in bandwidth
-        auto len = readRtcpData(buf, buf_size);
-        bool fromRTCP = true;
+    int len = 0;
+    bool fromRTCP = false;
 
-        // No RTCP... try RTP
-        if (len == 0) {
-            len = readRtpData(buf, buf_size);
-            fromRTCP = false;
-        }
-
-        if (len < 0)
-            return len;
+    // Priority to RTCP as its less invasive in bandwidth
+    if (datatype & static_cast<int>(DataType::RTCP)) {
+        len = readRtcpData(buf, buf_size);
+        fromRTCP = true;
+    }
 
-        // SRTP decrypt
-        if (not fromRTCP and srtpContext_ and srtpContext_->srtp_in.aes) {
-            auto err = ff_srtp_decrypt(&srtpContext_->srtp_in, buf, &len);
-            if (err < 0)
-                RING_WARN("decrypt error %d", err);
-        }
+    // No RTCP... try RTP
+    if (!len and (datatype & static_cast<int>(DataType::RTP))) {
+        len = readRtpData(buf, buf_size);
+        fromRTCP = false;
+    }
 
+    if (len <= 0)
         return len;
+
+    // SRTP decrypt
+    if (not fromRTCP and srtpContext_ and srtpContext_->srtp_in.aes) {
+        auto err = ff_srtp_decrypt(&srtpContext_->srtp_in, buf, &len);
+        if (err < 0)
+            RING_WARN("decrypt error %d", err);
     }
+
+    return len;
 }
 
 int
-- 
GitLab