• 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 // Wraps the transport layer of RPC. Implementation may use plain sockets or TLS.
18 
19 #pragma once
20 
21 #include <functional>
22 #include <memory>
23 #include <optional>
24 #include <string>
25 #include <variant>
26 #include <vector>
27 
28 #include <android-base/function_ref.h>
29 #include <android-base/unique_fd.h>
30 #include <utils/Errors.h>
31 
32 #include <binder/RpcCertificateFormat.h>
33 #include <binder/RpcThreads.h>
34 
35 #include <sys/uio.h>
36 
37 namespace android {
38 
39 class FdTrigger;
40 struct RpcTransportFd;
41 
42 // Represents a socket connection.
43 // No thread-safety is guaranteed for these APIs.
44 class RpcTransport {
45 public:
46     virtual ~RpcTransport() = default;
47 
48     /**
49      * Poll the transport to check whether there is any data ready to read.
50      *
51      * Return:
52      *   OK - There is data available on this transport
53      *   WOULDBLOCK - No data is available
54      *   error - any other error
55      */
56     [[nodiscard]] virtual status_t pollRead(void) = 0;
57 
58     /**
59      * Read (or write), but allow to be interrupted by a trigger.
60      *
61      * iovs - array of iovecs to perform the operation on. The elements
62      * of the array may be modified by this method.
63      *
64      * altPoll - function to be called instead of polling, when needing to wait
65      * to read/write data. If this returns an error, that error is returned from
66      * this function.
67      *
68      * ancillaryFds - FDs to be sent via UNIX domain dockets or Trusty IPC. When
69      * reading, if `ancillaryFds` is null, any received FDs will be silently
70      * dropped and closed (by the OS). Appended values will always be unique_fd,
71      * the variant type is used to avoid extra copies elsewhere.
72      *
73      * Return:
74      *   OK - succeeded in completely processing 'size'
75      *   error - interrupted (failure or trigger)
76      */
77     [[nodiscard]] virtual status_t interruptableWriteFully(
78             FdTrigger *fdTrigger, iovec *iovs, int niovs,
79             const std::optional<android::base::function_ref<status_t()>> &altPoll,
80             const std::vector<std::variant<base::unique_fd, base::borrowed_fd>> *ancillaryFds) = 0;
81     [[nodiscard]] virtual status_t interruptableReadFully(
82             FdTrigger *fdTrigger, iovec *iovs, int niovs,
83             const std::optional<android::base::function_ref<status_t()>> &altPoll,
84             std::vector<std::variant<base::unique_fd, base::borrowed_fd>> *ancillaryFds) = 0;
85 
86     /**
87      *  Check whether any threads are blocked while polling the transport
88      *  for read operations
89      *  Return:
90      *    True - Specifies that there is active polling on transport.
91      *    False - No active polling on transport
92      */
93     [[nodiscard]] virtual bool isWaiting() = 0;
94 
95 protected:
96     RpcTransport() = default;
97 };
98 
99 // Represents the context that generates the socket connection.
100 // All APIs are thread-safe. See RpcTransportCtxRaw and RpcTransportCtxTls for details.
101 class RpcTransportCtx {
102 public:
103     virtual ~RpcTransportCtx() = default;
104 
105     // Create a new RpcTransport object.
106     //
107     // Implementation details: for TLS, this function may incur I/O. |fdTrigger| may be used
108     // to interrupt I/O. This function blocks until handshake is finished.
109     [[nodiscard]] virtual std::unique_ptr<RpcTransport> newTransport(
110             android::RpcTransportFd fd, FdTrigger *fdTrigger) const = 0;
111 
112     // Return the preconfigured certificate of this context.
113     //
114     // Implementation details:
115     // - For raw sockets, this always returns empty string.
116     // - For TLS, this returns the certificate. See RpcTransportTls for details.
117     [[nodiscard]] virtual std::vector<uint8_t> getCertificate(
118             RpcCertificateFormat format) const = 0;
119 
120 protected:
121     RpcTransportCtx() = default;
122 };
123 
124 // A factory class that generates RpcTransportCtx.
125 // All APIs are thread-safe.
126 class RpcTransportCtxFactory {
127 public:
128     virtual ~RpcTransportCtxFactory() = default;
129     // Creates server context.
130     [[nodiscard]] virtual std::unique_ptr<RpcTransportCtx> newServerCtx() const = 0;
131 
132     // Creates client context.
133     [[nodiscard]] virtual std::unique_ptr<RpcTransportCtx> newClientCtx() const = 0;
134 
135     // Return a short description of this transport (e.g. "raw"). For logging / debugging / testing
136     // only.
137     [[nodiscard]] virtual const char *toCString() const = 0;
138 
139 protected:
140     RpcTransportCtxFactory() = default;
141 };
142 
143 struct RpcTransportFd {
144 private:
145     mutable bool isPolling{false};
146 
setPollingStateRpcTransportFd147     void setPollingState(bool state) const { isPolling = state; }
148 
149 public:
150     base::unique_fd fd;
151 
152     RpcTransportFd() = default;
RpcTransportFdRpcTransportFd153     explicit RpcTransportFd(base::unique_fd &&descriptor)
154           : isPolling(false), fd(std::move(descriptor)) {}
155 
RpcTransportFdRpcTransportFd156     RpcTransportFd(RpcTransportFd &&transportFd) noexcept
157           : isPolling(transportFd.isPolling), fd(std::move(transportFd.fd)) {}
158 
159     RpcTransportFd &operator=(RpcTransportFd &&transportFd) noexcept {
160         fd = std::move(transportFd.fd);
161         isPolling = transportFd.isPolling;
162         return *this;
163     }
164 
165     RpcTransportFd &operator=(base::unique_fd &&descriptor) noexcept {
166         fd = std::move(descriptor);
167         isPolling = false;
168         return *this;
169     }
170 
isInPollingStateRpcTransportFd171     bool isInPollingState() const { return isPolling; }
172     friend class FdTrigger;
173 };
174 
175 } // namespace android
176