aboutsummaryrefslogtreecommitdiff
path: root/cast/common/channel/message_framer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'cast/common/channel/message_framer.cc')
-rw-r--r--cast/common/channel/message_framer.cc71
1 files changed, 71 insertions, 0 deletions
diff --git a/cast/common/channel/message_framer.cc b/cast/common/channel/message_framer.cc
new file mode 100644
index 00000000..97a82466
--- /dev/null
+++ b/cast/common/channel/message_framer.cc
@@ -0,0 +1,71 @@
+// 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/common/channel/message_framer.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <limits>
+
+#include "cast/common/channel/proto/cast_channel.pb.h"
+#include "platform/api/logging.h"
+#include "util/big_endian.h"
+
+namespace cast {
+namespace channel {
+namespace message_serialization {
+
+using openscreen::Error;
+
+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
+
+ErrorOr<std::vector<uint8_t>> Serialize(const CastMessage& message) {
+ const size_t message_size = message.ByteSizeLong();
+ if (message_size > kMaxBodySize || message_size == 0) {
+ return Error::Code::kCastV2InvalidMessage;
+ }
+ std::vector<uint8_t> out(message_size + kHeaderSize, 0);
+ openscreen::WriteBigEndian<uint32_t>(message_size, out.data());
+ if (!message.SerializeToArray(&out[kHeaderSize], message_size)) {
+ return Error::Code::kCastV2InvalidMessage;
+ }
+ return out;
+}
+
+ErrorOr<DeserializeResult> TryDeserialize(absl::Span<uint8_t> input) {
+ if (input.size() < kHeaderSize) {
+ return Error::Code::kInsufficientBuffer;
+ }
+
+ const uint32_t message_size =
+ openscreen::ReadBigEndian<uint32_t>(input.data());
+ if (message_size > kMaxBodySize) {
+ return Error::Code::kCastV2InvalidMessage;
+ }
+
+ if (input.size() < (kHeaderSize + message_size)) {
+ return Error::Code::kInsufficientBuffer;
+ }
+
+ DeserializeResult result;
+ if (!result.message.ParseFromArray(input.data() + kHeaderSize,
+ message_size)) {
+ return Error::Code::kCastV2InvalidMessage;
+ }
+ result.length = kHeaderSize + message_size;
+
+ return result;
+}
+
+} // namespace message_serialization
+} // namespace channel
+} // namespace cast