1 //
2 //
3 // Copyright 2018 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18
19 #include <grpc/support/port_platform.h>
20
21 #include "src/core/lib/resolver/server_address.h"
22
23 #include <string.h>
24
25 #include <algorithm>
26 #include <initializer_list>
27 #include <memory>
28 #include <string>
29 #include <utility>
30 #include <vector>
31
32 #include "absl/status/status.h"
33 #include "absl/status/statusor.h"
34 #include "absl/strings/str_cat.h"
35 #include "absl/strings/str_format.h"
36 #include "absl/strings/str_join.h"
37
38 #include "src/core/lib/address_utils/sockaddr_utils.h"
39 #include "src/core/lib/channel/channel_args.h"
40
41 // IWYU pragma: no_include <sys/socket.h>
42
43 namespace grpc_core {
44
45 //
46 // ServerAddressWeightAttribute
47 //
48 const char* ServerAddressWeightAttribute::kServerAddressWeightAttributeKey =
49 "server_address_weight";
50
51 //
52 // ServerAddress
53 //
54
ServerAddress(const grpc_resolved_address & address,const ChannelArgs & args,std::map<const char *,std::unique_ptr<AttributeInterface>> attributes)55 ServerAddress::ServerAddress(
56 const grpc_resolved_address& address, const ChannelArgs& args,
57 std::map<const char*, std::unique_ptr<AttributeInterface>> attributes)
58 : address_(address), args_(args), attributes_(std::move(attributes)) {}
59
ServerAddress(const ServerAddress & other)60 ServerAddress::ServerAddress(const ServerAddress& other)
61 : address_(other.address_), args_(other.args_) {
62 for (const auto& p : other.attributes_) {
63 attributes_[p.first] = p.second->Copy();
64 }
65 }
operator =(const ServerAddress & other)66 ServerAddress& ServerAddress::operator=(const ServerAddress& other) {
67 if (&other == this) {
68 return *this;
69 }
70 address_ = other.address_;
71 args_ = other.args_;
72 attributes_.clear();
73 for (const auto& p : other.attributes_) {
74 attributes_[p.first] = p.second->Copy();
75 }
76 return *this;
77 }
78
ServerAddress(ServerAddress && other)79 ServerAddress::ServerAddress(ServerAddress&& other) noexcept
80 : address_(other.address_),
81 args_(std::move(other.args_)),
82 attributes_(std::move(other.attributes_)) {}
83
operator =(ServerAddress && other)84 ServerAddress& ServerAddress::operator=(ServerAddress&& other) noexcept {
85 address_ = other.address_;
86 args_ = std::move(other.args_);
87 attributes_ = std::move(other.attributes_);
88 return *this;
89 }
90
91 namespace {
92
CompareAttributes(const std::map<const char *,std::unique_ptr<ServerAddress::AttributeInterface>> & attributes1,const std::map<const char *,std::unique_ptr<ServerAddress::AttributeInterface>> & attributes2)93 int CompareAttributes(
94 const std::map<const char*,
95 std::unique_ptr<ServerAddress::AttributeInterface>>&
96 attributes1,
97 const std::map<const char*,
98 std::unique_ptr<ServerAddress::AttributeInterface>>&
99 attributes2) {
100 auto it2 = attributes2.begin();
101 for (auto it1 = attributes1.begin(); it1 != attributes1.end(); ++it1) {
102 // attributes2 has fewer elements than attributes1
103 if (it2 == attributes2.end()) return -1;
104 // compare keys
105 int retval = strcmp(it1->first, it2->first);
106 if (retval != 0) return retval;
107 // compare values
108 retval = it1->second->Cmp(it2->second.get());
109 if (retval != 0) return retval;
110 ++it2;
111 }
112 // attributes1 has fewer elements than attributes2
113 if (it2 != attributes2.end()) return 1;
114 // equal
115 return 0;
116 }
117
118 } // namespace
119
Cmp(const ServerAddress & other) const120 int ServerAddress::Cmp(const ServerAddress& other) const {
121 if (address_.len > other.address_.len) return 1;
122 if (address_.len < other.address_.len) return -1;
123 int retval = memcmp(address_.addr, other.address_.addr, address_.len);
124 if (retval != 0) return retval;
125 retval = QsortCompare(args_, other.args_);
126 if (retval != 0) return retval;
127 return CompareAttributes(attributes_, other.attributes_);
128 }
129
GetAttribute(const char * key) const130 const ServerAddress::AttributeInterface* ServerAddress::GetAttribute(
131 const char* key) const {
132 auto it = attributes_.find(key);
133 if (it == attributes_.end()) return nullptr;
134 return it->second.get();
135 }
136
137 // Returns a copy of the address with a modified attribute.
138 // If the new value is null, the attribute is removed.
WithAttribute(const char * key,std::unique_ptr<AttributeInterface> value) const139 ServerAddress ServerAddress::WithAttribute(
140 const char* key, std::unique_ptr<AttributeInterface> value) const {
141 ServerAddress address = *this;
142 if (value == nullptr) {
143 address.attributes_.erase(key);
144 } else {
145 address.attributes_[key] = std::move(value);
146 }
147 return address;
148 }
149
ToString() const150 std::string ServerAddress::ToString() const {
151 auto addr_str = grpc_sockaddr_to_string(&address_, false);
152 std::vector<std::string> parts = {
153 addr_str.ok() ? addr_str.value() : addr_str.status().ToString(),
154 };
155 if (args_ != ChannelArgs()) {
156 parts.emplace_back(absl::StrCat("args=", args_.ToString()));
157 }
158 if (!attributes_.empty()) {
159 std::vector<std::string> attrs;
160 attrs.reserve(attributes_.size());
161 for (const auto& p : attributes_) {
162 attrs.emplace_back(absl::StrCat(p.first, "=", p.second->ToString()));
163 }
164 parts.emplace_back(
165 absl::StrCat("attributes={", absl::StrJoin(attrs, ", "), "}"));
166 }
167 return absl::StrJoin(parts, " ");
168 }
169
ToString() const170 std::string ServerAddressWeightAttribute::ToString() const {
171 return absl::StrFormat("%d", weight_);
172 }
173
174 } // namespace grpc_core
175