• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <android-base/logging.h>
18 #include <android-base/unique_fd.h>
19 #include <android/binder_libbinder.h>
20 #include <binder/RpcServer.h>
21 #include <binder/RpcSession.h>
22 #include <linux/vm_sockets.h>
23 
24 using android::OK;
25 using android::RpcServer;
26 using android::RpcSession;
27 using android::status_t;
28 using android::statusToString;
29 using android::base::unique_fd;
30 
31 extern "C" {
32 
RunRpcServerWithFactory(AIBinder * (* factory)(unsigned int cid,void * context),void * factoryContext,unsigned int port)33 bool RunRpcServerWithFactory(AIBinder* (*factory)(unsigned int cid, void* context),
34                              void* factoryContext, unsigned int port) {
35     auto server = RpcServer::make();
36     if (status_t status = server->setupVsockServer(port); status != OK) {
37         LOG(ERROR) << "Failed to set up vsock server with port " << port
38                    << " error: " << statusToString(status).c_str();
39         return false;
40     }
41     server->setPerSessionRootObject([=](const sockaddr* addr, socklen_t addrlen) {
42         LOG_ALWAYS_FATAL_IF(addr->sa_family != AF_VSOCK, "address is not a vsock");
43         LOG_ALWAYS_FATAL_IF(addrlen < sizeof(sockaddr_vm), "sockaddr is truncated");
44         const sockaddr_vm* vaddr = reinterpret_cast<const sockaddr_vm*>(addr);
45         return AIBinder_toPlatformBinder(factory(vaddr->svm_cid, factoryContext));
46     });
47 
48     server->join();
49 
50     // Shutdown any open sessions since server failed.
51     (void)server->shutdown();
52     return true;
53 }
54 
RunRpcServerCallback(AIBinder * service,unsigned int port,void (* readyCallback)(void * param),void * param)55 bool RunRpcServerCallback(AIBinder* service, unsigned int port, void (*readyCallback)(void* param),
56                           void* param) {
57     auto server = RpcServer::make();
58     if (status_t status = server->setupVsockServer(port); status != OK) {
59         LOG(ERROR) << "Failed to set up vsock server with port " << port
60                    << " error: " << statusToString(status).c_str();
61         return false;
62     }
63     server->setRootObject(AIBinder_toPlatformBinder(service));
64 
65     if (readyCallback) readyCallback(param);
66     server->join();
67 
68     // Shutdown any open sessions since server failed.
69     (void)server->shutdown();
70     return true;
71 }
72 
RunRpcServer(AIBinder * service,unsigned int port)73 bool RunRpcServer(AIBinder* service, unsigned int port) {
74     return RunRpcServerCallback(service, port, nullptr, nullptr);
75 }
76 
RpcClient(unsigned int cid,unsigned int port)77 AIBinder* RpcClient(unsigned int cid, unsigned int port) {
78     auto session = RpcSession::make();
79     if (status_t status = session->setupVsockClient(cid, port); status != OK) {
80         LOG(ERROR) << "Failed to set up vsock client with CID " << cid << " and port " << port
81                    << " error: " << statusToString(status).c_str();
82         return nullptr;
83     }
84     return AIBinder_fromPlatformBinder(session->getRootObject());
85 }
86 
RpcPreconnectedClient(int (* requestFd)(void * param),void * param)87 AIBinder* RpcPreconnectedClient(int (*requestFd)(void* param), void* param) {
88     auto session = RpcSession::make();
89     auto request = [=] { return unique_fd{requestFd(param)}; };
90     if (status_t status = session->setupPreconnectedClient(unique_fd{}, request); status != OK) {
91         LOG(ERROR) << "Failed to set up vsock client. error: " << statusToString(status).c_str();
92         return nullptr;
93     }
94     return AIBinder_fromPlatformBinder(session->getRootObject());
95 }
96 }
97