From 59d7779b1a121b752c49afd92f342cdd15c7bd3b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Blin?=
 <sebastien.blin@savoirfairelinux.com>
Date: Thu, 5 Apr 2018 09:45:54 -0400
Subject: [PATCH] data transfer: do not lose good reads when no stream is
 attached

A buffer can arrive before the ATTACH_INPUT or ATTACH_OUTPUT, we
should store this buffer and inject it as soon as a stream is attached
or we might have a blocked data transfer.

Change-Id: I110f7edc3d3e93fc4a9349c9e8a6d6aed699984b
---
 src/peer_connection.cpp | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp
index 6c16c25b3b..87396fc028 100644
--- a/src/peer_connection.cpp
+++ b/src/peer_connection.cpp
@@ -507,6 +507,7 @@ private:
     std::vector<std::shared_ptr<Stream>> inputs_;
     std::vector<std::shared_ptr<Stream>> outputs_;
     std::future<void> eventLoopFut_;
+    std::vector<uint8_t> bufferPool_; // will store non rattached buffers
 
     void eventLoop();
 
@@ -548,9 +549,14 @@ PeerConnection::PeerConnectionImpl::eventLoop()
                     std::error_code ec;
                     if (endpoint_->waitForData(100, ec) > 0) {
                         std::vector<uint8_t> buf(IO_BUFFER_SIZE);
-                        endpoint_->read(buf, ec); ///< \todo what to do with data from a good read?
+                        RING_DBG("A good buffer arrived before any input or output attachment");
+                        auto size = endpoint_->read(buf, ec);
                         if (ec)
                             throw std::system_error(ec);
+                        // If it's a good read, we should store the buffer somewhere
+                        // and give it to the next input or output.
+                        if (size < IO_BUFFER_SIZE)
+                            bufferPool_.insert(bufferPool_.end(), buf.begin(), buf.begin() + size);
                     }
                     break;
                 }
@@ -603,7 +609,10 @@ PeerConnection::PeerConnectionImpl::eventLoop()
                     return false;
                 }
 
-                if (endpoint_->waitForData(0, ec) > 0) {
+                if (!bufferPool_.empty()) {
+                    stream->write(bufferPool_);
+                    bufferPool_.clear();
+                } else if (endpoint_->waitForData(0, ec) > 0) {
                     buf.resize(IO_BUFFER_SIZE);
                     endpoint_->read(buf, ec);
                     if (ec)
@@ -629,7 +638,10 @@ PeerConnection::PeerConnectionImpl::eventLoop()
                 if (not eof)
                     return false;
 
-                if (endpoint_->waitForData(0, ec) > 0) {
+                if (!bufferPool_.empty()) {
+                    stream->write(bufferPool_);
+                    bufferPool_.clear();
+                } else if (endpoint_->waitForData(0, ec) > 0) {
                     buf.resize(IO_BUFFER_SIZE);
                     endpoint_->read(buf, ec);
                     if (ec)
-- 
GitLab