1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "fidl/ordinals.h"
6 
7 #include <optional>
8 
9 #define BORINGSSL_NO_CXX
10 #include <openssl/sha.h>
11 
12 namespace fidl {
13 namespace ordinals {
14 
GetSelector(const raw::AttributeList * attributes,SourceLocation name)15 std::string GetSelector(const raw::AttributeList* attributes, SourceLocation name) {
16     if (attributes != nullptr) {
17         const size_t size = attributes->attributes.size();
18         for (int i = 0; i < size; i++) {
19             if (attributes->attributes[i]->name == "Selector") {
20                 return attributes->attributes[i]->value;
21             }
22         }
23     }
24     return std::string(name.data().data(), name.data().size());
25 }
26 
GetOrdinal(const std::vector<StringView> & library_name,const StringView & interface_name,const raw::InterfaceMethod & method)27 raw::Ordinal GetOrdinal(const std::vector<StringView>& library_name,
28                         const StringView& interface_name,
29                         const raw::InterfaceMethod& method) {
30     if (method.ordinal != nullptr)
31         return *method.ordinal;
32 
33     std::string method_name = GetSelector(method.attributes.get(), method.identifier->location());
34     std::string full_name;
35     bool once = false;
36     for (StringView id : library_name) {
37         if (once) {
38             full_name.push_back('.');
39         } else {
40             once = true;
41         }
42         full_name.append(id.data(), id.size());
43     }
44     full_name.append(".");
45     full_name.append(interface_name.data(), interface_name.size());
46     full_name.append("/");
47     full_name.append(method_name);
48 
49     uint8_t digest[SHA256_DIGEST_LENGTH];
50     SHA256(reinterpret_cast<const uint8_t*>(full_name.data()), full_name.size(), digest);
51     // The following dance ensures that we treat the bytes as a little-endian
52     // int32 regardless of host byte order.
53     uint32_t ordinal = static_cast<uint32_t>(digest[0]) |
54         static_cast<uint32_t>(digest[1]) << 8 |
55         static_cast<uint32_t>(digest[2]) << 16 |
56         static_cast<uint32_t>(digest[3]) << 24;
57 
58     ordinal &= 0x7fffffff;
59     return raw::Ordinal(*method.identifier, ordinal);
60 }
61 
62 } // namespace ordinals
63 } // namespace fidl
64