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 "src/core/ext/transport/binder/server/binder_server.h"
18 
19 #ifndef GRPC_NO_BINDER
20 
21 #include <memory>
22 #include <string>
23 #include <utility>
24 
25 #include "absl/memory/memory.h"
26 
27 #include <grpc/grpc.h>
28 
29 #include "src/core/ext/transport/binder/transport/binder_transport.h"
30 #include "src/core/ext/transport/binder/utils/ndk_binder.h"
31 #include "src/core/ext/transport/binder/wire_format/binder_android.h"
32 #include "src/core/lib/iomgr/exec_ctx.h"
33 #include "src/core/lib/surface/server.h"
34 #include "src/core/lib/transport/error_utils.h"
35 
36 #ifdef GPR_SUPPORT_BINDER_TRANSPORT
37 
38 #include <jni.h>
39 
40 extern "C" {
41 
42 // This will be invoked from
43 // src/core/ext/transport/binder/java/io/grpc/binder/cpp/GrpcCppServerBuilder.java
44 JNIEXPORT jobject JNICALL
Java_io_grpc_binder_cpp_GrpcCppServerBuilder_GetEndpointBinderInternal__Ljava_lang_String_2(JNIEnv * jni_env,jobject,jstring conn_id_jstring)45 Java_io_grpc_binder_cpp_GrpcCppServerBuilder_GetEndpointBinderInternal__Ljava_lang_String_2(
46     JNIEnv* jni_env, jobject, jstring conn_id_jstring) {
47   grpc_binder::ndk_util::AIBinder* ai_binder = nullptr;
48 
49   {
50     // This block is the scope of conn_id c-string
51     jboolean isCopy;
52     const char* conn_id = jni_env->GetStringUTFChars(conn_id_jstring, &isCopy);
53     ai_binder = static_cast<grpc_binder::ndk_util::AIBinder*>(
54         grpc_get_endpoint_binder(std::string(conn_id)));
55     if (ai_binder == nullptr) {
56       gpr_log(GPR_ERROR, "Cannot find endpoint binder with connection id = %s",
57               conn_id);
58     }
59     if (isCopy == JNI_TRUE) {
60       jni_env->ReleaseStringUTFChars(conn_id_jstring, conn_id);
61     }
62   }
63 
64   if (ai_binder == nullptr) {
65     return nullptr;
66   }
67 
68   return grpc_binder::ndk_util::AIBinder_toJavaBinder(jni_env, ai_binder);
69 }
70 }
71 
72 #endif
73 
74 namespace grpc {
75 namespace experimental {
76 namespace binder {
77 
GetEndpointBinder(const std::string & service)78 void* GetEndpointBinder(const std::string& service) {
79   return grpc_get_endpoint_binder(service);
80 }
81 
AddEndpointBinder(const std::string & service,void * endpoint_binder)82 void AddEndpointBinder(const std::string& service, void* endpoint_binder) {
83   grpc_add_endpoint_binder(service, endpoint_binder);
84 }
85 
RemoveEndpointBinder(const std::string & service)86 void RemoveEndpointBinder(const std::string& service) {
87   grpc_remove_endpoint_binder(service);
88 }
89 
90 }  // namespace binder
91 }  // namespace experimental
92 }  // namespace grpc
93 
94 static absl::flat_hash_map<std::string, void*>* g_endpoint_binder_pool =
95     nullptr;
96 
97 namespace {
98 
GetBinderPoolMutex()99 grpc_core::Mutex* GetBinderPoolMutex() {
100   static grpc_core::Mutex* mu = new grpc_core::Mutex();
101   return mu;
102 }
103 
104 }  // namespace
105 
grpc_add_endpoint_binder(const std::string & service,void * endpoint_binder)106 void grpc_add_endpoint_binder(const std::string& service,
107                               void* endpoint_binder) {
108   grpc_core::MutexLock lock(GetBinderPoolMutex());
109   if (g_endpoint_binder_pool == nullptr) {
110     g_endpoint_binder_pool = new absl::flat_hash_map<std::string, void*>();
111   }
112   (*g_endpoint_binder_pool)[service] = endpoint_binder;
113 }
114 
grpc_remove_endpoint_binder(const std::string & service)115 void grpc_remove_endpoint_binder(const std::string& service) {
116   grpc_core::MutexLock lock(GetBinderPoolMutex());
117   if (g_endpoint_binder_pool == nullptr) {
118     return;
119   }
120   g_endpoint_binder_pool->erase(service);
121 }
122 
grpc_get_endpoint_binder(const std::string & service)123 void* grpc_get_endpoint_binder(const std::string& service) {
124   grpc_core::MutexLock lock(GetBinderPoolMutex());
125   if (g_endpoint_binder_pool == nullptr) {
126     return nullptr;
127   }
128   auto iter = g_endpoint_binder_pool->find(service);
129   return iter == g_endpoint_binder_pool->end() ? nullptr : iter->second;
130 }
131 
132 namespace grpc_core {
133 
134 class BinderServerListener : public Server::ListenerInterface {
135  public:
BinderServerListener(Server * server,std::string addr,BinderTxReceiverFactory factory,std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy)136   BinderServerListener(
137       Server* server, std::string addr, BinderTxReceiverFactory factory,
138       std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
139           security_policy)
140       : server_(server),
141         addr_(std::move(addr)),
142         factory_(std::move(factory)),
143         security_policy_(security_policy) {}
144 
Start(Server *,const std::vector<grpc_pollset * > *)145   void Start(Server* /*server*/,
146              const std::vector<grpc_pollset*>* /*pollsets*/) override {
147     tx_receiver_ = factory_(
148         [this](transaction_code_t code, grpc_binder::ReadableParcel* parcel,
149                int uid) { return OnSetupTransport(code, parcel, uid); });
150     endpoint_binder_ = tx_receiver_->GetRawBinder();
151     grpc_add_endpoint_binder(addr_, endpoint_binder_);
152   }
153 
channelz_listen_socket_node() const154   channelz::ListenSocketNode* channelz_listen_socket_node() const override {
155     return nullptr;
156   }
157 
SetOnDestroyDone(grpc_closure * on_destroy_done)158   void SetOnDestroyDone(grpc_closure* on_destroy_done) override {
159     on_destroy_done_ = on_destroy_done;
160   }
161 
Orphan()162   void Orphan() override { delete this; }
163 
~BinderServerListener()164   ~BinderServerListener() override {
165     ExecCtx::Get()->Flush();
166     if (on_destroy_done_) {
167       ExecCtx::Run(DEBUG_LOCATION, on_destroy_done_, absl::OkStatus());
168       ExecCtx::Get()->Flush();
169     }
170     grpc_remove_endpoint_binder(addr_);
171   }
172 
173  private:
OnSetupTransport(transaction_code_t code,grpc_binder::ReadableParcel * parcel,int uid)174   absl::Status OnSetupTransport(transaction_code_t code,
175                                 grpc_binder::ReadableParcel* parcel, int uid) {
176     ExecCtx exec_ctx;
177     if (static_cast<grpc_binder::BinderTransportTxCode>(code) !=
178         grpc_binder::BinderTransportTxCode::SETUP_TRANSPORT) {
179       return absl::InvalidArgumentError("Not a SETUP_TRANSPORT request");
180     }
181 
182     gpr_log(GPR_INFO, "BinderServerListener calling uid = %d", uid);
183     if (!security_policy_->IsAuthorized(uid)) {
184       // TODO(mingcl): For now we just ignore this unauthorized
185       // SETUP_TRANSPORT transaction and ghost the client. Check if we should
186       // send back a SHUTDOWN_TRANSPORT in this case.
187       return absl::PermissionDeniedError(
188           "UID " + std::to_string(uid) +
189           " is not allowed to connect to this "
190           "server according to security policy.");
191     }
192 
193     int version;
194     absl::Status status = parcel->ReadInt32(&version);
195     if (!status.ok()) {
196       return status;
197     }
198     gpr_log(GPR_INFO, "BinderTransport client protocol version = %d", version);
199     // TODO(mingcl): Make sure we only give client a version that is not newer
200     // than the version they specify. For now, we always tell client that we
201     // only support version=1.
202     std::unique_ptr<grpc_binder::Binder> client_binder{};
203     status = parcel->ReadBinder(&client_binder);
204     if (!status.ok()) {
205       return status;
206     }
207     if (!client_binder) {
208       return absl::InvalidArgumentError("NULL binder read from the parcel");
209     }
210     client_binder->Initialize();
211     // Finish the second half of SETUP_TRANSPORT in
212     // grpc_create_binder_transport_server().
213     grpc_transport* server_transport = grpc_create_binder_transport_server(
214         std::move(client_binder), security_policy_);
215     GPR_ASSERT(server_transport);
216     grpc_error_handle error = server_->SetupTransport(
217         server_transport, nullptr, server_->channel_args(), nullptr);
218     return grpc_error_to_absl_status(error);
219   }
220 
221   Server* server_;
222   grpc_closure* on_destroy_done_ = nullptr;
223   std::string addr_;
224   BinderTxReceiverFactory factory_;
225   std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy_;
226   void* endpoint_binder_ = nullptr;
227   std::unique_ptr<grpc_binder::TransactionReceiver> tx_receiver_;
228 };
229 
AddBinderPort(const std::string & addr,grpc_server * server,BinderTxReceiverFactory factory,std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy)230 bool AddBinderPort(const std::string& addr, grpc_server* server,
231                    BinderTxReceiverFactory factory,
232                    std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
233                        security_policy) {
234   // TODO(mingcl): Check if the addr is valid here after binder address resolver
235   // related code are merged.
236   const std::string kBinderUriScheme = "binder:";
237   if (addr.compare(0, kBinderUriScheme.size(), kBinderUriScheme) != 0) {
238     return false;
239   }
240   std::string conn_id = addr.substr(kBinderUriScheme.size());
241   Server* core_server = Server::FromC(server);
242   core_server->AddListener(
243       OrphanablePtr<Server::ListenerInterface>(new BinderServerListener(
244           core_server, conn_id, std::move(factory), security_policy)));
245   return true;
246 }
247 
248 }  // namespace grpc_core
249 #endif
250