From 8c37ba4892e3e62f0481178876be92705b68fdab Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Blin?=
 <sebastien.blin@savoirfairelinux.com>
Date: Fri, 16 Mar 2018 09:41:17 -0400
Subject: [PATCH] datatransfer: do not flood turn with zero-filled buffers when
 receiving

+ Handle the EBUSY state in turn_transport.
+ Resize the buffer to empty if no orders to send when reading from
the ftp server.

Change-Id: I95d3c11917da250058dd8dfb4dbdea0324c47442
Reviewed-by: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
---
 src/ftp_server.cpp     |  3 +++
 src/turn_transport.cpp | 12 +++++++++---
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/src/ftp_server.cpp b/src/ftp_server.cpp
index b1db522894..b74fd8edf7 100644
--- a/src/ftp_server.cpp
+++ b/src/ftp_server.cpp
@@ -105,6 +105,9 @@ FtpServer::read(std::vector<uint8_t>& buffer) const
         buffer.resize(3);
         buffer[0] = 'G'; buffer[1] = 'O'; buffer[2] = '\n';
         RING_DBG() << "[FTP] sending GO order";
+    } else {
+        // Nothing to send. Avoid to have an useless buffer filled with 0.
+        buffer.resize(0);
     }
     return true;
 }
diff --git a/src/turn_transport.cpp b/src/turn_transport.cpp
index fd4c0ea96a..e13a0f7fca 100644
--- a/src/turn_transport.cpp
+++ b/src/turn_transport.cpp
@@ -421,10 +421,10 @@ TurnTransport::sendto(const IpAddr& peer, const char* const buffer, std::size_t
     auto status = pj_turn_sock_sendto(pimpl_->relay,
                                       reinterpret_cast<const pj_uint8_t*>(buffer), length,
                                       peer.pjPtr(), peer.getLength());
-    if (status != PJ_SUCCESS && status != PJ_EPENDING)
+    if (status != PJ_SUCCESS && status != PJ_EPENDING && status != PJ_EBUSY)
         throw sip_utils::PjsipFailure(PJ_STATUS_TO_OS(status));
 
-    return status == PJ_SUCCESS;
+    return status != PJ_EBUSY;
 }
 
 bool
@@ -489,7 +489,13 @@ std::size_t
 ConnectedTurnTransport::write(const ValueType* buf, std::size_t size, std::error_code& ec)
 {
     try {
-        turn_.sendto(peer_, reinterpret_cast<const char*>(buf), size);
+        auto success = turn_.sendto(peer_, reinterpret_cast<const char*>(buf), size);
+        if (!success) {
+            // if !success, pj_turn_sock_sendto returned EBUSY
+            // So, we should retry to send this later
+            ec.assign(EAGAIN, std::generic_category());
+            return 0;
+        }
     } catch (const sip_utils::PjsipFailure& ex) {
         ec = ex.code();
         return 0;
-- 
GitLab