xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/http/quic_send_control_stream.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/quic/core/http/quic_send_control_stream.h"
6 
7 #include <cstdint>
8 #include <memory>
9 
10 #include "absl/base/macros.h"
11 #include "absl/strings/string_view.h"
12 #include "quiche/quic/core/crypto/quic_random.h"
13 #include "quiche/quic/core/http/http_constants.h"
14 #include "quiche/quic/core/http/quic_spdy_session.h"
15 #include "quiche/quic/core/quic_session.h"
16 #include "quiche/quic/core/quic_types.h"
17 #include "quiche/quic/core/quic_utils.h"
18 #include "quiche/quic/platform/api/quic_logging.h"
19 
20 namespace quic {
21 namespace {
22 
23 }  // anonymous namespace
24 
QuicSendControlStream(QuicStreamId id,QuicSpdySession * spdy_session,const SettingsFrame & settings)25 QuicSendControlStream::QuicSendControlStream(QuicStreamId id,
26                                              QuicSpdySession* spdy_session,
27                                              const SettingsFrame& settings)
28     : QuicStream(id, spdy_session, /*is_static = */ true, WRITE_UNIDIRECTIONAL),
29       settings_sent_(false),
30       settings_(settings),
31       spdy_session_(spdy_session) {}
32 
OnStreamReset(const QuicRstStreamFrame &)33 void QuicSendControlStream::OnStreamReset(const QuicRstStreamFrame& /*frame*/) {
34   QUIC_BUG(quic_bug_10382_1)
35       << "OnStreamReset() called for write unidirectional stream.";
36 }
37 
OnStopSending(QuicResetStreamError)38 bool QuicSendControlStream::OnStopSending(QuicResetStreamError /* code */) {
39   stream_delegate()->OnStreamError(
40       QUIC_HTTP_CLOSED_CRITICAL_STREAM,
41       "STOP_SENDING received for send control stream");
42   return false;
43 }
44 
MaybeSendSettingsFrame()45 void QuicSendControlStream::MaybeSendSettingsFrame() {
46   if (settings_sent_) {
47     return;
48   }
49 
50   QuicConnection::ScopedPacketFlusher flusher(session()->connection());
51   // Send the stream type on so the peer knows about this stream.
52   char data[sizeof(kControlStream)];
53   QuicDataWriter writer(ABSL_ARRAYSIZE(data), data);
54   writer.WriteVarInt62(kControlStream);
55   WriteOrBufferData(absl::string_view(writer.data(), writer.length()), false,
56                     nullptr);
57 
58   SettingsFrame settings = settings_;
59   // https://tools.ietf.org/html/draft-ietf-quic-http-25#section-7.2.4.1
60   // specifies that setting identifiers of 0x1f * N + 0x21 are reserved and
61   // greasing should be attempted.
62   if (!GetQuicFlag(quic_enable_http3_grease_randomness)) {
63     settings.values[0x40] = 20;
64   } else {
65     uint32_t result;
66     QuicRandom::GetInstance()->RandBytes(&result, sizeof(result));
67     uint64_t setting_id = 0x1fULL * static_cast<uint64_t>(result) + 0x21ULL;
68     QuicRandom::GetInstance()->RandBytes(&result, sizeof(result));
69     settings.values[setting_id] = result;
70   }
71 
72   std::string settings_frame = HttpEncoder::SerializeSettingsFrame(settings);
73   QUIC_DVLOG(1) << "Control stream " << id() << " is writing settings frame "
74                 << settings;
75   if (spdy_session_->debug_visitor()) {
76     spdy_session_->debug_visitor()->OnSettingsFrameSent(settings);
77   }
78   WriteOrBufferData(settings_frame, /*fin = */ false, nullptr);
79   settings_sent_ = true;
80 
81   // https://tools.ietf.org/html/draft-ietf-quic-http-25#section-7.2.9
82   // specifies that a reserved frame type has no semantic meaning and should be
83   // discarded. A greasing frame is added here.
84   WriteOrBufferData(HttpEncoder::SerializeGreasingFrame(), /*fin = */ false,
85                     nullptr);
86 }
87 
WritePriorityUpdate(QuicStreamId stream_id,HttpStreamPriority priority)88 void QuicSendControlStream::WritePriorityUpdate(QuicStreamId stream_id,
89                                                 HttpStreamPriority priority) {
90   QuicConnection::ScopedPacketFlusher flusher(session()->connection());
91   MaybeSendSettingsFrame();
92 
93   const std::string priority_field_value =
94       SerializePriorityFieldValue(priority);
95   PriorityUpdateFrame priority_update_frame{stream_id, priority_field_value};
96   if (spdy_session_->debug_visitor()) {
97     spdy_session_->debug_visitor()->OnPriorityUpdateFrameSent(
98         priority_update_frame);
99   }
100 
101   std::string frame =
102       HttpEncoder::SerializePriorityUpdateFrame(priority_update_frame);
103   QUIC_DVLOG(1) << "Control Stream " << id() << " is writing "
104                 << priority_update_frame;
105   WriteOrBufferData(frame, false, nullptr);
106 }
107 
SendGoAway(QuicStreamId id)108 void QuicSendControlStream::SendGoAway(QuicStreamId id) {
109   QuicConnection::ScopedPacketFlusher flusher(session()->connection());
110   MaybeSendSettingsFrame();
111 
112   GoAwayFrame frame;
113   frame.id = id;
114   if (spdy_session_->debug_visitor()) {
115     spdy_session_->debug_visitor()->OnGoAwayFrameSent(id);
116   }
117 
118   WriteOrBufferData(HttpEncoder::SerializeGoAwayFrame(frame), false, nullptr);
119 }
120 
121 }  // namespace quic
122