xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/qbone/qbone_control_stream.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 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/qbone/qbone_control_stream.h"
6 
7 #include <cstdint>
8 #include <limits>
9 
10 #include "absl/strings/string_view.h"
11 #include "quiche/quic/core/quic_session.h"
12 #include "quiche/quic/platform/api/quic_bug_tracker.h"
13 #include "quiche/quic/qbone/qbone_constants.h"
14 
15 namespace quic {
16 
17 namespace {
18 static constexpr size_t kRequestSizeBytes = sizeof(uint16_t);
19 }  // namespace
20 
QboneControlStreamBase(QuicSession * session)21 QboneControlStreamBase::QboneControlStreamBase(QuicSession* session)
22     : QuicStream(
23           QboneConstants::GetControlStreamId(session->transport_version()),
24           session,
25           /*is_static=*/true, BIDIRECTIONAL),
26       pending_message_size_(0) {}
27 
QboneControlStreamBase(quic::PendingStream * pending,QuicSession * session)28 QboneControlStreamBase::QboneControlStreamBase(quic::PendingStream* pending,
29                                                QuicSession* session)
30     : QuicStream(pending, session, /*is_static=*/true),
31       pending_message_size_(0) {
32   QUICHE_DCHECK_EQ(pending->id(), QboneConstants::GetControlStreamId(
33                                       session->transport_version()));
34 }
35 
OnDataAvailable()36 void QboneControlStreamBase::OnDataAvailable() {
37   sequencer()->Read(&buffer_);
38   while (true) {
39     if (pending_message_size_ == 0) {
40       // Start of a message.
41       if (buffer_.size() < kRequestSizeBytes) {
42         return;
43       }
44       memcpy(&pending_message_size_, buffer_.data(), kRequestSizeBytes);
45       buffer_.erase(0, kRequestSizeBytes);
46     }
47     // Continuation of a message.
48     if (buffer_.size() < pending_message_size_) {
49       return;
50     }
51     std::string tmp = buffer_.substr(0, pending_message_size_);
52     buffer_.erase(0, pending_message_size_);
53     pending_message_size_ = 0;
54     OnMessage(tmp);
55   }
56 }
57 
SendMessage(const proto2::Message & proto)58 bool QboneControlStreamBase::SendMessage(const proto2::Message& proto) {
59   std::string tmp;
60   if (!proto.SerializeToString(&tmp)) {
61     QUIC_BUG(quic_bug_11023_1) << "Failed to serialize QboneControlRequest";
62     return false;
63   }
64   if (tmp.size() > std::numeric_limits<uint16_t>::max()) {
65     QUIC_BUG(quic_bug_11023_2)
66         << "QboneControlRequest too large: " << tmp.size() << " > "
67         << std::numeric_limits<uint16_t>::max();
68     return false;
69   }
70   uint16_t size = tmp.size();
71   char size_str[kRequestSizeBytes];
72   memcpy(size_str, &size, kRequestSizeBytes);
73   WriteOrBufferData(absl::string_view(size_str, kRequestSizeBytes), false,
74                     nullptr);
75   WriteOrBufferData(tmp, false, nullptr);
76   return true;
77 }
78 
OnStreamReset(const QuicRstStreamFrame &)79 void QboneControlStreamBase::OnStreamReset(
80     const QuicRstStreamFrame& /*frame*/) {
81   stream_delegate()->OnStreamError(QUIC_INVALID_STREAM_ID,
82                                    "Attempt to reset control stream");
83 }
84 
85 }  // namespace quic
86