2 * Copyright 2014 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <folly/SocketAddress.h>
20 #include <folly/io/async/DelayedDestruction.h>
21 #include <folly/io/async/EventBase.h>
26 * flags given by the application for write* calls
28 enum class WriteFlags : uint32_t {
31 * Whether to delay the output until a subsequent non-corked write.
32 * (Note: may not be supported in all subclasses or on all platforms.)
36 * for a socket that has ACK latency enabled, it will cause the kernel
37 * to fire a TCP ESTATS event when the last byte of the given write call
38 * will be acknowledged.
46 inline WriteFlags operator|(WriteFlags a, WriteFlags b) {
47 return static_cast<WriteFlags>(
48 static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
52 * intersection operator
54 inline WriteFlags operator&(WriteFlags a, WriteFlags b) {
55 return static_cast<WriteFlags>(
56 static_cast<uint32_t>(a) & static_cast<uint32_t>(b));
62 inline WriteFlags operator~(WriteFlags a) {
63 return static_cast<WriteFlags>(~static_cast<uint32_t>(a));
69 inline WriteFlags unSet(WriteFlags a, WriteFlags b) {
76 inline bool isSet(WriteFlags a, WriteFlags b) {
82 * AsyncTransport defines an asynchronous API for streaming I/O.
84 * This class provides an API to for asynchronously waiting for data
85 * on a streaming transport, and for asynchronously sending data.
87 * The APIs for reading and writing are intentionally asymmetric. Waiting for
88 * data to read is a persistent API: a callback is installed, and is notified
89 * whenever new data is available. It continues to be notified of new events
90 * until it is uninstalled.
92 * AsyncTransport does not provide read timeout functionality, because it
93 * typically cannot determine when the timeout should be active. Generally, a
94 * timeout should only be enabled when processing is blocked waiting on data
95 * from the remote endpoint. For server-side applications, the timeout should
96 * not be active if the server is currently processing one or more outstanding
97 * requests on this transport. For client-side applications, the timeout
98 * should not be active if there are no requests pending on the transport.
99 * Additionally, if a client has multiple pending requests, it will ususally
100 * want a separate timeout for each request, rather than a single read timeout.
102 * The write API is fairly intuitive: a user can request to send a block of
103 * data, and a callback will be informed once the entire block has been
104 * transferred to the kernel, or on error. AsyncTransport does provide a send
105 * timeout, since most callers want to give up if the remote end stops
106 * responding and no further progress can be made sending the data.
108 class AsyncTransport : public DelayedDestruction {
110 typedef std::unique_ptr<AsyncTransport, Destructor> UniquePtr;
113 * Close the transport.
115 * This gracefully closes the transport, waiting for all pending write
116 * requests to complete before actually closing the underlying transport.
118 * If a read callback is set, readEOF() will be called immediately. If there
119 * are outstanding write requests, the close will be delayed until all
120 * remaining writes have completed. No new writes may be started after
121 * close() has been called.
123 virtual void close() = 0;
126 * Close the transport immediately.
128 * This closes the transport immediately, dropping any outstanding data
129 * waiting to be written.
131 * If a read callback is set, readEOF() will be called immediately.
132 * If there are outstanding write requests, these requests will be aborted
133 * and writeError() will be invoked immediately on all outstanding write
136 virtual void closeNow() = 0;
139 * Reset the transport immediately.
141 * This closes the transport immediately, sending a reset to the remote peer
142 * if possible to indicate abnormal shutdown.
144 * Note that not all subclasses implement this reset functionality: some
145 * subclasses may treat reset() the same as closeNow(). Subclasses that use
146 * TCP transports should terminate the connection with a TCP reset.
148 virtual void closeWithReset() {
153 * Perform a half-shutdown of the write side of the transport.
155 * The caller should not make any more calls to write() or writev() after
156 * shutdownWrite() is called. Any future write attempts will fail
159 * Not all transport types support half-shutdown. If the underlying
160 * transport does not support half-shutdown, it will fully shutdown both the
161 * read and write sides of the transport. (Fully shutting down the socket is
162 * better than doing nothing at all, since the caller may rely on the
163 * shutdownWrite() call to notify the other end of the connection that no
164 * more data can be read.)
166 * If there is pending data still waiting to be written on the transport,
167 * the actual shutdown will be delayed until the pending data has been
170 * Note: There is no corresponding shutdownRead() equivalent. Simply
171 * uninstall the read callback if you wish to stop reading. (On TCP sockets
172 * at least, shutting down the read side of the socket is a no-op anyway.)
174 virtual void shutdownWrite() = 0;
177 * Perform a half-shutdown of the write side of the transport.
179 * shutdownWriteNow() is identical to shutdownWrite(), except that it
180 * immediately performs the shutdown, rather than waiting for pending writes
181 * to complete. Any pending write requests will be immediately failed when
182 * shutdownWriteNow() is called.
184 virtual void shutdownWriteNow() = 0;
187 * Determine if transport is open and ready to read or write.
189 * Note that this function returns false on EOF; you must also call error()
190 * to distinguish between an EOF and an error.
192 * @return true iff the transport is open and ready, false otherwise.
194 virtual bool good() const = 0;
197 * Determine if the transport is readable or not.
199 * @return true iff the transport is readable, false otherwise.
201 virtual bool readable() const = 0;
204 * Determine if the there is pending data on the transport.
206 * @return true iff the if the there is pending data, false otherwise.
208 virtual bool isPending() const {
212 * Determine if transport is connected to the endpoint
214 * @return false iff the transport is connected, otherwise true
216 virtual bool connecting() const = 0;
219 * Determine if an error has occurred with this transport.
221 * @return true iff an error has occurred (not EOF).
223 virtual bool error() const = 0;
226 * Attach the transport to a EventBase.
228 * This may only be called if the transport is not currently attached to a
229 * EventBase (by an earlier call to detachEventBase()).
231 * This method must be invoked in the EventBase's thread.
233 virtual void attachEventBase(EventBase* eventBase) = 0;
236 * Detach the transport from its EventBase.
238 * This may only be called when the transport is idle and has no reads or
239 * writes pending. Once detached, the transport may not be used again until
240 * it is re-attached to a EventBase by calling attachEventBase().
242 * This method must be called from the current EventBase's thread.
244 virtual void detachEventBase() = 0;
247 * Determine if the transport can be detached.
249 * This method must be called from the current EventBase's thread.
251 virtual bool isDetachable() const = 0;
254 * Get the EventBase used by this transport.
256 * Returns nullptr if this transport is not currently attached to a
259 virtual EventBase* getEventBase() const = 0;
262 * Set the send timeout.
264 * If write requests do not make any progress for more than the specified
265 * number of milliseconds, fail all pending writes and close the transport.
267 * If write requests are currently pending when setSendTimeout() is called,
268 * the timeout interval is immediately restarted using the new value.
270 * @param milliseconds The timeout duration, in milliseconds. If 0, no
271 * timeout will be used.
273 virtual void setSendTimeout(uint32_t milliseconds) = 0;
276 * Get the send timeout.
278 * @return Returns the current send timeout, in milliseconds. A return value
279 * of 0 indicates that no timeout is set.
281 virtual uint32_t getSendTimeout() const = 0;
284 * Get the address of the local endpoint of this transport.
286 * This function may throw AsyncSocketException on error.
288 * @param address The local address will be stored in the specified
291 virtual void getLocalAddress(folly::SocketAddress* address) const = 0;
294 * Get the address of the remote endpoint to which this transport is
297 * This function may throw AsyncSocketException on error.
299 * @param address The remote endpoint's address will be stored in the
300 * specified SocketAddress.
302 virtual void getPeerAddress(folly::SocketAddress* address) const = 0;
305 * @return True iff end of record tracking is enabled
307 virtual bool isEorTrackingEnabled() const = 0;
309 virtual void setEorTracking(bool track) = 0;
311 virtual size_t getAppBytesWritten() const = 0;
312 virtual size_t getRawBytesWritten() const = 0;
313 virtual size_t getAppBytesReceived() const = 0;
314 virtual size_t getRawBytesReceived() const = 0;
317 virtual ~AsyncTransport() {}