aboutsummaryrefslogtreecommitdiff
path: root/cast/sender/channel/cast_framer.cc
diff options
context:
space:
mode:
authorbtolsch <btolsch@chromium.org>2019-09-18 13:50:32 -0700
committerCommit Bot <commit-bot@chromium.org>2019-09-18 21:00:03 +0000
commit26491c18de210836015403b7882b465c4552f81d (patch)
tree22b3af72544051e5f840a520399190bf475bf8e9 /cast/sender/channel/cast_framer.cc
parent17bbaa79f495bbd4e13983926413e11d92aec839 (diff)
downloadopenscreen-26491c18de210836015403b7882b465c4552f81d.tar.gz
Add framing for CastMessage
This change imports cast_framer.cc from Chromium's //components/cast_channel. Bug: openscreen:59 Change-Id: I189b6d1a243f439c8e8585afdb94f4bdd3d62251 Reviewed-on: https://chromium-review.googlesource.com/c/openscreen/+/1775425 Commit-Queue: Brandon Tolsch <btolsch@chromium.org> Reviewed-by: Max Yakimakha <yakimakha@chromium.org> Reviewed-by: Ryan Keane <rwkeane@google.com>
Diffstat (limited to 'cast/sender/channel/cast_framer.cc')
-rw-r--r--cast/sender/channel/cast_framer.cc94
1 files changed, 94 insertions, 0 deletions
diff --git a/cast/sender/channel/cast_framer.cc b/cast/sender/channel/cast_framer.cc
new file mode 100644
index 00000000..b5a8acb1
--- /dev/null
+++ b/cast/sender/channel/cast_framer.cc
@@ -0,0 +1,94 @@
+// Copyright 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 "cast/sender/channel/cast_framer.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <limits>
+
+#include "cast/sender/channel/proto/cast_channel.pb.h"
+#include "platform/api/logging.h"
+#include "util/big_endian.h"
+#include "util/std_util.h"
+
+namespace cast {
+namespace channel {
+
+using ChannelError = openscreen::Error::Code;
+
+namespace {
+
+static constexpr size_t kHeaderSize = sizeof(uint32_t);
+
+// Cast specifies a max message body size of 64 KiB.
+static constexpr size_t kMaxBodySize = 65536;
+
+} // namespace
+
+MessageFramer::MessageFramer(absl::Span<uint8_t> input_buffer)
+ : input_buffer_(input_buffer) {}
+
+MessageFramer::~MessageFramer() = default;
+
+// static
+ErrorOr<std::string> MessageFramer::Serialize(const CastMessage& message) {
+ const size_t message_size = message.ByteSizeLong();
+ if (message_size > kMaxBodySize || message_size == 0) {
+ return ChannelError::kCastV2InvalidMessage;
+ }
+ std::string out(message_size + kHeaderSize, 0);
+ openscreen::WriteBigEndian<uint32_t>(message_size, openscreen::data(out));
+ if (!message.SerializeToArray(&out[kHeaderSize], message_size)) {
+ return ChannelError::kCastV2InvalidMessage;
+ }
+ return out;
+}
+
+ErrorOr<size_t> MessageFramer::BytesRequested() const {
+ if (message_bytes_received_ < kHeaderSize) {
+ return kHeaderSize - message_bytes_received_;
+ }
+
+ const uint32_t message_size =
+ openscreen::ReadBigEndian<uint32_t>(input_buffer_.data());
+ if (message_size > kMaxBodySize) {
+ return ChannelError::kCastV2InvalidMessage;
+ }
+ return (kHeaderSize + message_size) - message_bytes_received_;
+}
+
+ErrorOr<CastMessage> MessageFramer::TryDeserialize(size_t byte_count) {
+ message_bytes_received_ += byte_count;
+ if (message_bytes_received_ > input_buffer_.size()) {
+ return ChannelError::kCastV2InvalidMessage;
+ }
+
+ if (message_bytes_received_ < kHeaderSize) {
+ return ChannelError::kInsufficientBuffer;
+ }
+
+ const uint32_t message_size =
+ openscreen::ReadBigEndian<uint32_t>(input_buffer_.data());
+ if (message_size > kMaxBodySize) {
+ return ChannelError::kCastV2InvalidMessage;
+ }
+
+ if (message_bytes_received_ < (kHeaderSize + message_size)) {
+ return ChannelError::kInsufficientBuffer;
+ }
+
+ CastMessage parsed_message;
+ if (!parsed_message.ParseFromArray(input_buffer_.data() + kHeaderSize,
+ message_size)) {
+ return ChannelError::kCastV2InvalidMessage;
+ }
+
+ message_bytes_received_ = 0;
+ return parsed_message;
+}
+
+} // namespace channel
+} // namespace cast