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 <grpc/support/alloc.h>
27 #include <grpc/support/string_util.h>
28 
29 #include "src/core/ext/filters/client_channel/resolver_registry.h"
30 #include "src/core/ext/filters/client_channel/server_address.h"
31 #include "src/core/lib/channel/channel_args.h"
32 #include "src/core/lib/gpr/string.h"
33 #include "src/core/lib/iomgr/parse_address.h"
34 #include "src/core/lib/iomgr/resolve_address.h"
35 #include "src/core/lib/iomgr/unix_sockets_posix.h"
36 #include "src/core/lib/iomgr/work_serializer.h"
37 #include "src/core/lib/slice/slice_internal.h"
38 #include "src/core/lib/slice/slice_string_helpers.h"
39 
40 namespace grpc_core {
41 
42 namespace {
43 
44 class SockaddrResolver : public Resolver {
45  public:
46   SockaddrResolver(ServerAddressList addresses, ResolverArgs args);
47   ~SockaddrResolver() override;
48 
49   void StartLocked() override;
50 
ShutdownLocked()51   void ShutdownLocked() override {}
52 
53  private:
54   ServerAddressList addresses_;
55   const grpc_channel_args* channel_args_ = nullptr;
56 };
57 
SockaddrResolver(ServerAddressList addresses,ResolverArgs args)58 SockaddrResolver::SockaddrResolver(ServerAddressList addresses,
59                                    ResolverArgs args)
60     : Resolver(std::move(args.work_serializer), std::move(args.result_handler)),
61       addresses_(std::move(addresses)),
62       channel_args_(grpc_channel_args_copy(args.args)) {}
63 
~SockaddrResolver()64 SockaddrResolver::~SockaddrResolver() {
65   grpc_channel_args_destroy(channel_args_);
66 }
67 
StartLocked()68 void SockaddrResolver::StartLocked() {
69   Result result;
70   result.addresses = std::move(addresses_);
71   // TODO(roth): Use std::move() once channel args is converted to C++.
72   result.args = channel_args_;
73   channel_args_ = nullptr;
74   result_handler()->ReturnResult(std::move(result));
75 }
76 
77 //
78 // Factory
79 //
80 
DoNothing(void *)81 void DoNothing(void* /*ignored*/) {}
82 
ParseUri(const grpc_uri * uri,bool parse (const grpc_uri * uri,grpc_resolved_address * dst),ServerAddressList * addresses)83 bool ParseUri(const grpc_uri* uri,
84               bool parse(const grpc_uri* uri, grpc_resolved_address* dst),
85               ServerAddressList* addresses) {
86   if (0 != strcmp(uri->authority, "")) {
87     gpr_log(GPR_ERROR, "authority-based URIs not supported by the %s scheme",
88             uri->scheme);
89     return false;
90   }
91   // Construct addresses.
92   grpc_slice path_slice =
93       grpc_slice_new(uri->path, strlen(uri->path), DoNothing);
94   grpc_slice_buffer path_parts;
95   grpc_slice_buffer_init(&path_parts);
96   grpc_slice_split(path_slice, ",", &path_parts);
97   bool errors_found = false;
98   for (size_t i = 0; i < path_parts.count; i++) {
99     grpc_uri ith_uri = *uri;
100     grpc_core::UniquePtr<char> part_str(
101         grpc_slice_to_c_string(path_parts.slices[i]));
102     ith_uri.path = part_str.get();
103     grpc_resolved_address addr;
104     if (!parse(&ith_uri, &addr)) {
105       errors_found = true;
106       break;
107     }
108     if (addresses != nullptr) {
109       addresses->emplace_back(addr, nullptr /* args */);
110     }
111   }
112   grpc_slice_buffer_destroy_internal(&path_parts);
113   grpc_slice_unref_internal(path_slice);
114   return !errors_found;
115 }
116 
CreateSockaddrResolver(ResolverArgs args,bool parse (const grpc_uri * uri,grpc_resolved_address * dst))117 OrphanablePtr<Resolver> CreateSockaddrResolver(
118     ResolverArgs args,
119     bool parse(const grpc_uri* uri, grpc_resolved_address* dst)) {
120   ServerAddressList addresses;
121   if (!ParseUri(args.uri, parse, &addresses)) return nullptr;
122   // Instantiate resolver.
123   return MakeOrphanable<SockaddrResolver>(std::move(addresses),
124                                           std::move(args));
125 }
126 
127 class IPv4ResolverFactory : public ResolverFactory {
128  public:
IsValidUri(const grpc_uri * uri) const129   bool IsValidUri(const grpc_uri* uri) const override {
130     return ParseUri(uri, grpc_parse_ipv4, nullptr);
131   }
132 
CreateResolver(ResolverArgs args) const133   OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
134     return CreateSockaddrResolver(std::move(args), grpc_parse_ipv4);
135   }
136 
scheme() const137   const char* scheme() const override { return "ipv4"; }
138 };
139 
140 class IPv6ResolverFactory : public ResolverFactory {
141  public:
IsValidUri(const grpc_uri * uri) const142   bool IsValidUri(const grpc_uri* uri) const override {
143     return ParseUri(uri, grpc_parse_ipv6, nullptr);
144   }
145 
CreateResolver(ResolverArgs args) const146   OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
147     return CreateSockaddrResolver(std::move(args), grpc_parse_ipv6);
148   }
149 
scheme() const150   const char* scheme() const override { return "ipv6"; }
151 };
152 
153 #ifdef GRPC_HAVE_UNIX_SOCKET
154 class UnixResolverFactory : public ResolverFactory {
155  public:
IsValidUri(const grpc_uri * uri) const156   bool IsValidUri(const grpc_uri* uri) const override {
157     return ParseUri(uri, grpc_parse_unix, nullptr);
158   }
159 
CreateResolver(ResolverArgs args) const160   OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
161     return CreateSockaddrResolver(std::move(args), grpc_parse_unix);
162   }
163 
GetDefaultAuthority(grpc_uri *) const164   grpc_core::UniquePtr<char> GetDefaultAuthority(
165       grpc_uri* /*uri*/) const override {
166     return grpc_core::UniquePtr<char>(gpr_strdup("localhost"));
167   }
168 
scheme() const169   const char* scheme() const override { return "unix"; }
170 };
171 
172 class UnixAbstractResolverFactory : public ResolverFactory {
173  public:
IsValidUri(const grpc_uri * uri) const174   bool IsValidUri(const grpc_uri* uri) const override {
175     return ParseUri(uri, grpc_parse_unix_abstract, nullptr);
176   }
177 
CreateResolver(ResolverArgs args) const178   OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
179     return CreateSockaddrResolver(std::move(args), grpc_parse_unix_abstract);
180   }
181 
GetDefaultAuthority(grpc_uri *) const182   grpc_core::UniquePtr<char> GetDefaultAuthority(
183       grpc_uri* /*uri*/) const override {
184     return grpc_core::UniquePtr<char>(gpr_strdup("localhost"));
185   }
186 
scheme() const187   const char* scheme() const override { return "unix-abstract"; }
188 };
189 #endif  // GRPC_HAVE_UNIX_SOCKET
190 
191 }  // namespace
192 
193 }  // namespace grpc_core
194 
grpc_resolver_sockaddr_init()195 void grpc_resolver_sockaddr_init() {
196   grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
197       absl::make_unique<grpc_core::IPv4ResolverFactory>());
198   grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
199       absl::make_unique<grpc_core::IPv6ResolverFactory>());
200 #ifdef GRPC_HAVE_UNIX_SOCKET
201   grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
202       absl::make_unique<grpc_core::UnixResolverFactory>());
203   grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
204       absl::make_unique<grpc_core::UnixAbstractResolverFactory>());
205 #endif
206 }
207 
grpc_resolver_sockaddr_shutdown()208 void grpc_resolver_sockaddr_shutdown() {}
209