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