AsyncSocket
[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 namespace folly {
20
21 /*
22  * flags given by the application for write* calls
23  */
24 enum class WriteFlags : uint32_t {
25   NONE = 0x00,
26   /*
27    * Whether to delay the output until a subsequent non-corked write.
28    * (Note: may not be supported in all subclasses or on all platforms.)
29    */
30   CORK = 0x01,
31   /*
32    * for a socket that has ACK latency enabled, it will cause the kernel
33    * to fire a TCP ESTATS event when the last byte of the given write call
34    * will be acknowledged.
35    */
36   EOR = 0x02,
37 };
38
39 /*
40  * union operator
41  */
42 inline WriteFlags operator|(WriteFlags a, WriteFlags b) {
43   return static_cast<WriteFlags>(
44     static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
45 }
46
47 /*
48  * intersection operator
49  */
50 inline WriteFlags operator&(WriteFlags a, WriteFlags b) {
51   return static_cast<WriteFlags>(
52     static_cast<uint32_t>(a) & static_cast<uint32_t>(b));
53 }
54
55 /*
56  * exclusion parameter
57  */
58 inline WriteFlags operator~(WriteFlags a) {
59   return static_cast<WriteFlags>(~static_cast<uint32_t>(a));
60 }
61
62 /*
63  * unset operator
64  */
65 inline WriteFlags unSet(WriteFlags a, WriteFlags b) {
66   return a & ~b;
67 }
68
69 /*
70  * inclusion operator
71  */
72 inline bool isSet(WriteFlags a, WriteFlags b) {
73   return (a & b) == b;
74 }
75
76
77 /**
78  * AsyncTransport defines an asynchronous API for streaming I/O.
79  *
80  * This class provides an API to for asynchronously waiting for data
81  * on a streaming transport, and for asynchronously sending data.
82  *
83  * The APIs for reading and writing are intentionally asymmetric.  Waiting for
84  * data to read is a persistent API: a callback is installed, and is notified
85  * whenever new data is available.  It continues to be notified of new events
86  * until it is uninstalled.
87  *
88  * AsyncTransport does not provide read timeout functionality, because it
89  * typically cannot determine when the timeout should be active.  Generally, a
90  * timeout should only be enabled when processing is blocked waiting on data
91  * from the remote endpoint.  For server-side applications, the timeout should
92  * not be active if the server is currently processing one or more outstanding
93  * requests on this transport.  For client-side applications, the timeout
94  * should not be active if there are no requests pending on the transport.
95  * Additionally, if a client has multiple pending requests, it will ususally
96  * want a separate timeout for each request, rather than a single read timeout.
97  *
98  * The write API is fairly intuitive: a user can request to send a block of
99  * data, and a callback will be informed once the entire block has been
100  * transferred to the kernel, or on error.  AsyncTransport does provide a send
101  * timeout, since most callers want to give up if the remote end stops
102  * responding and no further progress can be made sending the data.
103  */
104 class AsyncTransport : public DelayedDestruction {
105  public:
106   typedef std::unique_ptr<AsyncTransport, Destructor> UniquePtr;
107
108   /**
109    * Close the transport.
110    *
111    * This gracefully closes the transport, waiting for all pending write
112    * requests to complete before actually closing the underlying transport.
113    *
114    * If a read callback is set, readEOF() will be called immediately.  If there
115    * are outstanding write requests, the close will be delayed until all
116    * remaining writes have completed.  No new writes may be started after
117    * close() has been called.
118    */
119   virtual void close() = 0;
120
121   /**
122    * Close the transport immediately.
123    *
124    * This closes the transport immediately, dropping any outstanding data
125    * waiting to be written.
126    *
127    * If a read callback is set, readEOF() will be called immediately.
128    * If there are outstanding write requests, these requests will be aborted
129    * and writeError() will be invoked immediately on all outstanding write
130    * callbacks.
131    */
132   virtual void closeNow() = 0;
133
134   /**
135    * Reset the transport immediately.
136    *
137    * This closes the transport immediately, sending a reset to the remote peer
138    * if possible to indicate abnormal shutdown.
139    *
140    * Note that not all subclasses implement this reset functionality: some
141    * subclasses may treat reset() the same as closeNow().  Subclasses that use
142    * TCP transports should terminate the connection with a TCP reset.
143    */
144   virtual void closeWithReset() {
145     closeNow();
146   }
147
148   /**
149    * Perform a half-shutdown of the write side of the transport.
150    *
151    * The caller should not make any more calls to write() or writev() after
152    * shutdownWrite() is called.  Any future write attempts will fail
153    * immediately.
154    *
155    * Not all transport types support half-shutdown.  If the underlying
156    * transport does not support half-shutdown, it will fully shutdown both the
157    * read and write sides of the transport.  (Fully shutting down the socket is
158    * better than doing nothing at all, since the caller may rely on the
159    * shutdownWrite() call to notify the other end of the connection that no
160    * more data can be read.)
161    *
162    * If there is pending data still waiting to be written on the transport,
163    * the actual shutdown will be delayed until the pending data has been
164    * written.
165    *
166    * Note: There is no corresponding shutdownRead() equivalent.  Simply
167    * uninstall the read callback if you wish to stop reading.  (On TCP sockets
168    * at least, shutting down the read side of the socket is a no-op anyway.)
169    */
170   virtual void shutdownWrite() = 0;
171
172   /**
173    * Perform a half-shutdown of the write side of the transport.
174    *
175    * shutdownWriteNow() is identical to shutdownWrite(), except that it
176    * immediately performs the shutdown, rather than waiting for pending writes
177    * to complete.  Any pending write requests will be immediately failed when
178    * shutdownWriteNow() is called.
179    */
180   virtual void shutdownWriteNow() = 0;
181
182   /**
183    * Determine if transport is open and ready to read or write.
184    *
185    * Note that this function returns false on EOF; you must also call error()
186    * to distinguish between an EOF and an error.
187    *
188    * @return  true iff the transport is open and ready, false otherwise.
189    */
190   virtual bool good() const = 0;
191
192   /**
193    * Determine if the transport is readable or not.
194    *
195    * @return  true iff the transport is readable, false otherwise.
196    */
197   virtual bool readable() const = 0;
198
199   /**
200    * Determine if the there is pending data on the transport.
201    *
202    * @return  true iff the if the there is pending data, false otherwise.
203    */
204   virtual bool isPending() const {
205     return readable();
206   }
207   /**
208    * Determine if transport is connected to the endpoint
209    *
210    * @return  false iff the transport is connected, otherwise true
211    */
212   virtual bool connecting() const = 0;
213
214   /**
215    * Determine if an error has occurred with this transport.
216    *
217    * @return  true iff an error has occurred (not EOF).
218    */
219   virtual bool error() const = 0;
220
221   /**
222    * Attach the transport to a EventBase.
223    *
224    * This may only be called if the transport is not currently attached to a
225    * EventBase (by an earlier call to detachEventBase()).
226    *
227    * This method must be invoked in the EventBase's thread.
228    */
229   virtual void attachEventBase(EventBase* eventBase) = 0;
230
231   /**
232    * Detach the transport from its EventBase.
233    *
234    * This may only be called when the transport is idle and has no reads or
235    * writes pending.  Once detached, the transport may not be used again until
236    * it is re-attached to a EventBase by calling attachEventBase().
237    *
238    * This method must be called from the current EventBase's thread.
239    */
240   virtual void detachEventBase() = 0;
241
242   /**
243    * Determine if the transport can be detached.
244    *
245    * This method must be called from the current EventBase's thread.
246    */
247   virtual bool isDetachable() const = 0;
248
249   /**
250    * Get the EventBase used by this transport.
251    *
252    * Returns nullptr if this transport is not currently attached to a
253    * EventBase.
254    */
255   virtual EventBase* getEventBase() const = 0;
256
257   /**
258    * Set the send timeout.
259    *
260    * If write requests do not make any progress for more than the specified
261    * number of milliseconds, fail all pending writes and close the transport.
262    *
263    * If write requests are currently pending when setSendTimeout() is called,
264    * the timeout interval is immediately restarted using the new value.
265    *
266    * @param milliseconds  The timeout duration, in milliseconds.  If 0, no
267    *                      timeout will be used.
268    */
269   virtual void setSendTimeout(uint32_t milliseconds) = 0;
270
271   /**
272    * Get the send timeout.
273    *
274    * @return Returns the current send timeout, in milliseconds.  A return value
275    *         of 0 indicates that no timeout is set.
276    */
277   virtual uint32_t getSendTimeout() const = 0;
278
279   /**
280    * Get the address of the local endpoint of this transport.
281    *
282    * This function may throw AsyncSocketException on error.
283    *
284    * @param address  The local address will be stored in the specified
285    *                 SocketAddress.
286    */
287   virtual void getLocalAddress(folly::SocketAddress* address) const = 0;
288
289   /**
290    * Get the address of the remote endpoint to which this transport is
291    * connected.
292    *
293    * This function may throw AsyncSocketException on error.
294    *
295    * @param address  The remote endpoint's address will be stored in the
296    *                 specified SocketAddress.
297    */
298   virtual void getPeerAddress(folly::SocketAddress* address) const = 0;
299
300   /**
301    * @return True iff end of record tracking is enabled
302    */
303   virtual bool isEorTrackingEnabled() const = 0;
304
305   virtual void setEorTracking(bool track) = 0;
306
307   virtual size_t getAppBytesWritten() const = 0;
308   virtual size_t getRawBytesWritten() const = 0;
309   virtual size_t getAppBytesReceived() const = 0;
310   virtual size_t getRawBytesReceived() const = 0;
311
312  protected:
313   virtual ~AsyncTransport() {}
314 };
315
316
317 } // folly