| // Copyright (c) 2019 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "quic/qbone/qbone_control_stream.h" |
| |
| #include <cstdint> |
| #include <limits> |
| |
| #include "absl/strings/string_view.h" |
| #include "quic/core/quic_session.h" |
| #include "quic/platform/api/quic_bug_tracker.h" |
| #include "quic/qbone/qbone_constants.h" |
| |
| namespace quic { |
| |
| namespace { |
| static constexpr size_t kRequestSizeBytes = sizeof(uint16_t); |
| } // namespace |
| |
| QboneControlStreamBase::QboneControlStreamBase(QuicSession* session) |
| : QuicStream( |
| QboneConstants::GetControlStreamId(session->transport_version()), |
| session, |
| /*is_static=*/true, |
| BIDIRECTIONAL), |
| pending_message_size_(0) {} |
| |
| QboneControlStreamBase::QboneControlStreamBase(quic::PendingStream* pending, |
| QuicSession* session) |
| : QuicStream(pending, session, /*is_static=*/true), |
| pending_message_size_(0) { |
| QUICHE_DCHECK_EQ(pending->id(), QboneConstants::GetControlStreamId( |
| session->transport_version())); |
| } |
| |
| void QboneControlStreamBase::OnDataAvailable() { |
| sequencer()->Read(&buffer_); |
| while (true) { |
| if (pending_message_size_ == 0) { |
| // Start of a message. |
| if (buffer_.size() < kRequestSizeBytes) { |
| return; |
| } |
| memcpy(&pending_message_size_, buffer_.data(), kRequestSizeBytes); |
| buffer_.erase(0, kRequestSizeBytes); |
| } |
| // Continuation of a message. |
| if (buffer_.size() < pending_message_size_) { |
| return; |
| } |
| std::string tmp = buffer_.substr(0, pending_message_size_); |
| buffer_.erase(0, pending_message_size_); |
| pending_message_size_ = 0; |
| OnMessage(tmp); |
| } |
| } |
| |
| bool QboneControlStreamBase::SendMessage(const proto2::Message& proto) { |
| std::string tmp; |
| if (!proto.SerializeToString(&tmp)) { |
| QUIC_BUG(quic_bug_11023_1) << "Failed to serialize QboneControlRequest"; |
| return false; |
| } |
| if (tmp.size() > std::numeric_limits<uint16_t>::max()) { |
| QUIC_BUG(quic_bug_11023_2) |
| << "QboneControlRequest too large: " << tmp.size() << " > " |
| << std::numeric_limits<uint16_t>::max(); |
| return false; |
| } |
| uint16_t size = tmp.size(); |
| char size_str[kRequestSizeBytes]; |
| memcpy(size_str, &size, kRequestSizeBytes); |
| WriteOrBufferData(absl::string_view(size_str, kRequestSizeBytes), false, |
| nullptr); |
| WriteOrBufferData(tmp, false, nullptr); |
| return true; |
| } |
| |
| void QboneControlStreamBase::OnStreamReset( |
| const QuicRstStreamFrame& /*frame*/) { |
| stream_delegate()->OnStreamError(QUIC_INVALID_STREAM_ID, |
| "Attempt to reset control stream"); |
| } |
| |
| } // namespace quic |