| // Copyright 2021 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 "chromecast/base/hash_util.h" |
| |
| #include <limits.h> |
| #include <vector> |
| |
| #include "base/check_op.h" |
| #include "base/hash/sha1.h" |
| #include "base/logging.h" |
| #include "base/notreached.h" |
| #include "base/stl_util.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_split.h" |
| #include "base/strings/string_util.h" |
| #include "chromecast/base/legacy_app_id_mapper.h" |
| #include "chromecast/base/version.h" |
| |
| namespace chromecast { |
| |
| namespace { |
| |
| const size_t kAppIdV2StrLen = 8; |
| |
| } // namespace |
| |
| uint64_t HashToUInt64(const std::string& value) { |
| uint64_t output; |
| const std::string sha1hash = base::SHA1HashString(value); |
| DCHECK_GE(sha1hash.size(), sizeof(output)); |
| memcpy(&output, sha1hash.data(), sizeof(output)); |
| return output; |
| } |
| |
| uint32_t HashToUInt32(const std::string& value) { |
| uint32_t output; |
| const std::string sha1hash = base::SHA1HashString(value); |
| DCHECK_GE(sha1hash.size(), sizeof(output)); |
| memcpy(&output, sha1hash.data(), sizeof(output)); |
| return output; |
| } |
| |
| uint64_t HashGUID64(const std::string& guid) { |
| std::string hex; |
| base::RemoveChars(guid, "-", &hex); |
| uint64_t output; |
| DCHECK_EQ(hex.size(), 32u); |
| if (base::HexStringToUInt64(hex.substr(0, 16), &output)) |
| return output; |
| NOTREACHED(); |
| return 0; |
| } |
| |
| uint32_t HashAppId32(const std::string& app_id) { |
| uint32_t output; |
| if (app_id.size() == kAppIdV2StrLen && |
| base::HexStringToUInt(app_id, &output)) { |
| return output; |
| } |
| |
| return MapLegacyAppId(app_id); |
| } |
| |
| uint64_t HashCastBuildNumber64(const std::string& build_number) { |
| uint64_t return_value = 0; |
| std::vector<std::string> tokens(base::SplitString( |
| build_number, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)); |
| const size_t tsize = tokens.size(); |
| if (tsize < 1 || tsize > 4) |
| return static_cast<uint64_t>(-1); |
| |
| int bits = 64 / tsize; |
| // special case for 3-tuple to make hex look nicer. |
| if (tsize == 3) |
| bits = 16; |
| |
| for (size_t i = 0; i < tsize; ++i) { |
| // special case for the last token of 3-tuple. |
| if (tsize == 3 && i == 2) |
| bits = 32; |
| return_value <<= bits; |
| unsigned value = 0; |
| if (!base::StringToUint(tokens[i], &value)) |
| return static_cast<uint64_t>(-1); |
| if (bits != 64) // avoid overflow |
| value &= (static_cast<uint64_t>(1) << bits) - 1; |
| return_value |= value; |
| } |
| return return_value; |
| } |
| |
| uint64_t HashSessionId64(const std::string& session_id) { |
| return HashGUID64(session_id); |
| } |
| |
| uint64_t HashSdkVersion64(const std::string& sdk_version) { |
| if (sdk_version.empty()) |
| return 0; |
| |
| // Sdk version is usually in "X.Y.Z(.minor)" format. |
| // Following code is a little bit relaxed to accept all sub-fields optional. |
| uint64_t return_value = 0; |
| std::vector<std::string> tokens(base::SplitString( |
| sdk_version, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)); |
| for (size_t i = 0; i < 4; ++i) { |
| return_value <<= 16; |
| if (tokens.size() > i) { |
| unsigned value = 0; |
| if (base::StringToUint(tokens[i], &value)) { |
| return_value |= value & 0xFFFF; |
| } else { |
| LOG_IF(ERROR, !CAST_IS_DEBUG_BUILD()) |
| << "Sdk version " << sdk_version << " is not in correct format."; |
| return static_cast<uint64_t>(-1); |
| } |
| } |
| } |
| return return_value; |
| } |
| |
| uint32_t HashSocketId32(const std::string& socket_id) { |
| uint32_t output; |
| // socket id is usually just numerical. |
| if (base::StringToUint(socket_id, &output)) { |
| return output; |
| } else { // CastControlSocket and unittests. |
| return HashToUInt32(socket_id); |
| } |
| } |
| |
| uint32_t HashConnectionId32(const std::string& connection_id) { |
| return HashToUInt32(connection_id); |
| } |
| |
| uint64_t HashAndroidBuildNumber64(const std::string& build_id) { |
| if (build_id.length() == 0) { |
| return static_cast<uint64_t>(-1); |
| } |
| |
| uint64_t value = 0; |
| for (const char& c : build_id.substr(0, sizeof(value) / sizeof(char))) { |
| value <<= CHAR_BIT; |
| value += c; |
| } |
| return value; |
| } |
| |
| } // namespace chromecast |