| // 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 "net/third_party/quiche/src/quic/qbone/qbone_control_stream.h" | 
 |  | 
 | #include "net/third_party/quiche/src/quic/core/quic_session.h" | 
 | #include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h" | 
 | #include "net/third_party/quiche/src/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) {} | 
 |  | 
 | 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; | 
 |     } | 
 |     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) { | 
 |   string tmp; | 
 |   if (!proto.SerializeToString(&tmp)) { | 
 |     QUIC_BUG << "Failed to serialize QboneControlRequest"; | 
 |     return false; | 
 |   } | 
 |   if (tmp.size() > kuint16max) { | 
 |     QUIC_BUG << "QboneControlRequest too large: " << tmp.size() << " > " | 
 |              << kuint16max; | 
 |     return false; | 
 |   } | 
 |   uint16_t size = tmp.size(); | 
 |   char size_str[kRequestSizeBytes]; | 
 |   memcpy(size_str, &size, kRequestSizeBytes); | 
 |   WriteOrBufferData(QuicStringPiece(size_str, kRequestSizeBytes), false, | 
 |                     nullptr); | 
 |   WriteOrBufferData(tmp, false, nullptr); | 
 |   return true; | 
 | } | 
 |  | 
 | }  // namespace quic |