diff options
Diffstat (limited to 'cast/common/channel/message_framer.cc')
-rw-r--r-- | cast/common/channel/message_framer.cc | 71 |
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 |