diff options
author | Jordan Bayles <jophba@chromium.org> | 2020-12-10 11:12:44 -0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-12-10 19:26:04 +0000 |
commit | 79c6ea2a0c44439e73d3c9d9859513eb4d086983 (patch) | |
tree | b6eb16b78bc168225621f6a39a2aee83e2888514 /util | |
parent | b2522b5f9832ad9e64428a2245f4a7fb0171ec8d (diff) | |
download | openscreen-79c6ea2a0c44439e73d3c9d9859513eb4d086983.tar.gz |
Refactor session message sending
This patch refactors session message sending to include multiple new
message types, such as RPC and GET_STATUS. Integration tests
are included.
Bug: b/170756458, b/174188662
Change-Id: I8b5de8a668171e0ce7cb3e74651d207aa7911c24
Reviewed-on: https://chromium-review.googlesource.com/c/openscreen/+/2506651
Commit-Queue: Jordan Bayles <jophba@chromium.org>
Reviewed-by: Yuri Wiitala <miu@chromium.org>
Diffstat (limited to 'util')
-rw-r--r-- | util/BUILD.gn | 7 | ||||
-rw-r--r-- | util/base64.cc | 54 | ||||
-rw-r--r-- | util/base64.h | 31 | ||||
-rw-r--r-- | util/base64_unittest.cc | 60 | ||||
-rw-r--r-- | util/json/json_helpers.h | 16 | ||||
-rw-r--r-- | util/json/json_helpers_unittest.cc | 7 |
6 files changed, 169 insertions, 6 deletions
diff --git a/util/BUILD.gn b/util/BUILD.gn index f1da81e4..1cb34360 100644 --- a/util/BUILD.gn +++ b/util/BUILD.gn @@ -21,6 +21,8 @@ source_set("util") { sources = [ "alarm.cc", "alarm.h", + "base64.cc", + "base64.h", "big_endian.cc", "big_endian.h", "chrono_helpers.h", @@ -78,6 +80,10 @@ source_set("util") { deps = [ "../third_party/boringssl", "../third_party/mozilla", + + # We do a clone of Chrome's modp_b64 in order to share their BUILD.gn + # and license files, so this should always be an absolute reference. + "//third_party/modp_b64", ] public_configs = [ @@ -91,6 +97,7 @@ source_set("unittests") { sources = [ "alarm_unittest.cc", + "base64_unittest.cc", "big_endian_unittest.cc", "crypto/random_bytes_unittest.cc", "crypto/rsa_private_key_unittest.cc", diff --git a/util/base64.cc b/util/base64.cc new file mode 100644 index 00000000..06e120e0 --- /dev/null +++ b/util/base64.cc @@ -0,0 +1,54 @@ +// Copyright 2020 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 "util/base64.h" + +#include <stddef.h> + +#include "third_party/modp_b64/modp_b64.h" +#include "util/osp_logging.h" +#include "util/std_util.h" + +namespace openscreen { +namespace base64 { + +std::string Encode(absl::Span<const uint8_t> input) { + return Encode(absl::string_view(reinterpret_cast<const char*>(input.data()), + input.size())); +} + +std::string Encode(absl::string_view input) { + std::string out; + out.resize(modp_b64_encode_len(input.size())); + + const size_t output_size = + modp_b64_encode(data(out), input.data(), input.size()); + if (output_size == MODP_B64_ERROR) { + return {}; + } + + // The encode_len is generally larger than needed. + out.resize(output_size); + return out; +} + +bool Decode(absl::string_view input, std::string* output) { + std::string out; + out.resize(modp_b64_decode_len(input.size())); + + // We don't null terminate the result since it is binary data. + const size_t output_size = + modp_b64_decode(data(out), input.data(), input.size()); + if (output_size == MODP_B64_ERROR) { + return false; + } + + // The output size from decode_len is generally larger than needed. + out.resize(output_size); + output->swap(out); + return true; +} + +} // namespace base64 +} // namespace openscreen diff --git a/util/base64.h b/util/base64.h new file mode 100644 index 00000000..b24c3b3f --- /dev/null +++ b/util/base64.h @@ -0,0 +1,31 @@ +// Copyright 2020 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. + +#ifndef UTIL_BASE64_H_ +#define UTIL_BASE64_H_ + +#include <string> + +#include "absl/strings/string_view.h" +#include "absl/types/span.h" +#include "platform/base/error.h" + +namespace openscreen { +namespace base64 { + +// Encodes the input binary data in base64. +std::string Encode(absl::Span<const uint8_t> input); + +// Encodes the input string in base64. +std::string Encode(absl::string_view input); + +// Decodes the base64 input string. Returns true if successful and false +// otherwise. The output string is only modified if successful. The decoding can +// be done in-place. +bool Decode(absl::string_view input, std::string* output); + +} // namespace base64 +} // namespace openscreen + +#endif // UTIL_BASE64_H_ diff --git a/util/base64_unittest.cc b/util/base64_unittest.cc new file mode 100644 index 00000000..28d4fb1d --- /dev/null +++ b/util/base64_unittest.cc @@ -0,0 +1,60 @@ +// Copyright 2020 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 "util/base64.h" + +#include "gtest/gtest.h" + +namespace openscreen { +namespace base64 { + +namespace { + +constexpr char kText[] = "hello world"; +constexpr char kBase64Text[] = "aGVsbG8gd29ybGQ="; + +void CheckEncodeDecode(const char* to_encode, const char* encode_expected) { + std::string encoded = Encode(to_encode); + EXPECT_EQ(encode_expected, encoded); + + std::string decoded; + EXPECT_TRUE(Decode(encoded, &decoded)); + EXPECT_EQ(to_encode, decoded); +} + +} // namespace + +TEST(Base64Test, ZeroSize) { + CheckEncodeDecode("", ""); +} + +TEST(Base64Test, Basic) { + CheckEncodeDecode(kText, kBase64Text); +} + +TEST(Base64Test, Binary) { + const uint8_t kData[] = {0x00, 0x01, 0xFE, 0xFF}; + + std::string binary_encoded = Encode(absl::MakeConstSpan(kData)); + + // Check that encoding the same data through the StringPiece interface gives + // the same results. + std::string string_piece_encoded = Encode( + absl::string_view(reinterpret_cast<const char*>(kData), sizeof(kData))); + + EXPECT_EQ(binary_encoded, string_piece_encoded); +} + +TEST(Base64Test, InPlace) { + std::string text(kText); + + text = Encode(text); + EXPECT_EQ(kBase64Text, text); + + EXPECT_TRUE(Decode(text, &text)); + EXPECT_EQ(text, kText); +} + +} // namespace base64 +} // namespace openscreen diff --git a/util/json/json_helpers.h b/util/json/json_helpers.h index a4c43479..1943973d 100644 --- a/util/json/json_helpers.h +++ b/util/json/json_helpers.h @@ -6,6 +6,7 @@ #define UTIL_JSON_JSON_HELPERS_H_ #include <chrono> +#include <cmath> #include <functional> #include <string> #include <utility> @@ -77,16 +78,19 @@ inline bool ParseBool(const Json::Value& value, bool* out) { } // A general note about parsing primitives. "Validation" in this context -// generally means ensuring that the values are non-negative. There are -// currently no cases in our usage of JSON strings where we accept negative -// values. If this changes in the future, care must be taken to ensure -// that we don't break anything in existing code. -inline bool ParseAndValidateDouble(const Json::Value& value, double* out) { +// generally means ensuring that the values are non-negative, excepting doubles +// which may be negative in some cases. +inline bool ParseAndValidateDouble(const Json::Value& value, + double* out, + bool allow_negative = false) { if (!value.isDouble()) { return false; } const double d = value.asDouble(); - if (d < 0) { + if (std::isnan(d)) { + return false; + } + if (!allow_negative && d < 0) { return false; } *out = d; diff --git a/util/json/json_helpers_unittest.cc b/util/json/json_helpers_unittest.cc index fdac1897..c461cf93 100644 --- a/util/json/json_helpers_unittest.cc +++ b/util/json/json_helpers_unittest.cc @@ -42,6 +42,7 @@ TEST(ParsingHelpersTest, ParseAndValidateDouble) { const Json::Value kNotDouble = "coffee beans"; const Json::Value kNegativeDouble = -4.2; const Json::Value kZeroDouble = 0.0; + const Json::Value kNanDouble = std::nan(""); double out; EXPECT_TRUE(ParseAndValidateDouble(kValid, &out)); @@ -51,6 +52,7 @@ TEST(ParsingHelpersTest, ParseAndValidateDouble) { EXPECT_FALSE(ParseAndValidateDouble(kNotDouble, &out)); EXPECT_FALSE(ParseAndValidateDouble(kNegativeDouble, &out)); EXPECT_FALSE(ParseAndValidateDouble(kNone, &out)); + EXPECT_FALSE(ParseAndValidateDouble(kNanDouble, &out)); } TEST(ParsingHelpersTest, ParseAndValidateInt) { @@ -105,18 +107,23 @@ TEST(ParsingHelpersTest, ParseAndValidateSimpleFraction) { const Json::Value kNegative = "10/-2"; const Json::Value kInvalidNumber = "-1"; const Json::Value kNotSimpleFraction = "latte"; + const Json::Value kInteger = 123; + const Json::Value kNegativeInteger = -5000; SimpleFraction out; EXPECT_TRUE(ParseAndValidateSimpleFraction(kValid, &out)); EXPECT_EQ((SimpleFraction{42, 30}), out); EXPECT_TRUE(ParseAndValidateSimpleFraction(kValidNumber, &out)); EXPECT_EQ((SimpleFraction{42, 1}), out); + EXPECT_TRUE(ParseAndValidateSimpleFraction(kInteger, &out)); + EXPECT_EQ((SimpleFraction{123, 1}), out); EXPECT_FALSE(ParseAndValidateSimpleFraction(kUndefined, &out)); EXPECT_FALSE(ParseAndValidateSimpleFraction(kNegative, &out)); EXPECT_FALSE(ParseAndValidateSimpleFraction(kInvalidNumber, &out)); EXPECT_FALSE(ParseAndValidateSimpleFraction(kNotSimpleFraction, &out)); EXPECT_FALSE(ParseAndValidateSimpleFraction(kNone, &out)); EXPECT_FALSE(ParseAndValidateSimpleFraction(kEmptyString, &out)); + EXPECT_FALSE(ParseAndValidateSimpleFraction(kNegativeInteger, &out)); } TEST(ParsingHelpersTest, ParseAndValidateMilliseconds) { |