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

zwoop pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/9.0.x by this push:
     new 2baa388  Dechunk chunked contents on HttpTunnel if client protocol is 
HTTP/2 or HTTP/3
2baa388 is described below

commit 2baa388c3e3cb3ff71c468c8b0b4c68d8a0320fe
Author: Masaori Koshiba <[email protected]>
AuthorDate: Mon Sep 2 14:31:56 2019 +0900

    Dechunk chunked contents on HttpTunnel if client protocol is HTTP/2 or 
HTTP/3
    
    (cherry picked from commit 3ac74b5157cf6705b94d5eeb910953e25a6cdfc0)
---
 proxy/http/HttpTransact.cc | 15 ++++----
 proxy/http2/Http2Stream.cc | 93 +++-------------------------------------------
 proxy/http2/Http2Stream.h  | 18 +--------
 3 files changed, 15 insertions(+), 111 deletions(-)

diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc
index 0664a45..918a4b0 100644
--- a/proxy/http/HttpTransact.cc
+++ b/proxy/http/HttpTransact.cc
@@ -6730,11 +6730,10 @@ HttpTransact::handle_response_keep_alive_headers(State 
*s, HTTPVersion ver, HTTP
     // to the client to keep the connection alive.
     // Insert a Transfer-Encoding header in the response if necessary.
 
-    // check that the client is HTTP 1.1 and the conf allows chunking or the 
client
-    // protocol unchunks before returning to the user agent (i.e. is http/2)
-    if (s->client_info.http_version == HTTPVersion(1, 1) &&
-        (s->txn_conf->chunking_enabled == 1 ||
-         (s->state_machine->plugin_tag && 
(!strncmp(s->state_machine->plugin_tag, "http/2", 6)))) &&
+    // check that the client protocol is HTTP/1.1 and the conf allows chunking 
or
+    // the client protocol doesn't support chunked transfer coding (i.e. 
HTTP/1.0, HTTP/2, and HTTP/3)
+    if (s->state_machine->ua_txn && 
s->state_machine->ua_txn->is_chunked_encoding_supported() &&
+        s->client_info.http_version == HTTPVersion(1, 1) && 
s->txn_conf->chunking_enabled == 1 &&
         // if we're not sending a body, don't set a chunked header regardless 
of server response
         !is_response_body_precluded(s->hdr_info.client_response.status_get(), 
s->method) &&
         // we do not need chunked encoding for internal error messages
@@ -6767,10 +6766,12 @@ HttpTransact::handle_response_keep_alive_headers(State 
*s, HTTPVersion ver, HTTP
 
     // Close the connection if client_info is not keep-alive.
     // Otherwise, if we cannot trust the content length, we will close the 
connection
-    // unless we are going to use chunked encoding or the client issued
-    // a PUSH request
+    // unless we are going to use chunked encoding on HTTP/1.1 or the client 
issued a PUSH request
     if (s->client_info.keep_alive != HTTP_KEEPALIVE) {
       ka_action = KA_DISABLED;
+    } else if (s->state_machine->client_protocol && 
(IP_PROTO_TAG_HTTP_3.compare(s->state_machine->client_protocol) == 0 ||
+                                                     
strncmp(s->state_machine->client_protocol, "http/2", 6) == 0)) {
+      ka_action = KA_CONNECTION;
     } else if (s->hdr_info.trust_response_cl == false &&
                !(s->client_info.receive_chunked_response == true ||
                  (s->method == HTTP_WKSIDX_PUSH && s->client_info.keep_alive 
== HTTP_KEEPALIVE))) {
diff --git a/proxy/http2/Http2Stream.cc b/proxy/http2/Http2Stream.cc
index fad170c..8d2d5c6 100644
--- a/proxy/http2/Http2Stream.cc
+++ b/proxy/http2/Http2Stream.cc
@@ -575,7 +575,7 @@ void
 Http2Stream::update_write_request(IOBufferReader *buf_reader, int64_t 
write_len, bool call_update)
 {
   if (!this->is_client_state_writeable() || closed || _proxy_ssn == nullptr || 
write_vio.mutex == nullptr ||
-      (buf_reader == nullptr && write_len == 0)) {
+      (buf_reader == nullptr && write_len == 0) || this->response_reader == 
nullptr) {
     return;
   }
 
@@ -589,22 +589,7 @@ Http2Stream::update_write_request(IOBufferReader 
*buf_reader, int64_t write_len,
 
   SCOPED_MUTEX_LOCK(lock, write_vio.mutex, this_ethread());
 
-  // if response is chunked, limit the dechunked_buffer size.
-  bool is_done = false;
-  if (this->chunked) {
-    if (chunked_handler.dechunked_buffer && 
chunked_handler.dechunked_buffer->max_read_avail() > HTTP2_MAX_BUFFER_USAGE) {
-      if (buffer_full_write_event == nullptr) {
-        buffer_full_write_event = _thread->schedule_imm(this, 
VC_EVENT_WRITE_READY);
-      }
-    } else {
-      this->response_process_data(is_done);
-    }
-  }
-
-  if (this->response_get_data_reader() == nullptr) {
-    return;
-  }
-  int64_t bytes_avail = this->response_get_data_reader()->read_avail();
+  int64_t bytes_avail = this->response_reader->read_avail();
   if (write_vio.nbytes > 0 && write_vio.ntodo() > 0) {
     int64_t num_to_write = write_vio.ntodo();
     if (num_to_write > write_len) {
@@ -619,7 +604,7 @@ Http2Stream::update_write_request(IOBufferReader 
*buf_reader, int64_t write_len,
                    ", reader.read_avail=%" PRId64,
                    write_vio.nbytes, write_vio.ndone, 
write_vio.get_writer()->write_avail(), bytes_avail);
 
-  if (bytes_avail <= 0 && !is_done) {
+  if (bytes_avail <= 0) {
     return;
   }
 
@@ -654,17 +639,7 @@ Http2Stream::update_write_request(IOBufferReader 
*buf_reader, int64_t write_len,
         h2_proxy_ssn->connection_state.send_headers_frame(this);
       }
 
-      // See if the response is chunked.  Set up the dechunking logic if it is
-      // Make sure to check if the chunk is complete and signal appropriately
-      this->response_initialize_data_handling(is_done);
-
-      // If there is additional data, send it along in a data frame.  Or if 
this was header only
-      // make sure to send the end of stream
-      is_done |= (write_vio.ntodo() + this->response_header.length_get()) == 
bytes_avail;
-      if (this->response_is_data_available() || is_done) {
-        if (is_done) {
-          this->mark_body_done();
-        }
+      if (this->response_reader->is_read_avail_more_than(0)) {
         this->_milestones.mark(Http2StreamMilestone::START_TX_DATA_FRAMES);
         this->send_response_body(call_update);
       }
@@ -677,9 +652,6 @@ Http2Stream::update_write_request(IOBufferReader 
*buf_reader, int64_t write_len,
       break;
     }
   } else {
-    if (write_vio.ntodo() == bytes_avail || is_done) {
-      this->mark_body_done();
-    }
     this->_milestones.mark(Http2StreamMilestone::START_TX_DATA_FRAMES);
     this->send_response_body(call_update);
   }
@@ -820,7 +792,6 @@ Http2Stream::destroy()
   if (header_blocks) {
     ats_free(header_blocks);
   }
-  chunked_handler.clear();
   clear_timers();
   clear_io_events();
   http_parser_clear(&http_parser);
@@ -829,53 +800,10 @@ Http2Stream::destroy()
   THREAD_FREE(this, http2StreamAllocator, this_ethread());
 }
 
-void
-Http2Stream::response_initialize_data_handling(bool &is_done)
-{
-  is_done           = false;
-  int chunked_index = 
response_header.value_get_index(TS_MIME_FIELD_TRANSFER_ENCODING, 
TS_MIME_LEN_TRANSFER_ENCODING,
-                                                      TS_HTTP_VALUE_CHUNKED, 
TS_HTTP_LEN_CHUNKED);
-  // -1 means this value was not found for this field
-  if (chunked_index >= 0) {
-    Http2StreamDebug("Response is chunked");
-    chunked = true;
-    this->chunked_handler.init_by_action(this->response_reader, 
ChunkedHandler::ACTION_DECHUNK);
-    this->chunked_handler.state            = ChunkedHandler::CHUNK_READ_SIZE;
-    this->chunked_handler.dechunked_reader = 
this->chunked_handler.dechunked_buffer->alloc_reader();
-    this->response_reader->dealloc();
-    this->response_reader = nullptr;
-    // Get things going if there is already data waiting
-    if (this->chunked_handler.chunked_reader->is_read_avail_more_than(0)) {
-      response_process_data(is_done);
-    }
-  }
-}
-
-void
-Http2Stream::response_process_data(bool &done)
-{
-  done = false;
-  if (chunked) {
-    do {
-      if (chunked_handler.state == ChunkedHandler::CHUNK_FLOW_CONTROL) {
-        chunked_handler.state = ChunkedHandler::CHUNK_READ_SIZE_START;
-      }
-      done = this->chunked_handler.process_chunked_content();
-    } while (chunked_handler.state == ChunkedHandler::CHUNK_FLOW_CONTROL);
-  }
-}
-
-bool
-Http2Stream::response_is_data_available() const
-{
-  IOBufferReader *reader = this->response_get_data_reader();
-  return reader ? reader->is_read_avail_more_than(0) : false;
-}
-
 IOBufferReader *
 Http2Stream::response_get_data_reader() const
 {
-  return (chunked) ? chunked_handler.dechunked_reader : response_reader;
+  return this->response_reader;
 }
 
 void
@@ -1053,17 +981,6 @@ Http2Stream::_switch_thread_if_not_on_right_thread(int 
event, void *edata)
   return true;
 }
 
-void
-Http2Stream::mark_body_done()
-{
-  body_done = true;
-  if (response_is_chunked()) {
-    ink_assert(chunked_handler.state == ChunkedHandler::CHUNK_READ_DONE ||
-               chunked_handler.state == ChunkedHandler::CHUNK_READ_ERROR);
-    this->write_vio.nbytes = response_header.length_get() + 
chunked_handler.dechunked_size;
-  }
-}
-
 int
 Http2Stream::get_transaction_priority_weight() const
 {
diff --git a/proxy/http2/Http2Stream.h b/proxy/http2/Http2Stream.h
index 759b0f2..58baee6 100644
--- a/proxy/http2/Http2Stream.h
+++ b/proxy/http2/Http2Stream.h
@@ -24,9 +24,8 @@
 #pragma once
 
 #include "HTTP2.h"
-#include "../ProxyTransaction.h"
+#include "ProxyTransaction.h"
 #include "Http2DebugNames.h"
-#include "../http/HttpTunnel.h" // To get ChunkedHandler
 #include "Http2DependencyTree.h"
 #include "tscore/History.h"
 #include "Milestones.h"
@@ -107,7 +106,6 @@ public:
 
   bool is_client_state_writeable() const;
   bool is_closed() const;
-  bool response_is_chunked() const;
   IOBufferReader *response_get_data_reader() const;
 
   void mark_milestone(Http2StreamMilestone type);
@@ -115,7 +113,6 @@ public:
   void increment_data_length(uint64_t length);
   bool payload_length_is_valid() const;
   bool is_body_done() const;
-  void mark_body_done();
   void update_sent_count(unsigned num_bytes);
   Http2StreamId get_id() const;
   Http2StreamState get_state() const;
@@ -146,8 +143,6 @@ public:
   Http2DependencyTree::Node *priority_node = nullptr;
 
 private:
-  void response_initialize_data_handling(bool &is_done);
-  void response_process_data(bool &is_done);
   bool response_is_data_available() const;
   Event *send_tracked_event(Event *event, int send_event, VIO *vio);
   void send_response_body(bool call_update);
@@ -173,8 +168,6 @@ private:
   Milestones<Http2StreamMilestone, 
static_cast<size_t>(Http2StreamMilestone::LAST_ENTRY)> _milestones;
 
   bool trailing_header = false;
-  bool body_done       = false;
-  bool chunked         = false;
 
   // A brief discussion of similar flags and state variables:  _state, closed, 
terminate_stream
   //
@@ -208,7 +201,6 @@ private:
   std::vector<size_t> _recent_rwnd_increment = {SIZE_MAX, SIZE_MAX, SIZE_MAX, 
SIZE_MAX, SIZE_MAX};
   int _recent_rwnd_increment_index           = 0;
 
-  ChunkedHandler chunked_handler;
   Event *cross_thread_event      = nullptr;
   Event *buffer_full_write_event = nullptr;
 
@@ -240,7 +232,7 @@ Http2Stream::mark_milestone(Http2StreamMilestone type)
 inline bool
 Http2Stream::is_body_done() const
 {
-  return body_done;
+  return this->write_vio.ntodo() == 0;
 }
 
 inline void
@@ -301,12 +293,6 @@ Http2Stream::payload_length_is_valid() const
 }
 
 inline bool
-Http2Stream::response_is_chunked() const
-{
-  return chunked;
-}
-
-inline bool
 Http2Stream::allow_half_open() const
 {
   return false;

Reply via email to