2 * Copyright 2015 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.
22 #include <folly/io/async/DelayedDestruction.h>
23 #include <folly/io/async/EventBase.h>
24 #include <folly/io/async/AsyncSocketBase.h>
28 class AsyncSocketException;
34 * flags given by the application for write* calls
36 enum class WriteFlags : uint32_t {
39 * Whether to delay the output until a subsequent non-corked write.
40 * (Note: may not be supported in all subclasses or on all platforms.)
44 * for a socket that has ACK latency enabled, it will cause the kernel
45 * to fire a TCP ESTATS event when the last byte of the given write call
46 * will be acknowledged.
54 inline WriteFlags operator|(WriteFlags a, WriteFlags b) {
55 return static_cast<WriteFlags>(
56 static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
60 * intersection operator
62 inline WriteFlags operator&(WriteFlags a, WriteFlags b) {
63 return static_cast<WriteFlags>(
64 static_cast<uint32_t>(a) & static_cast<uint32_t>(b));
70 inline WriteFlags operator~(WriteFlags a) {
71 return static_cast<WriteFlags>(~static_cast<uint32_t>(a));
77 inline WriteFlags unSet(WriteFlags a, WriteFlags b) {
84 inline bool isSet(WriteFlags a, WriteFlags b) {
90 * AsyncTransport defines an asynchronous API for streaming I/O.
92 * This class provides an API to for asynchronously waiting for data
93 * on a streaming transport, and for asynchronously sending data.
95 * The APIs for reading and writing are intentionally asymmetric. Waiting for
96 * data to read is a persistent API: a callback is installed, and is notified
97 * whenever new data is available. It continues to be notified of new events
98 * until it is uninstalled.
100 * AsyncTransport does not provide read timeout functionality, because it
101 * typically cannot determine when the timeout should be active. Generally, a
102 * timeout should only be enabled when processing is blocked waiting on data
103 * from the remote endpoint. For server-side applications, the timeout should
104 * not be active if the server is currently processing one or more outstanding
105 * requests on this transport. For client-side applications, the timeout
106 * should not be active if there are no requests pending on the transport.
107 * Additionally, if a client has multiple pending requests, it will ususally
108 * want a separate timeout for each request, rather than a single read timeout.
110 * The write API is fairly intuitive: a user can request to send a block of
111 * data, and a callback will be informed once the entire block has been
112 * transferred to the kernel, or on error. AsyncTransport does provide a send
113 * timeout, since most callers want to give up if the remote end stops
114 * responding and no further progress can be made sending the data.
116 class AsyncTransport : public DelayedDestruction, public AsyncSocketBase {
118 typedef std::unique_ptr<AsyncTransport, Destructor> UniquePtr;
121 * Close the transport.
123 * This gracefully closes the transport, waiting for all pending write
124 * requests to complete before actually closing the underlying transport.
126 * If a read callback is set, readEOF() will be called immediately. If there
127 * are outstanding write requests, the close will be delayed until all
128 * remaining writes have completed. No new writes may be started after
129 * close() has been called.
131 virtual void close() = 0;
134 * Close the transport immediately.
136 * This closes the transport immediately, dropping any outstanding data
137 * waiting to be written.
139 * If a read callback is set, readEOF() will be called immediately.
140 * If there are outstanding write requests, these requests will be aborted
141 * and writeError() will be invoked immediately on all outstanding write
144 virtual void closeNow() = 0;
147 * Reset the transport immediately.
149 * This closes the transport immediately, sending a reset to the remote peer
150 * if possible to indicate abnormal shutdown.
152 * Note that not all subclasses implement this reset functionality: some
153 * subclasses may treat reset() the same as closeNow(). Subclasses that use
154 * TCP transports should terminate the connection with a TCP reset.
156 virtual void closeWithReset() {
161 * Perform a half-shutdown of the write side of the transport.
163 * The caller should not make any more calls to write() or writev() after
164 * shutdownWrite() is called. Any future write attempts will fail
167 * Not all transport types support half-shutdown. If the underlying
168 * transport does not support half-shutdown, it will fully shutdown both the
169 * read and write sides of the transport. (Fully shutting down the socket is
170 * better than doing nothing at all, since the caller may rely on the
171 * shutdownWrite() call to notify the other end of the connection that no
172 * more data can be read.)
174 * If there is pending data still waiting to be written on the transport,
175 * the actual shutdown will be delayed until the pending data has been
178 * Note: There is no corresponding shutdownRead() equivalent. Simply
179 * uninstall the read callback if you wish to stop reading. (On TCP sockets
180 * at least, shutting down the read side of the socket is a no-op anyway.)
182 virtual void shutdownWrite() = 0;
185 * Perform a half-shutdown of the write side of the transport.
187 * shutdownWriteNow() is identical to shutdownWrite(), except that it
188 * immediately performs the shutdown, rather than waiting for pending writes
189 * to complete. Any pending write requests will be immediately failed when
190 * shutdownWriteNow() is called.
192 virtual void shutdownWriteNow() = 0;
195 * Determine if transport is open and ready to read or write.
197 * Note that this function returns false on EOF; you must also call error()
198 * to distinguish between an EOF and an error.
200 * @return true iff the transport is open and ready, false otherwise.
202 virtual bool good() const = 0;
205 * Determine if the transport is readable or not.
207 * @return true iff the transport is readable, false otherwise.
209 virtual bool readable() const = 0;
212 * Determine if the there is pending data on the transport.
214 * @return true iff the if the there is pending data, false otherwise.
216 virtual bool isPending() const {
220 * Determine if transport is connected to the endpoint
222 * @return false iff the transport is connected, otherwise true
224 virtual bool connecting() const = 0;
227 * Determine if an error has occurred with this transport.
229 * @return true iff an error has occurred (not EOF).
231 virtual bool error() const = 0;
234 * Attach the transport to a EventBase.
236 * This may only be called if the transport is not currently attached to a
237 * EventBase (by an earlier call to detachEventBase()).
239 * This method must be invoked in the EventBase's thread.
241 virtual void attachEventBase(EventBase* eventBase) = 0;
244 * Detach the transport from its EventBase.
246 * This may only be called when the transport is idle and has no reads or
247 * writes pending. Once detached, the transport may not be used again until
248 * it is re-attached to a EventBase by calling attachEventBase().
250 * This method must be called from the current EventBase's thread.
252 virtual void detachEventBase() = 0;
255 * Determine if the transport can be detached.
257 * This method must be called from the current EventBase's thread.
259 virtual bool isDetachable() 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(SocketAddress* address) const = 0;
293 virtual void getAddress(SocketAddress* address) const {
294 getLocalAddress(address);
298 * Get the address of the remote endpoint to which this transport is
301 * This function may throw AsyncSocketException on error.
303 * @param address The remote endpoint's address will be stored in the
304 * specified SocketAddress.
306 virtual void getPeerAddress(SocketAddress* address) const = 0;
309 * @return True iff end of record tracking is enabled
311 virtual bool isEorTrackingEnabled() const = 0;
313 virtual void setEorTracking(bool track) = 0;
315 virtual size_t getAppBytesWritten() const = 0;
316 virtual size_t getRawBytesWritten() const = 0;
317 virtual size_t getAppBytesReceived() const = 0;
318 virtual size_t getRawBytesReceived() const = 0;
321 virtual ~AsyncTransport() = default;
324 // Transitional intermediate interface. This is deprecated.
325 // Wrapper around folly::AsyncTransport, that includes read/write callbacks
326 class AsyncTransportWrapper : virtual public AsyncTransport {
328 typedef std::unique_ptr<AsyncTransportWrapper, Destructor> UniquePtr;
332 virtual ~ReadCallback() = default;
335 * When data becomes available, getReadBuffer() will be invoked to get the
336 * buffer into which data should be read.
338 * This method allows the ReadCallback to delay buffer allocation until
339 * data becomes available. This allows applications to manage large
340 * numbers of idle connections, without having to maintain a separate read
341 * buffer for each idle connection.
343 * It is possible that in some cases, getReadBuffer() may be called
344 * multiple times before readDataAvailable() is invoked. In this case, the
345 * data will be written to the buffer returned from the most recent call to
346 * readDataAvailable(). If the previous calls to readDataAvailable()
347 * returned different buffers, the ReadCallback is responsible for ensuring
348 * that they are not leaked.
350 * If getReadBuffer() throws an exception, returns a nullptr buffer, or
351 * returns a 0 length, the ReadCallback will be uninstalled and its
352 * readError() method will be invoked.
354 * getReadBuffer() is not allowed to change the transport state before it
355 * returns. (For example, it should never uninstall the read callback, or
356 * set a different read callback.)
358 * @param bufReturn getReadBuffer() should update *bufReturn to contain the
359 * address of the read buffer. This parameter will never
361 * @param lenReturn getReadBuffer() should update *lenReturn to contain the
362 * maximum number of bytes that may be written to the read
363 * buffer. This parameter will never be nullptr.
365 virtual void getReadBuffer(void** bufReturn, size_t* lenReturn) = 0;
368 * readDataAvailable() will be invoked when data has been successfully read
369 * into the buffer returned by the last call to getReadBuffer().
371 * The read callback remains installed after readDataAvailable() returns.
372 * It must be explicitly uninstalled to stop receiving read events.
373 * getReadBuffer() will be called at least once before each call to
374 * readDataAvailable(). getReadBuffer() will also be called before any
377 * @param len The number of bytes placed in the buffer.
379 virtual void readDataAvailable(size_t len) noexcept = 0;
382 * readEOF() will be invoked when the transport is closed.
384 * The read callback will be automatically uninstalled immediately before
385 * readEOF() is invoked.
387 virtual void readEOF() noexcept = 0;
390 * readError() will be invoked if an error occurs reading from the
393 * The read callback will be automatically uninstalled immediately before
394 * readError() is invoked.
396 * @param ex An exception describing the error that occurred.
398 virtual void readErr(const AsyncSocketException& ex) noexcept = 0;
401 class WriteCallback {
403 virtual ~WriteCallback() = default;
406 * writeSuccess() will be invoked when all of the data has been
407 * successfully written.
409 * Note that this mainly signals that the buffer containing the data to
410 * write is no longer needed and may be freed or re-used. It does not
411 * guarantee that the data has been fully transmitted to the remote
412 * endpoint. For example, on socket-based transports, writeSuccess() only
413 * indicates that the data has been given to the kernel for eventual
416 virtual void writeSuccess() noexcept = 0;
419 * writeError() will be invoked if an error occurs writing the data.
421 * @param bytesWritten The number of bytes that were successfull
422 * @param ex An exception describing the error that occurred.
424 virtual void writeErr(size_t bytesWritten,
425 const AsyncSocketException& ex) noexcept = 0;
428 // Read/write methods that aren't part of AsyncTransport
429 virtual void setReadCB(ReadCallback* callback) = 0;
430 virtual ReadCallback* getReadCallback() const = 0;
432 virtual void write(WriteCallback* callback, const void* buf, size_t bytes,
433 WriteFlags flags = WriteFlags::NONE) = 0;
434 virtual void writev(WriteCallback* callback, const iovec* vec, size_t count,
435 WriteFlags flags = WriteFlags::NONE) = 0;
436 virtual void writeChain(WriteCallback* callback,
437 std::unique_ptr<IOBuf>&& buf,
438 WriteFlags flags = WriteFlags::NONE) = 0;