You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by sh...@apache.org on 2017/11/14 16:14:08 UTC

[trafficserver] branch master updated: Cancel closing if Http2SendDataFrameResult is NO_WINDOW

This is an automated email from the ASF dual-hosted git repository.

shinrich pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 9a93d32  Cancel closing if Http2SendDataFrameResult is NO_WINDOW
9a93d32 is described below

commit 9a93d32863364e01267b5aabd322a9740c695441
Author: Masaori Koshiba <ma...@apache.org>
AuthorDate: Mon Nov 13 16:50:34 2017 +0900

    Cancel closing if Http2SendDataFrameResult is NO_WINDOW
---
 proxy/http2/Http2ConnectionState.cc | 38 ++++++++++++++++++-------------------
 proxy/http2/Http2ConnectionState.h  | 14 +++++++-------
 proxy/http2/Http2Stream.cc          | 22 +++++++++++++--------
 3 files changed, 39 insertions(+), 35 deletions(-)

diff --git a/proxy/http2/Http2ConnectionState.cc b/proxy/http2/Http2ConnectionState.cc
index 0368fed..75c489b 100644
--- a/proxy/http2/Http2ConnectionState.cc
+++ b/proxy/http2/Http2ConnectionState.cc
@@ -1236,11 +1236,11 @@ Http2ConnectionState::send_data_frames_depends_on_priority()
   ink_release_assert(stream != nullptr);
   Http2StreamDebug(ua_session, stream->get_id(), "top node, point=%d", node->point);
 
