test for OutputBufferingHandler
[folly.git] / folly / io / async / AsyncTransport.h
1 /*
2  * Copyright 2014 Facebook, Inc.
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 #pragma once
18
19 #include <folly/SocketAddress.h>
20 #include <folly/io/async/DelayedDestruction.h>
21 #include <folly/io/async/EventBase.h>
22
23 namespace folly {
24
25 /*
26  * flags given by the application for write* calls
27  */
28 enum class WriteFlags : uint32_t {
29   NONE = 0x00,
30   /*
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.)
33    */
34   CORK = 0x01,
35   /*
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.
39    */
40   EOR = 0x02,
41 };
42
43 /*
44  * union operator
45  */
46 inline WriteFlags operator|(WriteFlags a, WriteFlags b) {
47   return static_cast<WriteFlags>(
48     static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
49 }
50
51 /*
52  * intersection operator
53  */
54 inline WriteFlags operator&(WriteFlags a, WriteFlags b) {
55   return static_cast<WriteFlags>(
56     static_cast<uint32_t>(a) & static_cast<uint32_t>(b));
57 }
58
59 /*
60  * exclusion parameter
61  */
62 inline WriteFlags operator~(WriteFlags a) {
63   return static_cast<WriteFlags>(~static_cast<uint32_t>(a));
64 }
65
66 /*
67  * unset operator
68  */
69 inline WriteFlags unSet(WriteFlags a, WriteFlags b) {
70   return a & ~b;
71 }
72
73 /*
74  * inclusion operator
75  */
76 inline bool isSet(WriteFlags a, WriteFlags b) {
77   return (a & b) == b;
78 }
79
80
81 /**
82  * AsyncTransport defines an asynchronous API for streaming I/O.
83  *
84  * This class provides an API to for asynchronously waiting for data
85  * on a streaming transport, and for asynchronously sending data.
86  *
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.
91  *
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.
101  *
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.
107  */
108 class AsyncTransport : public DelayedDestruction {
109  public:
110   typedef std::unique_ptr<AsyncTransport, Destructor> UniquePtr;
111
112   /**
113    * Close the transport.
114    *
115    * This gracefully closes the transport, waiting for all pending write
116    * requests to complete before actually closing the underlying transport.
117    *
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.
122    */
123   virtual void close() = 0;
124
125   /**
126    * Close the transport immediately.
127    *
128    * This closes the transport immediately, dropping any outstanding data
129    * waiting to be written.
130    *
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
134    * callbacks.
135    */
136   virtual void closeNow() = 0;
137
138   /**
139    * Reset the transport immediately.
140    *
141    * This closes the transport immediately, sending a reset to the remote peer
142    * if possible to indicate abnormal shutdown.
143    *
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.
147    */
148   virtual void closeWithReset() {
149     closeNow();
150   }
151
152   /**
153    * Perform a half-shutdown of the write side of the transport.
154    *
155    * The caller should not make any more calls to write() or writev() after
156    * shutdownWrite() is called.  Any future write attempts will fail
157    * immediately.
158    *
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.)
165    *
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
168    * written.
169    *
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.)
173    */
174   virtual void shutdownWrite() = 0;
175
176   /**
177    * Perform a half-shutdown of the write side of the transport.
178    *
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.
183    */
184   virtual void shutdownWriteNow() = 0;
185
186   /**
187    * Determine if transport is open and ready to read or write.
188    *
189    * Note that this function returns false on EOF; you must also call error()
190    * to distinguish between an EOF and an error.
191    *
192    * @return  true iff the transport is open and ready, false otherwise.
193    */
194   virtual bool good() const = 0;
195
196   /**
197    * Determine if the transport is readable or not.
198    *
199    * @return  true iff the transport is readable, false otherwise.
200    */
201   virtual bool readable() const = 0;
202
203   /**
204    * Determine if the there is pending data on the transport.
205    *
206    * @return  true iff the if the there is pending data, false otherwise.
207    */
208   virtual bool isPending() const {
209     return readable();
210   }
211   /**
212    * Determine if transport is connected to the endpoint
213    *
214    * @return  false iff the transport is connected, otherwise true
215    */
216   virtual bool connecting() const = 0;
217
218   /**
219    * Determine if an error has occurred with this transport.
220    *
221    * @return  true iff an error has occurred (not EOF).
222    */
223   virtual bool error() const = 0;
224
225   /**
226    * Attach the transport to a EventBase.
227    *
228    * This may only be called if the transport is not currently attached to a
229    * EventBase (by an earlier call to detachEventBase()).
230    *
231    * This method must be invoked in the EventBase's thread.
232    */
233   virtual void attachEventBase(EventBase* eventBase) = 0;
234
235   /**
236    * Detach the transport from its EventBase.
237    *
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().
241    *
242    * This method must be called from the current EventBase's thread.
243    */
244   virtual void detachEventBase() = 0;
245
246   /**
247    * Determine if the transport can be detached.
248    *
249    * This method must be called from the current EventBase's thread.
250    */
251   virtual bool isDetachable() const = 0;
252
253   /**
254    * Get the EventBase used by this transport.
255    *
256    * Returns nullptr if this transport is not currently attached to a
257    * EventBase.
258    */
259   virtual EventBase* getEventBase() const = 0;
260
261   /**
262    * Set the send timeout.
263    *
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.
266    *
267    * If write requests are currently pending when setSendTimeout() is called,
268    * the timeout interval is immediately restarted using the new value.
269    *
270    * @param milliseconds  The timeout duration, in milliseconds.  If 0, no
271    *                      timeout will be used.
272    */
273   virtual void setSendTimeout(uint32_t milliseconds) = 0;
274
275   /**
276    * Get the send timeout.
277    *
278    * @return Returns the current send timeout, in milliseconds.  A return value
279    *         of 0 indicates that no timeout is set.
280    */
281   virtual uint32_t getSendTimeout() const = 0;
282
283   /**
284    * Get the address of the local endpoint of this transport.
285    *
286    * This function may throw AsyncSocketException on error.
287    *
288    * @param address  The local address will be stored in the specified
289    *                 SocketAddress.
290    */
291   virtual void getLocalAddress(folly::SocketAddress* address) const = 0;
292
293   /**
294    * Get the address of the remote endpoint to which this transport is
295    * connected.
296    *
297    * This function may throw AsyncSocketException on error.
298    *
299    * @param address  The remote endpoint's address will be stored in the
300    *                 specified SocketAddress.
301    */
302   virtual void getPeerAddress(folly::SocketAddress* address) const = 0;
303
304   /**
305    * @return True iff end of record tracking is enabled
306    */
307   virtual bool isEorTrackingEnabled() const = 0;
308
309   virtual void setEorTracking(bool track) = 0;
310
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;
315
316  protected:
317   virtual ~AsyncTransport() {}
318 };
319
320
321 } // folly