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