• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <grpc/support/port_platform.h>
16 
17 #include <algorithm>
18 
19 #include "absl/status/status.h"
20 
21 #include "src/core/lib/gprpp/status_helper.h"
22 #include "src/core/lib/iomgr/port.h"  // IWYU pragma: keep
23 
24 #ifdef GRPC_HAVE_UNIX_SOCKET
25 
26 #include <string.h>
27 #ifdef GPR_WINDOWS
28 // clang-format off
29 #include <ws2def.h>
30 #include <afunix.h>
31 // clang-format on
32 #else
33 #include <sys/socket.h>
34 #include <sys/un.h>
35 #endif // GPR_WINDOWS
36 
37 #include <memory>
38 #include <utility>
39 
40 #include "absl/status/statusor.h"
41 #include "absl/strings/str_cat.h"
42 #include "absl/strings/string_view.h"
43 #include "absl/strings/strip.h"
44 
45 #include <grpc/support/log.h>
46 
47 #include "src/core/lib/channel/channel_args.h"
48 #include "src/core/lib/config/core_configuration.h"
49 #include "src/core/lib/gprpp/orphanable.h"
50 #include "src/core/lib/iomgr/error.h"
51 #include "src/core/lib/iomgr/resolved_address.h"
52 #include "src/core/resolver/endpoint_addresses.h"
53 #include "src/core/resolver/resolver.h"
54 #include "src/core/resolver/resolver_factory.h"
55 #include "src/core/lib/uri/uri_parser.h"
56 
57 namespace grpc_core {
58 namespace {
59 
60 class BinderResolver final : public Resolver {
61  public:
BinderResolver(EndpointAddressesList addresses,ResolverArgs args)62   BinderResolver(EndpointAddressesList addresses, ResolverArgs args)
63       : result_handler_(std::move(args.result_handler)),
64         addresses_(std::move(addresses)),
65         channel_args_(std::move(args.args)) {}
66 
StartLocked()67   void StartLocked() override {
68     Result result;
69     result.addresses = std::move(addresses_);
70     result.args = channel_args_;
71     channel_args_ = ChannelArgs();
72     result_handler_->ReportResult(std::move(result));
73   }
74 
ShutdownLocked()75   void ShutdownLocked() override {}
76 
77  private:
78   std::unique_ptr<ResultHandler> result_handler_;
79   EndpointAddressesList addresses_;
80   ChannelArgs channel_args_;
81 };
82 
83 class BinderResolverFactory final : public ResolverFactory {
84  public:
scheme() const85   absl::string_view scheme() const override { return "binder"; }
86 
IsValidUri(const URI & uri) const87   bool IsValidUri(const URI& uri) const override {
88     return ParseUri(uri, nullptr);
89   }
90 
CreateResolver(ResolverArgs args) const91   OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
92     EndpointAddressesList addresses;
93     if (!ParseUri(args.uri, &addresses)) return nullptr;
94     return MakeOrphanable<BinderResolver>(std::move(addresses),
95                                           std::move(args));
96   }
97 
98  private:
BinderAddrPopulate(absl::string_view path,grpc_resolved_address * resolved_addr)99   static grpc_error_handle BinderAddrPopulate(
100       absl::string_view path, grpc_resolved_address* resolved_addr) {
101     path = absl::StripPrefix(path, "/");
102     if (path.empty()) {
103       return GRPC_ERROR_CREATE("path is empty");
104     }
105     // Store parsed path in a unix socket so it can be reinterpreted as
106     // sockaddr. An invalid address family (AF_MAX) is set to make sure it won't
107     // be accidentally used.
108     memset(resolved_addr, 0, sizeof(*resolved_addr));
109     struct sockaddr_un* un =
110         reinterpret_cast<struct sockaddr_un*>(resolved_addr->addr);
111     un->sun_family = AF_MAX;
112     static_assert(sizeof(un->sun_path) >= 101,
113                   "unix socket path size is unexpectedly short");
114     if (path.size() + 1 > sizeof(un->sun_path)) {
115       return GRPC_ERROR_CREATE(
116           absl::StrCat(path, " is too long to be handled"));
117     }
118     // `un` has already be set to zero, no need to append null after the string
119     memcpy(un->sun_path, path.data(), path.size());
120     resolved_addr->len =
121         static_cast<socklen_t>(sizeof(un->sun_family) + path.size() + 1);
122     return absl::OkStatus();
123   }
124 
ParseUri(const URI & uri,EndpointAddressesList * addresses)125   static bool ParseUri(const URI& uri, EndpointAddressesList* addresses) {
126     grpc_resolved_address addr;
127     {
128       if (!uri.authority().empty()) {
129         gpr_log(GPR_ERROR, "authority is not supported in binder scheme");
130         return false;
131       }
132       grpc_error_handle error = BinderAddrPopulate(uri.path(), &addr);
133       if (!error.ok()) {
134         gpr_log(GPR_ERROR, "%s", StatusToString(error).c_str());
135         return false;
136       }
137     }
138     if (addresses != nullptr) {
139       addresses->emplace_back(addr, ChannelArgs());
140     }
141     return true;
142   }
143 };
144 
145 }  // namespace
146 
RegisterBinderResolver(CoreConfiguration::Builder * builder)147 void RegisterBinderResolver(CoreConfiguration::Builder* builder) {
148   builder->resolver_registry()->RegisterResolverFactory(
149       std::make_unique<BinderResolverFactory>());
150 }
151 
152 }  // namespace grpc_core
153 
154 #endif
155