summaryrefslogtreecommitdiff
path: root/libs/binder/include/binder/RpcServer.h
diff options
context:
space:
mode:
Diffstat (limited to 'libs/binder/include/binder/RpcServer.h')
-rw-r--r--libs/binder/include/binder/RpcServer.h164
1 files changed, 164 insertions, 0 deletions
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
new file mode 100644
index 0000000000..8f0c6fd5e1
--- /dev/null
+++ b/libs/binder/include/binder/RpcServer.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <android-base/unique_fd.h>
+#include <binder/IBinder.h>
+#include <binder/RpcSession.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+#include <mutex>
+#include <thread>
+
+// WARNING: This is a feature which is still in development, and it is subject
+// to radical change. Any production use of this may subject your code to any
+// number of problems.
+
+namespace android {
+
+class RpcSocketAddress;
+
+/**
+ * This represents a server of an interface, which may be connected to by any
+ * number of clients over sockets.
+ *
+ * Usage:
+ * auto server = RpcServer::make();
+ * // only supports one now
+ * if (!server->setup*Server(...)) {
+ * :(
+ * }
+ * server->join();
+ */
+class RpcServer final : public virtual RefBase {
+public:
+ static sp<RpcServer> make();
+
+ /**
+ * This represents a session for responses, e.g.:
+ *
+ * process A serves binder a
+ * process B opens a session to process A
+ * process B makes binder b and sends it to A
+ * A uses this 'back session' to send things back to B
+ */
+ [[nodiscard]] bool setupUnixDomainServer(const char* path);
+
+ /**
+ * Creates an RPC server at the current port.
+ */
+ [[nodiscard]] bool setupVsockServer(unsigned int port);
+
+ /**
+ * Creates an RPC server at the current port using IPv4.
+ *
+ * TODO(b/182914638): IPv6 support
+ *
+ * Set |port| to 0 to pick an ephemeral port; see discussion of
+ * /proc/sys/net/ipv4/ip_local_port_range in ip(7). In this case, |assignedPort|
+ * will be set to the picked port number, if it is not null.
+ */
+ [[nodiscard]] bool setupInetServer(unsigned int port, unsigned int* assignedPort);
+
+ /**
+ * If setup*Server has been successful, return true. Otherwise return false.
+ */
+ [[nodiscard]] bool hasServer();
+
+ /**
+ * If hasServer(), return the server FD. Otherwise return invalid FD.
+ */
+ [[nodiscard]] base::unique_fd releaseServer();
+
+ /**
+ * Set up server using an external FD previously set up by releaseServer().
+ * Return false if there's already a server.
+ */
+ bool setupExternalServer(base::unique_fd serverFd);
+
+ void iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
+
+ /**
+ * This must be called before adding a client session.
+ *
+ * If this is not specified, this will be a single-threaded server.
+ *
+ * TODO(b/185167543): these are currently created per client, but these
+ * should be shared.
+ */
+ void setMaxThreads(size_t threads);
+ size_t getMaxThreads();
+
+ /**
+ * The root object can be retrieved by any client, without any
+ * authentication. TODO(b/183988761)
+ *
+ * Holds a strong reference to the root object.
+ */
+ void setRootObject(const sp<IBinder>& binder);
+ /**
+ * Holds a weak reference to the root object.
+ */
+ void setRootObjectWeak(const wp<IBinder>& binder);
+ sp<IBinder> getRootObject();
+
+ /**
+ * You must have at least one client session before calling this.
+ *
+ * TODO(b/185167543): way to shut down?
+ */
+ void join();
+
+ /**
+ * Accept one connection on this server. You must have at least one client
+ * session before calling this.
+ */
+ [[nodiscard]] bool acceptOne();
+
+ /**
+ * For debugging!
+ */
+ std::vector<sp<RpcSession>> listSessions();
+ size_t numUninitializedSessions();
+
+ ~RpcServer();
+
+ // internal use only
+
+ void onSessionTerminating(const sp<RpcSession>& session);
+
+private:
+ friend sp<RpcServer>;
+ RpcServer();
+
+ void establishConnection(sp<RpcServer>&& session, base::unique_fd clientFd);
+ bool setupSocketServer(const RpcSocketAddress& address);
+
+ bool mAgreedExperimental = false;
+ bool mStarted = false; // TODO(b/185167543): support dynamically added clients
+ size_t mMaxThreads = 1;
+ base::unique_fd mServer; // socket we are accepting sessions on
+
+ std::mutex mLock; // for below
+ std::map<std::thread::id, std::thread> mConnectingThreads;
+ sp<IBinder> mRootObject;
+ wp<IBinder> mRootObjectWeak;
+ std::map<int32_t, sp<RpcSession>> mSessions;
+ int32_t mSessionIdCounter = 0;
+};
+
+} // namespace android