-  size_t len                       = 0;
-  Http2SendADataFrameResult result = send_a_data_frame(stream, len);
+  size_t len                      = 0;
+  Http2SendDataFrameResult result = send_a_data_frame(stream, len);
 
   switch (result) {
-  case HTTP2_SEND_A_DATA_FRAME_NO_ERROR: {
+  case Http2SendDataFrameResult::NO_ERROR: {
     // No response body to send
     if (len == 0 && !stream->is_body_done()) {
       dependency_tree->deactivate(node, len);
@@ -1249,7 +1249,7 @@ Http2ConnectionState::send_data_frames_depends_on_priority()
     }
     break;
   }
-  case HTTP2_SEND_A_DATA_FRAME_DONE: {
+  case Http2SendDataFrameResult::DONE: {
     dependency_tree->deactivate(node, len);
     delete_stream(stream);
     break;
@@ -1264,7 +1264,7 @@ Http2ConnectionState::send_data_frames_depends_on_priority()
   return;
 }
 
-Http2SendADataFrameResult
+Http2SendDataFrameResult
 Http2ConnectionState::send_a_data_frame(Http2Stream *stream, size_t &payload_length)
 {
   const ssize_t window_size         = std::min(this->client_rwnd, stream->client_rwnd);
@@ -1286,7 +1286,7 @@ Http2ConnectionState::send_a_data_frame(Http2Stream *stream, size_t &payload_len
   if (read_available_size > 0) {
     // We only need to check for window size when there is a payload
     if (window_size <= 0) {
-      return HTTP2_SEND_A_DATA_FRAME_NO_WINDOW;
+      return Http2SendDataFrameResult::NO_WINDOW;
     }
     // Copy into the payload buffer. Seems like we should be able to skip this copy step
     payload_length = current_reader->read(payload_buffer, write_available_size);
@@ -1298,7 +1298,7 @@ Http2ConnectionState::send_a_data_frame(Http2Stream *stream, size_t &payload_len
   // If we return here, we never send the END_STREAM in the case of a early terminating OS.
   // OK if there is no body yet. Otherwise continue on to send a DATA frame and delete the stream
   if (!stream->is_body_done() && payload_length == 0) {
-    return HTTP2_SEND_A_DATA_FRAME_NO_PAYLOAD;
+    return Http2SendDataFrameResult::NO_PAYLOAD;
   }
 
   if (stream->is_body_done() && read_available_size <= write_available_size) {
@@ -1330,13 +1330,13 @@ Http2ConnectionState::send_a_data_frame(Http2Stream *stream, size_t &payload_len
     // Setting to the same state shouldn't be erroneous
     stream->change_state(data.header().type, data.header().flags);
 
-    return HTTP2_SEND_A_DATA_FRAME_DONE;
+    return Http2SendDataFrameResult::DONE;
   }
 
-  return HTTP2_SEND_A_DATA_FRAME_NO_ERROR;
+  return Http2SendDataFrameResult::NO_ERROR;
 }
 
-void
+Http2SendDataFrameResult
 Http2ConnectionState::send_data_frames(Http2Stream *stream)
 {
   // To follow RFC 7540 must not send more frames other than priority on
@@ -1345,27 +1345,25 @@ Http2ConnectionState::send_data_frames(Http2Stream *stream)
       stream->get_state() == Http2StreamState::HTTP2_STREAM_STATE_CLOSED) {
     Http2StreamDebug(this->ua_session, stream->get_id(), "Shutdown half closed local stream");
     this->delete_stream(stream);
-    return;
+    return Http2SendDataFrameResult::NO_ERROR;
   }
 
-  size_t len = 0;
-  while (true) {
-    Http2SendADataFrameResult result = send_a_data_frame(stream, len);
+  size_t len                      = 0;
+  Http2SendDataFrameResult result = Http2SendDataFrameResult::NO_ERROR;
+  while (result == Http2SendDataFrameResult::NO_ERROR) {
+    result = send_a_data_frame(stream, len);
 
-    if (result == HTTP2_SEND_A_DATA_FRAME_DONE) {
+    if (result == Http2SendDataFrameResult::DONE) {
       // Delete a stream immediately
       // TODO its should not be deleted for a several time to handling
       // RST_STREAM and WINDOW_UPDATE.
       // See 'closed' state written at [RFC 7540] 5.1.
       Http2StreamDebug(this->ua_session, stream->get_id(), "Shutdown stream");
       this->delete_stream(stream);
-      break;
-    } else if (result == HTTP2_SEND_A_DATA_FRAME_NO_ERROR) {
-      continue;
-    } else {
-      break;
     }
   }
+
+  return result;
 }
 
 void
diff --git a/proxy/http2/Http2ConnectionState.h b/proxy/http2/Http2ConnectionState.h
index a4ffd76..1a640b0 100644
--- a/proxy/http2/Http2ConnectionState.h
+++ b/proxy/http2/Http2ConnectionState.h
@@ -31,11 +31,11 @@
 
 class Http2ClientSession;
 
-enum Http2SendADataFrameResult {
-  HTTP2_SEND_A_DATA_FRAME_NO_ERROR   = 0,
-  HTTP2_SEND_A_DATA_FRAME_NO_WINDOW  = 1,
-  HTTP2_SEND_A_DATA_FRAME_NO_PAYLOAD = 2,
-  HTTP2_SEND_A_DATA_FRAME_DONE       = 3,
+enum class Http2SendDataFrameResult {
+  NO_ERROR   = 0,
+  NO_WINDOW  = 1,
+  NO_PAYLOAD = 2,
+  DONE       = 3,
 };
 
 enum Http2ShutdownState { NOT_INITIATED, INITIATED, IN_PROGRESS };
@@ -218,8 +218,8 @@ public:
   // HTTP/2 frame sender
   void schedule_stream(Http2Stream *stream);
   void send_data_frames_depends_on_priority();
-  void send_data_frames(Http2Stream *stream);
-  Http2SendADataFrameResult send_a_data_frame(Http2Stream *stream, size_t &payload_length);
+  Http2SendDataFrameResult send_data_frames(Http2Stream *stream);
+  Http2SendDataFrameResult send_a_data_frame(Http2Stream *stream, size_t &payload_length);
   void send_headers_frame(Http2Stream *stream);
   void send_push_promise_frame(Http2Stream *stream, URL &url, const MIMEField *accept_encoding);
   void send_rst_stream_frame(Http2StreamId id, Http2ErrorCode ec);
diff --git a/proxy/http2/Http2Stream.cc b/proxy/http2/Http2Stream.cc
index f1cdaa4..e42a3f1 100644
--- a/proxy/http2/Http2Stream.cc
+++ b/proxy/http2/Http2Stream.cc
@@ -315,26 +315,32 @@ void
 Http2Stream::do_io_close(int /* flags */)
 {
   SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
-  super::release(nullptr);
+
   if (!closed) {
-    Http2StreamDebug("do_io_close");
+    if (parent && this->is_client_state_writeable()) {
+      // Make sure any trailing end of stream frames are sent
+      // Wee will be removed at send_data_frames or closing connection phase
+      Http2SendDataFrameResult result = static_cast<Http2ClientSession *>(parent)->connection_state.send_data_frames(this);
+      if (result == Http2SendDataFrameResult::NO_WINDOW) {
+        Http2StreamDebug("cancel closing");
+        return;
+      } else {
+        Http2StreamDebug("continue closing");
+      }
+    }
 
     // When we get here, the SM has initiated the shutdown.  Either it received a WRITE_COMPLETE, or it is shutting down.  Any
     // remaining IO operations back to client should be abandoned.  The SM-side buffers backing these operations will be deleted
     // by the time this is called from transaction_done.
     closed = true;
 
-    if (parent && this->is_client_state_writeable()) {
-      // Make sure any trailing end of stream frames are sent
-      // Wee will be removed at send_data_frames or closing connection phase
-      static_cast<Http2ClientSession *>(parent)->connection_state.send_data_frames(this);
-    }
-
     clear_timers();
     clear_io_events();
 
     // Wait until transaction_done is called from HttpSM to signal that the TXN_CLOSE hook has been executed
   }
+
+  super::release(nullptr);
 }
 
 /*

-- 
To stop receiving notification emails like this one, please contact
['"commits@trafficserver.apache.org" <co...@trafficserver.apache.org>'].