From 7cdcd40de61863fed884bb65364b13063f1a2d97 Mon Sep 17 00:00:00 2001
From: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
Date: Sat, 4 Apr 2020 09:56:32 +0900
Subject: [PATCH] Don't return NGTCP2_ERR_STREAM_DATA_BLOCKED if max data is
 full

---
 examples/client.cc       | 23 +++++------------------
 examples/server.cc       | 21 ++++-----------------
 lib/ngtcp2_conn.c        | 14 ++++++++------
 tests/ngtcp2_conn_test.c |  2 +-
 4 files changed, 18 insertions(+), 42 deletions(-)

diff --git a/examples/client.cc b/examples/client.cc
index f5bbd1da..79347fed 100644
--- a/examples/client.cc
+++ b/examples/client.cc
@@ -1186,17 +1186,6 @@ int Client::write_streams() {
       switch (nwrite) {
       case NGTCP2_ERR_STREAM_DATA_BLOCKED:
       case NGTCP2_ERR_STREAM_SHUT_WR:
-        if (nwrite == NGTCP2_ERR_STREAM_DATA_BLOCKED &&
-            ngtcp2_conn_get_max_data_left(conn_) == 0) {
-          /* Call ngtcp2_conn_writev_stream to ensure that a complete
-             packet is written to the buffer. */
-          nwrite = ngtcp2_conn_writev_stream(
-              conn_, &path.path, sendbuf_.wpos(), max_pktlen_, nullptr,
-              NGTCP2_WRITE_STREAM_FLAG_NONE, /* stream_id = */ 0, /* fin = */ 0,
-              nullptr, 0, util::timestamp(loop_));
-          break;
-        }
-
         if (auto rv = nghttp3_conn_block_stream(httpconn_, stream_id);
             rv != 0) {
           std::cerr << "nghttp3_conn_block_stream: " << nghttp3_strerror(rv)
@@ -1220,13 +1209,11 @@ int Client::write_streams() {
         continue;
       }
 
-      if (nwrite < 0) {
-        std::cerr << "ngtcp2_conn_write_stream: " << ngtcp2_strerror(nwrite)
-                  << std::endl;
-        last_error_ = quic_err_transport(nwrite);
-        disconnect();
-        return -1;
-      }
+      std::cerr << "ngtcp2_conn_write_stream: " << ngtcp2_strerror(nwrite)
+                << std::endl;
+      last_error_ = quic_err_transport(nwrite);
+      disconnect();
+      return -1;
     }
 
     if (nwrite == 0) {
diff --git a/examples/server.cc b/examples/server.cc
index eadf5a54..785501c6 100644
--- a/examples/server.cc
+++ b/examples/server.cc
@@ -1723,17 +1723,6 @@ int Handler::write_streams() {
       switch (nwrite) {
       case NGTCP2_ERR_STREAM_DATA_BLOCKED:
       case NGTCP2_ERR_STREAM_SHUT_WR:
-        if (nwrite == NGTCP2_ERR_STREAM_DATA_BLOCKED &&
-            ngtcp2_conn_get_max_data_left(conn_) == 0) {
-          /* Call ngtcp2_conn_writev_stream to ensure that a complete
-             packet is written to the buffer. */
-          nwrite = ngtcp2_conn_writev_stream(
-              conn_, &path.path, bufpos, max_pktlen_, nullptr,
-              NGTCP2_WRITE_STREAM_FLAG_NONE, /* stream_id = */ -1,
-              /* fin = */ 0, nullptr, 0, util::timestamp(loop_));
-          break;
-        }
-
         if (auto rv = nghttp3_conn_block_stream(httpconn_, stream_id);
             rv != 0) {
           std::cerr << "nghttp3_conn_block_stream: " << nghttp3_strerror(rv)
@@ -1755,12 +1744,10 @@ int Handler::write_streams() {
         continue;
       }
 
-      if (nwrite < 0) {
-        std::cerr << "ngtcp2_conn_writev_stream: " << ngtcp2_strerror(nwrite)
-                  << std::endl;
-        last_error_ = quic_err_transport(nwrite);
-        return handle_error();
-      }
+      std::cerr << "ngtcp2_conn_writev_stream: " << ngtcp2_strerror(nwrite)
+                << std::endl;
+      last_error_ = quic_err_transport(nwrite);
+      return handle_error();
     }
 
     if (nwrite == 0) {
diff --git a/lib/ngtcp2_conn.c b/lib/ngtcp2_conn.c
index 72b1f57d..42bb4de8 100644
--- a/lib/ngtcp2_conn.c
+++ b/lib/ngtcp2_conn.c
@@ -2762,7 +2762,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, uint8_t *dest,
 
   if (pkt_empty) {
     assert(rv == 0 || NGTCP2_ERR_NOBUF == rv);
-    if (rv == 0 && stream_blocked) {
+    if (rv == 0 && stream_blocked && ngtcp2_conn_get_max_data_left(conn)) {
       return NGTCP2_ERR_STREAM_DATA_BLOCKED;
     }
 
@@ -2776,11 +2776,13 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, uint8_t *dest,
     conn->pkt.hd_logged = hd_logged;
     conn->flags |= NGTCP2_CONN_FLAG_PPE_PENDING;
 
-    if (stream_blocked) {
-      return NGTCP2_ERR_STREAM_DATA_BLOCKED;
-    }
-    if (send_stream) {
-      return NGTCP2_ERR_WRITE_STREAM_MORE;
+    if (ngtcp2_conn_get_max_data_left(conn)) {
+      if (stream_blocked) {
+        return NGTCP2_ERR_STREAM_DATA_BLOCKED;
+      }
+      if (send_stream) {
+        return NGTCP2_ERR_WRITE_STREAM_MORE;
+      }
     }
   }
 
diff --git a/tests/ngtcp2_conn_test.c b/tests/ngtcp2_conn_test.c
index 0f87f0c2..ca96b2f9 100644
--- a/tests/ngtcp2_conn_test.c
+++ b/tests/ngtcp2_conn_test.c
@@ -1028,7 +1028,7 @@ void test_ngtcp2_conn_tx_flow_control(void) {
                                      NGTCP2_WRITE_STREAM_FLAG_NONE, stream_id,
                                      0, null_data, 1024, 4);
 
-  CU_ASSERT(NGTCP2_ERR_STREAM_DATA_BLOCKED == spktlen);
+  CU_ASSERT(spktlen == 0);
   CU_ASSERT(-1 == nwrite);
 
   fr.type = NGTCP2_FRAME_MAX_DATA;
-- 
GitLab