1 /*
2  *
3  * Copyright 2015-2016 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 <stdbool.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #include "absl/strings/str_split.h"
27 
28 #include <grpc/support/alloc.h>
29 #include <grpc/support/string_util.h>
30 
31 #include "src/core/ext/filters/client_channel/resolver_registry.h"
32 #include "src/core/ext/filters/client_channel/server_address.h"
33 #include "src/core/lib/address_utils/parse_address.h"
34 #include "src/core/lib/channel/channel_args.h"
35 #include "src/core/lib/gpr/string.h"
36 #include "src/core/lib/iomgr/resolve_address.h"
37 #include "src/core/lib/iomgr/unix_sockets_posix.h"
38 #include "src/core/lib/slice/slice_internal.h"
39 #include "src/core/lib/slice/slice_string_helpers.h"
40 
41 namespace grpc_core {
42 
43 namespace {
44 
45 class SockaddrResolver : public Resolver {
46  public:
47   SockaddrResolver(ServerAddressList addresses, ResolverArgs args);
48   ~SockaddrResolver() override;
49 
50   void StartLocked() override;
51 
ShutdownLocked()52   void ShutdownLocked() override {}
53 
54  private:
55   std::unique_ptr<ResultHandler> result_handler_;
56   ServerAddressList addresses_;
57   const grpc_channel_args* channel_args_ = nullptr;
58 };
59 
SockaddrResolver(ServerAddressList addresses,ResolverArgs args)60 SockaddrResolver::SockaddrResolver(ServerAddressList addresses,
61                                    ResolverArgs args)
62     : result_handler_(std::move(args.result_handler)),
63       addresses_(std::move(addresses)),
64       channel_args_(grpc_channel_args_copy(args.args)) {}
65 
~SockaddrResolver()66 SockaddrResolver::~SockaddrResolver() {
67   grpc_channel_args_destroy(channel_args_);
68 }
69 
StartLocked()70 void SockaddrResolver::StartLocked() {
71   Result result;
72   result.addresses = std::move(addresses_);
73   // TODO(roth): Use std::move() once channel args is converted to C++.
74   result.args = channel_args_;
75   channel_args_ = nullptr;
76   result_handler_->ReturnResult(std::move(result));
77 }
78 
79 //
80 // Factory
81 //
82 
ParseUri(const URI & uri,bool parse (const URI & uri,grpc_resolved_address * dst),ServerAddressList * addresses)83 bool ParseUri(const URI& uri,
84               bool parse(const URI& uri, grpc_resolved_address* dst),
85               ServerAddressList* addresses) {
86   if (!uri.authority().empty()) {
87     gpr_log(GPR_ERROR, "authority-based URIs not supported by the %s scheme",
88             uri.scheme().c_str());
89     return false;
90   }
91   // Construct addresses.
92   bool errors_found = false;
93   for (absl::string_view ith_path : absl::StrSplit(uri.path(), ',')) {
94     URI ith_uri(uri.scheme(), "", std::string(ith_path), {}, "");
95     grpc_resolved_address addr;
96     if (!parse(ith_uri, &addr)) {
97       errors_found = true;
98       break;
99     }
100     if (addresses != nullptr) {
101       addresses->emplace_back(addr, nullptr /* args */);
102     }
103   }
104   return !errors_found;
105 }
106 
CreateSockaddrResolver(ResolverArgs args,bool parse (const URI & uri,grpc_resolved_address * dst))107 OrphanablePtr<Resolver> CreateSockaddrResolver(
108     ResolverArgs args, bool parse(const URI& uri, grpc_resolved_address* dst)) {
109   ServerAddressList addresses;
110   if (!ParseUri(args.uri, parse, &addresses)) return nullptr;
111   // Instantiate resolver.
112   return MakeOrphanable<SockaddrResolver>(std::move(addresses),
113                                           std::move(args));
114 }
115 
116 class IPv4ResolverFactory : public ResolverFactory {
117  public:
IsValidUri(const URI & uri) const118   bool IsValidUri(const URI& uri) const override {
119     return ParseUri(uri, grpc_parse_ipv4, nullptr);
120   }
121 
CreateResolver(ResolverArgs args) const122   OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
123     return CreateSockaddrResolver(std::move(args), grpc_parse_ipv4);
124   }
125 
scheme() const126   const char* scheme() const override { return "ipv4"; }
127 };
128 
129 class IPv6ResolverFactory : public ResolverFactory {
130  public:
IsValidUri(const URI & uri) const131   bool IsValidUri(const URI& uri) const override {
132     return ParseUri(uri, grpc_parse_ipv6, nullptr);
133   }
134 
CreateResolver(ResolverArgs args) const135   OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
136     return CreateSockaddrResolver(std::move(args), grpc_parse_ipv6);
137   }
138 
scheme() const139   const char* scheme() const override { return "ipv6"; }
140 };
141 
142 #ifdef GRPC_HAVE_UNIX_SOCKET
143 class UnixResolverFactory : public ResolverFactory {
144  public:
IsValidUri(const URI & uri) const145   bool IsValidUri(const URI& uri) const override {
146     return ParseUri(uri, grpc_parse_unix, nullptr);
147   }
148 
CreateResolver(ResolverArgs args) const149   OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
150     return CreateSockaddrResolver(std::move(args), grpc_parse_unix);
151   }
152 
GetDefaultAuthority(const URI &) const153   std::string GetDefaultAuthority(const URI& /*uri*/) const override {
154     return "localhost";
155   }
156 
scheme() const157   const char* scheme() const override { return "unix"; }
158 };
159 
160 class UnixAbstractResolverFactory : public ResolverFactory {
161  public:
IsValidUri(const URI & uri) const162   bool IsValidUri(const URI& uri) const override {
163     return ParseUri(uri, grpc_parse_unix_abstract, nullptr);
164   }
165 
CreateResolver(ResolverArgs args) const166   OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
167     return CreateSockaddrResolver(std::move(args), grpc_parse_unix_abstract);
168   }
169 
GetDefaultAuthority(const URI &) const170   std::string GetDefaultAuthority(const URI& /*uri*/) const override {
171     return "localhost";
172   }
173 
scheme() const174   const char* scheme() const override { return "unix-abstract"; }
175 };
176 #endif  // GRPC_HAVE_UNIX_SOCKET
177 
178 }  // namespace
179 
180 }  // namespace grpc_core
181 
grpc_resolver_sockaddr_init()182 void grpc_resolver_sockaddr_init() {
183   grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
184       absl::make_unique<grpc_core::IPv4ResolverFactory>());
185   grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
186       absl::make_unique<grpc_core::IPv6ResolverFactory>());
187 #ifdef GRPC_HAVE_UNIX_SOCKET
188   grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
189       absl::make_unique<grpc_core::UnixResolverFactory>());
190   grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
191       absl::make_unique<grpc_core::UnixAbstractResolverFactory>());
192 #endif
193 }
194 
grpc_resolver_sockaddr_shutdown()195 void grpc_resolver_sockaddr_shutdown() {}
196