Imported Upstream version 1.41.0
[platform/upstream/grpc.git] / src / core / ext / transport / chttp2 / transport / frame_window_update.cc
index 4b586dc..9763e81 100644 (file)
 #include <grpc/support/port_platform.h>
 
 #include "src/core/ext/transport/chttp2/transport/frame_window_update.h"
-#include "src/core/ext/transport/chttp2/transport/internal.h"
+
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
+
+#include "src/core/ext/transport/chttp2/transport/internal.h"
 
 grpc_slice grpc_chttp2_window_update_create(
-    uint32_t id, uint32_t window_update, grpc_transport_one_way_stats* stats) {
+    uint32_t id, uint32_t window_delta, grpc_transport_one_way_stats* stats) {
   static const size_t frame_size = 13;
   grpc_slice slice = GRPC_SLICE_MALLOC(frame_size);
   stats->header_bytes += frame_size;
   uint8_t* p = GRPC_SLICE_START_PTR(slice);
 
-  GPR_ASSERT(window_update);
+  GPR_ASSERT(window_delta);
 
   *p++ = 0;
   *p++ = 0;
@@ -43,37 +46,31 @@ grpc_slice grpc_chttp2_window_update_create(
   *p++ = static_cast<uint8_t>(id >> 16);
   *p++ = static_cast<uint8_t>(id >> 8);
   *p++ = static_cast<uint8_t>(id);
-  *p++ = static_cast<uint8_t>(window_update >> 24);
-  *p++ = static_cast<uint8_t>(window_update >> 16);
-  *p++ = static_cast<uint8_t>(window_update >> 8);
-  *p++ = static_cast<uint8_t>(window_update);
+  *p++ = static_cast<uint8_t>(window_delta >> 24);
+  *p++ = static_cast<uint8_t>(window_delta >> 16);
+  *p++ = static_cast<uint8_t>(window_delta >> 8);
+  *p++ = static_cast<uint8_t>(window_delta);
 
   return slice;
 }
 
-grpc_error* grpc_chttp2_window_update_parser_begin_frame(
+grpc_error_handle grpc_chttp2_window_update_parser_begin_frame(
     grpc_chttp2_window_update_parser* parser, uint32_t length, uint8_t flags) {
   if (flags || length != 4) {
-    char* msg;
-    gpr_asprintf(&msg, "invalid window update: length=%d, flags=%02x", length,
-                 flags);
-    grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
-    gpr_free(msg);
-    return err;
+    return GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrFormat(
+        "invalid window update: length=%d, flags=%02x", length, flags));
   }
   parser->byte = 0;
   parser->amount = 0;
   return GRPC_ERROR_NONE;
 }
 
-grpc_error* grpc_chttp2_window_update_parser_parse(void* parser,
-                                                   grpc_chttp2_transport* t,
-                                                   grpc_chttp2_stream* s,
-                                                   grpc_slice slice,
-                                                   int is_last) {
-  uint8_t* const beg = GRPC_SLICE_START_PTR(slice);
-  uint8_t* const end = GRPC_SLICE_END_PTR(slice);
-  uint8_t* cur = beg;
+grpc_error_handle grpc_chttp2_window_update_parser_parse(
+    void* parser, grpc_chttp2_transport* t, grpc_chttp2_stream* s,
+    const grpc_slice& slice, int is_last) {
+  const uint8_t* const beg = GRPC_SLICE_START_PTR(slice);
+  const uint8_t* const end = GRPC_SLICE_END_PTR(slice);
+  const uint8_t* cur = beg;
   grpc_chttp2_window_update_parser* p =
       static_cast<grpc_chttp2_window_update_parser*>(parser);
 
@@ -88,19 +85,23 @@ grpc_error* grpc_chttp2_window_update_parser_parse(void* parser,
   }
 
   if (p->byte == 4) {
-    uint32_t received_update = p->amount;
-    if (received_update == 0 || (received_update & 0x80000000u)) {
-      char* msg;
-      gpr_asprintf(&msg, "invalid window update bytes: %d", p->amount);
-      grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
-      gpr_free(msg);
-      return err;
+    // top bit is reserved and must be ignored.
+    uint32_t received_update = p->amount & 0x7fffffffu;
+    if (received_update == 0) {
+      return GRPC_ERROR_CREATE_FROM_CPP_STRING(
+          absl::StrCat("invalid window update bytes: ", p->amount));
     }
     GPR_ASSERT(is_last);
 
     if (t->incoming_stream_id != 0) {
       if (s != nullptr) {
         s->flow_control->RecvUpdate(received_update);
+        if (grpc_core::chttp2::
+                g_test_only_transport_flow_control_window_check &&
+            s->flow_control->remote_window_delta() >
+                grpc_core::chttp2::kMaxWindowDelta) {
+          GPR_ASSERT(false);
+        }
         if (grpc_chttp2_list_remove_stalled_by_stream(t, s)) {
           grpc_chttp2_mark_stream_writable(t, s);
           grpc_chttp2_initiate_write(