1 /* 2 * Copyright (C) 2020 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 #pragma once 17 18 #include <android-base/unique_fd.h> 19 #include <binder/IBinder.h> 20 #include <binder/RpcSession.h> 21 #include <utils/Errors.h> 22 #include <utils/RefBase.h> 23 24 #include <mutex> 25 #include <thread> 26 27 // WARNING: This is a feature which is still in development, and it is subject 28 // to radical change. Any production use of this may subject your code to any 29 // number of problems. 30 31 namespace android { 32 33 class RpcSocketAddress; 34 35 /** 36 * This represents a server of an interface, which may be connected to by any 37 * number of clients over sockets. 38 * 39 * Usage: 40 * auto server = RpcServer::make(); 41 * // only supports one now 42 * if (!server->setup*Server(...)) { 43 * :( 44 * } 45 * server->join(); 46 */ 47 class RpcServer final : public virtual RefBase { 48 public: 49 static sp<RpcServer> make(); 50 51 /** 52 * This represents a session for responses, e.g.: 53 * 54 * process A serves binder a 55 * process B opens a session to process A 56 * process B makes binder b and sends it to A 57 * A uses this 'back session' to send things back to B 58 */ 59 [[nodiscard]] bool setupUnixDomainServer(const char* path); 60 61 /** 62 * Creates an RPC server at the current port. 63 */ 64 [[nodiscard]] bool setupVsockServer(unsigned int port); 65 66 /** 67 * Creates an RPC server at the current port using IPv4. 68 * 69 * TODO(b/182914638): IPv6 support 70 * 71 * Set |port| to 0 to pick an ephemeral port; see discussion of 72 * /proc/sys/net/ipv4/ip_local_port_range in ip(7). In this case, |assignedPort| 73 * will be set to the picked port number, if it is not null. 74 */ 75 [[nodiscard]] bool setupInetServer(unsigned int port, unsigned int* assignedPort); 76 77 /** 78 * If setup*Server has been successful, return true. Otherwise return false. 79 */ 80 [[nodiscard]] bool hasServer(); 81 82 /** 83 * If hasServer(), return the server FD. Otherwise return invalid FD. 84 */ 85 [[nodiscard]] base::unique_fd releaseServer(); 86 87 /** 88 * Set up server using an external FD previously set up by releaseServer(). 89 * Return false if there's already a server. 90 */ 91 bool setupExternalServer(base::unique_fd serverFd); 92 93 void iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); 94 95 /** 96 * This must be called before adding a client session. 97 * 98 * If this is not specified, this will be a single-threaded server. 99 * 100 * TODO(b/185167543): these are currently created per client, but these 101 * should be shared. 102 */ 103 void setMaxThreads(size_t threads); 104 size_t getMaxThreads(); 105 106 /** 107 * The root object can be retrieved by any client, without any 108 * authentication. TODO(b/183988761) 109 * 110 * Holds a strong reference to the root object. 111 */ 112 void setRootObject(const sp<IBinder>& binder); 113 /** 114 * Holds a weak reference to the root object. 115 */ 116 void setRootObjectWeak(const wp<IBinder>& binder); 117 sp<IBinder> getRootObject(); 118 119 /** 120 * You must have at least one client session before calling this. 121 * 122 * TODO(b/185167543): way to shut down? 123 */ 124 void join(); 125 126 /** 127 * Accept one connection on this server. You must have at least one client 128 * session before calling this. 129 */ 130 [[nodiscard]] bool acceptOne(); 131 132 /** 133 * For debugging! 134 */ 135 std::vector<sp<RpcSession>> listSessions(); 136 size_t numUninitializedSessions(); 137 138 ~RpcServer(); 139 140 // internal use only 141 142 void onSessionTerminating(const sp<RpcSession>& session); 143 144 private: 145 friend sp<RpcServer>; 146 RpcServer(); 147 148 void establishConnection(sp<RpcServer>&& session, base::unique_fd clientFd); 149 bool setupSocketServer(const RpcSocketAddress& address); 150 151 bool mAgreedExperimental = false; 152 bool mStarted = false; // TODO(b/185167543): support dynamically added clients 153 size_t mMaxThreads = 1; 154 base::unique_fd mServer; // socket we are accepting sessions on 155 156 std::mutex mLock; // for below 157 std::map<std::thread::id, std::thread> mConnectingThreads; 158 sp<IBinder> mRootObject; 159 wp<IBinder> mRootObjectWeak; 160 std::map<int32_t, sp<RpcSession>> mSessions; 161 int32_t mSessionIdCounter = 0; 162 }; 163 164 } // namespace android 165