Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / beast / doc / html / beast / using_io / timeouts.html
1 <html>
2 <head>
3 <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
4 <title>Timeouts &#128161;</title>
5 <link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
6 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
7 <link rel="home" href="../../index.html" title="Chapter&#160;1.&#160;Boost.Beast">
8 <link rel="up" href="../using_io.html" title="Networking">
9 <link rel="prev" href="stream_types.html" title="Streams">
10 <link rel="next" href="rate_limiting.html" title="Rate Limiting &#128161;">
11 </head>
12 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
13 <table cellpadding="2" width="100%"><tr>
14 <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
15 <td align="center"><a href="../../../../../../index.html">Home</a></td>
16 <td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
17 <td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
18 <td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
19 <td align="center"><a href="../../../../../../more/index.htm">More</a></td>
20 </tr></table>
21 <hr>
22 <div class="spirit-nav">
23 <a accesskey="p" href="stream_types.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../using_io.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="rate_limiting.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
24 </div>
25 <div class="section">
26 <div class="titlepage"><div><div><h3 class="title">
27 <a name="beast.using_io.timeouts"></a><a class="link" href="timeouts.html" title="Timeouts &#128161;">Timeouts &#128161;</a>
28 </h3></div></div></div>
29 <p>
30         Network programs must handle adverse connection conditions; the most common
31         is that a connected peer goes offline unexpectedly. Protocols have no way
32         of identifying this reliably: the peer is offline after all, and unable to
33         send a message announcing the absence. A peer can go offline for various
34         reasons:
35       </p>
36 <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
37 <li class="listitem">
38             The peer experiences a power loss
39           </li>
40 <li class="listitem">
41             The peer becomes disconnected from the network
42           </li>
43 <li class="listitem">
44             The local host becomes disconnected from the network
45           </li>
46 <li class="listitem">
47             The network itself becomes unavailable
48           </li>
49 </ul></div>
50 <p>
51         To determine when a peer is offline or idle, a program will implement a
52         <a href="https://en.wikipedia.org/wiki/Timeout_(computing)" target="_top">timeout</a>
53         algorithm, which closes the connection after a specified amount of time if
54         some condition is met. For example, if no data is received for the duration.
55         A timeout may be used to:
56       </p>
57 <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
58 <li class="listitem">
59             Drop malicious or poorly performing hosts
60           </li>
61 <li class="listitem">
62             Close idle connections to free up resources
63           </li>
64 <li class="listitem">
65             Determine if a peer is offline or no longer available
66           </li>
67 </ul></div>
68 <p>
69         Traditionally, programs use a <a href="../../../../../../doc/html/boost_asio/reference/steady_timer.html" target="_top"><code class="computeroutput"><span class="identifier">net</span><span class="special">::</span><span class="identifier">steady_timer</span></code></a>
70         to determine when a timeout occurs, and then call <a href="../../../../../../doc/html/boost_asio/reference/basic_socket/close/overload2.html" target="_top"><code class="computeroutput"><span class="identifier">close</span></code></a> on the socket to release
71         the resources. The complexity of managing a separate timer is often a source
72         of <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1269r0.html#timers" target="_top">frustration</a>
73         for non-experts.
74       </p>
75 <div class="note"><table border="0" summary="Note">
76 <tr>
77 <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../doc/src/images/note.png"></td>
78 <th align="left">Note</th>
79 </tr>
80 <tr><td align="left" valign="top"><p>
81           For portability reasons, networking does not provide timeouts or cancellation
82           features for synchronous stream operations.
83         </p></td></tr>
84 </table></div>
85 <p>
86         To simplify the handling of timeouts, these provided types wrap a <a href="../../../../../../doc/html/boost_asio/reference/basic_stream_socket.html" target="_top"><code class="computeroutput"><span class="identifier">net</span><span class="special">::</span><span class="identifier">basic_stream_socket</span></code></a>
87         to provide additional features:
88       </p>
89 <div class="informaltable"><table class="table">
90 <colgroup>
91 <col>
92 <col>
93 </colgroup>
94 <thead><tr>
95 <th>
96                 <p>
97                   Name
98                 </p>
99               </th>
100 <th>
101                 <p>
102                   Features
103                 </p>
104               </th>
105 </tr></thead>
106 <tbody>
107 <tr>
108 <td>
109                 <p>
110                   <a class="link" href="../ref/boost__beast__tcp_stream.html" title="tcp_stream"><code class="computeroutput"><span class="identifier">tcp_stream</span></code></a>
111                 </p>
112               </td>
113 <td>
114                 <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
115 <li class="listitem">
116                       Timeouts for logical operations
117                     </li>
118 <li class="listitem">
119                       <a href="../../../../../../doc/html/boost_asio/reference/ip__tcp.html" target="_top"><code class="computeroutput"><span class="identifier">net</span><span class="special">::</span><span class="identifier">ip</span><span class="special">::</span><span class="identifier">tcp</span></code></a> protocol
120                     </li>
121 <li class="listitem">
122                       <a href="../../../../../../doc/html/boost_asio/reference/executor.html" target="_top"><code class="computeroutput"><span class="identifier">net</span><span class="special">::</span><span class="identifier">executor</span></code></a> executor
123                     </li>
124 <li class="listitem">
125                       <a class="link" href="../ref/boost__beast__unlimited_rate_policy.html" title="unlimited_rate_policy"><code class="computeroutput"><span class="identifier">unlimited_rate_policy</span></code></a>
126                       rate limits
127                     </li>
128 </ul></div>
129               </td>
130 </tr>
131 <tr>
132 <td>
133                 <p>
134                   <a class="link" href="../ref/boost__beast__basic_stream.html" title="basic_stream"><code class="computeroutput"><span class="identifier">basic_stream</span></code></a>
135                 </p>
136               </td>
137 <td>
138                 <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
139 <li class="listitem">
140                       Timeouts for logical operations
141                     </li>
142 <li class="listitem">
143                       Configurable <a href="../../../../../../doc/html/boost_asio/reference/Protocol.html" target="_top"><span class="emphasis"><em>Protocol</em></span></a>
144                       type
145                     </li>
146 <li class="listitem">
147                       Configurable <a href="../../../../../../doc/html/boost_asio/reference/Executor1.html" target="_top"><span class="emphasis"><em>Executor</em></span></a>
148                       type
149                     </li>
150 <li class="listitem">
151                       Configurable <a class="link" href="../concepts/RatePolicy.html" title="RatePolicy"><span class="emphasis"><em>RatePolicy</em></span></a>
152                       type
153                     </li>
154 </ul></div>
155               </td>
156 </tr>
157 </tbody>
158 </table></div>
159 <h5>
160 <a name="beast.using_io.timeouts.h0"></a>
161         <span class="phrase"><a name="beast.using_io.timeouts.construction"></a></span><a class="link" href="timeouts.html#beast.using_io.timeouts.construction">Construction</a>
162       </h5>
163 <p>
164         The <code class="computeroutput"><span class="identifier">tcp_stream</span></code> is designed
165         as a replacement for <a href="../../../../../../doc/html/boost_asio/reference/ip__tcp/socket.html" target="_top"><code class="computeroutput"><span class="identifier">net</span><span class="special">::</span><span class="identifier">ip</span><span class="special">::</span><span class="identifier">tcp</span><span class="special">::</span><span class="identifier">socket</span></code></a>. Any program which currently
166         uses a socket, can switch to a <code class="computeroutput"><span class="identifier">tcp_stream</span></code>
167         and achieve the features above (although some interfaces are different, see
168         below). Networking now allows I/O objects to construct with any instance
169         of <a href="../../../../../../doc/html/boost_asio/reference/ExecutionContext.html" target="_top"><span class="emphasis"><em>ExecutionContext</em></span></a>
170         or <a href="../../../../../../doc/html/boost_asio/reference/Executor1.html" target="_top"><span class="emphasis"><em>Executor</em></span></a>
171         objects. Here we construct a stream which uses a particular I/O context to
172         dispatch completion handlers:
173       </p>
174 <pre class="programlisting"><span class="comment">// `ioc` will be used to dispatch completion handlers</span>
175 <span class="identifier">tcp_stream</span> <span class="identifier">stream</span><span class="special">(</span><span class="identifier">ioc</span><span class="special">);</span>
176 </pre>
177 <p>
178         Alternatively, we can construct the stream from an executor:
179       </p>
180 <pre class="programlisting"><span class="comment">// The resolver is used to look up the IP addresses for a domain name</span>
181 <span class="identifier">net</span><span class="special">::</span><span class="identifier">ip</span><span class="special">::</span><span class="identifier">tcp</span><span class="special">::</span><span class="identifier">resolver</span> <span class="identifier">resolver</span><span class="special">(</span><span class="identifier">ioc</span><span class="special">);</span>
182
183 <span class="comment">// The stream will use the same executor as the resolver</span>
184 <span class="identifier">tcp_stream</span> <span class="identifier">stream</span><span class="special">(</span><span class="identifier">resolver</span><span class="special">.</span><span class="identifier">get_executor</span><span class="special">());</span>
185 </pre>
186 <p>
187         The function <a href="../../../../../../doc/html/boost_asio/reference/make_strand.html" target="_top"><code class="computeroutput"><span class="identifier">make_strand</span></code></a> returns a strand constructed
188         from an execution context or executor. When a <a href="../../../../../../doc/html/boost_asio/reference/strand.html" target="_top"><code class="computeroutput"><span class="identifier">net</span><span class="special">::</span><span class="identifier">strand</span></code></a>
189         is chosen for the stream's executor, all completion handlers which do not
190         already have an associated executor will use the strand. This is both a notational
191         convenience (no need for <code class="computeroutput"><span class="identifier">strand</span><span class="special">::</span><span class="identifier">wrap</span></code>
192         or <code class="computeroutput"><span class="identifier">bind_executor</span></code> at call
193         sites) and a measure of safety, as it is no longer possible to forget to
194         use the strand.
195       </p>
196 <pre class="programlisting"><span class="comment">// The strand will be used to invoke all completion handlers</span>
197 <span class="identifier">tcp_stream</span> <span class="identifier">stream</span><span class="special">(</span><span class="identifier">net</span><span class="special">::</span><span class="identifier">make_strand</span><span class="special">(</span><span class="identifier">ioc</span><span class="special">));</span>
198 </pre>
199 <h5>
200 <a name="beast.using_io.timeouts.h1"></a>
201         <span class="phrase"><a name="beast.using_io.timeouts.connecting"></a></span><a class="link" href="timeouts.html#beast.using_io.timeouts.connecting">Connecting</a>
202       </h5>
203 <p>
204         Before data can be exchanged, the stream needs to be connected to a peer.
205         The following code sets a timeout for an asynchronous connect operation.
206         In Beast, functions to connect to a range of endpoints (such as the range
207         returned by <a href="../../../../../../doc/html/boost_asio/reference/ip__basic_resolver/resolve/overload3.html" target="_top"><code class="computeroutput"><span class="identifier">net</span><span class="special">::</span><span class="identifier">ip</span><span class="special">::</span><span class="identifier">tcp</span><span class="special">::</span><span class="identifier">resolver</span><span class="special">::</span><span class="identifier">resolve</span></code></a>) are members of the class
208         rather than free functions such as <a href="../../../../../../doc/html/boost_asio/reference/async_connect.html" target="_top"><code class="computeroutput"><span class="identifier">net</span><span class="special">::</span><span class="identifier">async_connect</span></code></a>.
209       </p>
210 <pre class="programlisting"><span class="comment">// Set the logical operation timer to 30 seconds</span>
211 <span class="identifier">stream</span><span class="special">.</span><span class="identifier">expires_after</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">seconds</span><span class="special">(</span><span class="number">30</span><span class="special">));</span>
212
213 <span class="comment">// If the connection is not established within 30 seconds,</span>
214 <span class="comment">// the operation will be canceled and the handler will receive</span>
215 <span class="comment">// error::timeout as the error code.</span>
216
217 <span class="identifier">stream</span><span class="special">.</span><span class="identifier">async_connect</span><span class="special">(</span><span class="identifier">resolver</span><span class="special">.</span><span class="identifier">resolve</span><span class="special">(</span><span class="string">"www.example.com"</span><span class="special">,</span> <span class="string">"http"</span><span class="special">),</span>
218     <span class="special">[](</span><span class="identifier">error_code</span> <span class="identifier">ec</span><span class="special">,</span> <span class="identifier">net</span><span class="special">::</span><span class="identifier">ip</span><span class="special">::</span><span class="identifier">tcp</span><span class="special">::</span><span class="identifier">endpoint</span> <span class="identifier">ep</span><span class="special">)</span>
219     <span class="special">{</span>
220         <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span> <span class="special">==</span> <span class="identifier">error</span><span class="special">::</span><span class="identifier">timeout</span><span class="special">)</span>
221             <span class="identifier">std</span><span class="special">::</span><span class="identifier">cerr</span> <span class="special">&lt;&lt;</span> <span class="string">"async_connect took too long\n"</span><span class="special">;</span>
222         <span class="keyword">else</span> <span class="keyword">if</span><span class="special">(!</span> <span class="identifier">ec</span><span class="special">)</span>
223             <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"Connected to "</span> <span class="special">&lt;&lt;</span> <span class="identifier">ep</span> <span class="special">&lt;&lt;</span> <span class="string">"\n"</span><span class="special">;</span>
224     <span class="special">}</span>
225 <span class="special">);</span>
226
227 <span class="comment">// The timer is still running. If we don't want the next</span>
228 <span class="comment">// operation to time out 30 seconds relative to the previous</span>
229 <span class="comment">// call  to `expires_after`, we need to turn it off before</span>
230 <span class="comment">// starting another asynchronous operation.</span>
231
232 <span class="identifier">stream</span><span class="special">.</span><span class="identifier">expires_never</span><span class="special">();</span>
233 </pre>
234 <p>
235         A server will use an acceptor bound to a particular IP address and port to
236         listen to and receive incoming connection requests. The acceptor returns
237         an ordinary socket. A <code class="computeroutput"><span class="identifier">tcp_stream</span></code>
238         can be move-constructed from the underlying <code class="computeroutput"><span class="identifier">basic_stream_socket</span></code>
239         thusly:
240       </p>
241 <pre class="programlisting"><span class="comment">// The acceptor is used to listen and accept incoming connections.</span>
242 <span class="comment">// We construct the acceptor to use a new strand, and listen</span>
243 <span class="comment">// on the loopback address with an operating-system assigned port.</span>
244
245 <span class="identifier">net</span><span class="special">::</span><span class="identifier">ip</span><span class="special">::</span><span class="identifier">tcp</span><span class="special">::</span><span class="identifier">acceptor</span> <span class="identifier">acceptor</span><span class="special">(</span><span class="identifier">net</span><span class="special">::</span><span class="identifier">make_strand</span><span class="special">(</span><span class="identifier">ioc</span><span class="special">));</span>
246 <span class="identifier">acceptor</span><span class="special">.</span><span class="identifier">bind</span><span class="special">(</span><span class="identifier">net</span><span class="special">::</span><span class="identifier">ip</span><span class="special">::</span><span class="identifier">tcp</span><span class="special">::</span><span class="identifier">endpoint</span><span class="special">(</span><span class="identifier">net</span><span class="special">::</span><span class="identifier">ip</span><span class="special">::</span><span class="identifier">make_address_v4</span><span class="special">(</span><span class="string">"127.0.0.1"</span><span class="special">),</span> <span class="number">0</span><span class="special">));</span>
247 <span class="identifier">acceptor</span><span class="special">.</span><span class="identifier">listen</span><span class="special">(</span><span class="number">0</span><span class="special">);</span>
248
249 <span class="comment">// This blocks until a new incoming connection is established.</span>
250 <span class="comment">// Upon success, the function returns a new socket which is</span>
251 <span class="comment">// connected to the peer. The socket will have its own executor,</span>
252 <span class="comment">// which in the call below is a new strand for the I/O context.</span>
253
254 <span class="identifier">net</span><span class="special">::</span><span class="identifier">ip</span><span class="special">::</span><span class="identifier">tcp</span><span class="special">::</span><span class="identifier">socket</span> <span class="identifier">s</span> <span class="special">=</span> <span class="identifier">acceptor</span><span class="special">.</span><span class="identifier">accept</span><span class="special">(</span><span class="identifier">net</span><span class="special">::</span><span class="identifier">make_strand</span><span class="special">(</span><span class="identifier">ioc</span><span class="special">));</span>
255
256 <span class="comment">// Construct a new tcp_stream from the connected socket.</span>
257 <span class="comment">// The stream will use the strand created when the connection</span>
258 <span class="comment">// was accepted.</span>
259
260 <span class="identifier">tcp_stream</span> <span class="identifier">stream</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">s</span><span class="special">));</span>
261 </pre>
262 <h5>
263 <a name="beast.using_io.timeouts.h2"></a>
264         <span class="phrase"><a name="beast.using_io.timeouts.reading_and_writing"></a></span><a class="link" href="timeouts.html#beast.using_io.timeouts.reading_and_writing">Reading
265         and Writing</a>
266       </h5>
267 <p>
268         Timeouts apply to the logical operation, expressed as a series of asynchronous
269         calls, rather than just the next call. This code reads a line from the stream
270         and writes it back. Both the read and the write must complete within 30 seconds
271         from when the timeout was set; the timer is not reset between operations.
272       </p>
273 <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">s</span><span class="special">;</span>
274
275 <span class="comment">// Set the logical operation timer to 30 seconds.</span>
276 <span class="identifier">stream</span><span class="special">.</span><span class="identifier">expires_after</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">seconds</span><span class="special">(</span><span class="number">30</span><span class="special">));</span>
277
278 <span class="comment">// Read a line from the stream into the string.</span>
279 <span class="identifier">net</span><span class="special">::</span><span class="identifier">async_read_until</span><span class="special">(</span><span class="identifier">stream</span><span class="special">,</span> <span class="identifier">net</span><span class="special">::</span><span class="identifier">dynamic_buffer</span><span class="special">(</span><span class="identifier">s</span><span class="special">),</span> <span class="char">'\n'</span><span class="special">,</span>
280     <span class="special">[&amp;</span><span class="identifier">s</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">stream</span><span class="special">](</span><span class="identifier">error_code</span> <span class="identifier">ec</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">bytes_transferred</span><span class="special">)</span>
281     <span class="special">{</span>
282         <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span>
283             <span class="keyword">return</span><span class="special">;</span>
284
285         <span class="comment">// read_until can read past the '\n', these will end up in</span>
286         <span class="comment">// our buffer but we don't want to echo those extra received</span>
287         <span class="comment">// bytes. `bytes_transferred` will be the number of bytes</span>
288         <span class="comment">// up to and including the '\n'. We use `buffers_prefix` so</span>
289         <span class="comment">// that extra data is not written.</span>
290
291         <span class="identifier">net</span><span class="special">::</span><span class="identifier">async_write</span><span class="special">(</span><span class="identifier">stream</span><span class="special">,</span> <span class="identifier">buffers_prefix</span><span class="special">(</span><span class="identifier">bytes_transferred</span><span class="special">,</span> <span class="identifier">net</span><span class="special">::</span><span class="identifier">buffer</span><span class="special">(</span><span class="identifier">s</span><span class="special">)),</span>
292             <span class="special">[&amp;</span><span class="identifier">s</span><span class="special">](</span><span class="identifier">error_code</span> <span class="identifier">ec</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">bytes_transferred</span><span class="special">)</span>
293             <span class="special">{</span>
294                 <span class="comment">// Consume the line from the buffer</span>
295                 <span class="identifier">s</span><span class="special">.</span><span class="identifier">erase</span><span class="special">(</span><span class="identifier">s</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">s</span><span class="special">.</span><span class="identifier">begin</span><span class="special">()</span> <span class="special">+</span> <span class="identifier">bytes_transferred</span><span class="special">);</span>
296
297                 <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span>
298                     <span class="identifier">std</span><span class="special">::</span><span class="identifier">cerr</span> <span class="special">&lt;&lt;</span> <span class="string">"Error: "</span> <span class="special">&lt;&lt;</span> <span class="identifier">ec</span><span class="special">.</span><span class="identifier">message</span><span class="special">()</span> <span class="special">&lt;&lt;</span> <span class="string">"\n"</span><span class="special">;</span>
299             <span class="special">});</span>
300     <span class="special">});</span>
301 </pre>
302 <p>
303         Since reads and writes can take place concurrently, it is possible to have
304         two simultaneous logical operations where each operation either only reads,
305         or only writes. The beginning of a new read or write operation will use the
306         most recently set timeout. This will not affect operations that are already
307         outstanding.
308       </p>
309 <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">s1</span><span class="special">;</span>
310 <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">s2</span><span class="special">;</span>
311
312 <span class="comment">// Set the logical operation timer to 15 seconds.</span>
313 <span class="identifier">stream</span><span class="special">.</span><span class="identifier">expires_after</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">seconds</span><span class="special">(</span><span class="number">15</span><span class="special">));</span>
314
315 <span class="comment">// Read another line from the stream into our dynamic buffer.</span>
316 <span class="comment">// The operation will time out after 15 seconds.</span>
317
318 <span class="identifier">net</span><span class="special">::</span><span class="identifier">async_read_until</span><span class="special">(</span><span class="identifier">stream</span><span class="special">,</span> <span class="identifier">net</span><span class="special">::</span><span class="identifier">dynamic_buffer</span><span class="special">(</span><span class="identifier">s1</span><span class="special">),</span> <span class="char">'\n'</span><span class="special">,</span> <span class="identifier">handler</span><span class="special">);</span>
319
320 <span class="comment">// Set the logical operation timer to 30 seconds.</span>
321 <span class="identifier">stream</span><span class="special">.</span><span class="identifier">expires_after</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">seconds</span><span class="special">(</span><span class="number">30</span><span class="special">));</span>
322
323 <span class="comment">// Write the contents of the other buffer.</span>
324 <span class="comment">// This operation will time out after 30 seconds.</span>
325
326 <span class="identifier">net</span><span class="special">::</span><span class="identifier">async_write</span><span class="special">(</span><span class="identifier">stream</span><span class="special">,</span> <span class="identifier">net</span><span class="special">::</span><span class="identifier">buffer</span><span class="special">(</span><span class="identifier">s2</span><span class="special">),</span> <span class="identifier">handler</span><span class="special">);</span>
327 </pre>
328 <p>
329         When a timeout is set, it cancels any previous read or write timeout for
330         which no outstanding operation is in progress. Algorithms which loop over
331         logical operations simply need to set the timeout once before the logical
332         operation, it is not necessary to call <code class="computeroutput"><span class="identifier">expires_never</span></code>
333         in this case. Here we implement an algorithm which continuously echoes lines
334         back, with a timeout. This example is implemented as a complete function.
335       </p>
336 <pre class="programlisting"><span class="comment">/** This function echoes back received lines from a peer, with a timeout.
337
338     The algorithm terminates upon any error (including timeout).
339 */</span>
340 <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Protocol</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Executor</span><span class="special">&gt;</span>
341 <span class="keyword">void</span> <span class="identifier">do_async_echo</span> <span class="special">(</span><span class="identifier">basic_stream</span><span class="special">&lt;</span><span class="identifier">Protocol</span><span class="special">,</span> <span class="identifier">Executor</span><span class="special">&gt;&amp;</span> <span class="identifier">stream</span><span class="special">)</span>
342 <span class="special">{</span>
343     <span class="comment">// This object will hold our state when reading the line.</span>
344
345     <span class="keyword">struct</span> <span class="identifier">echo_line</span>
346     <span class="special">{</span>
347         <span class="identifier">basic_stream</span><span class="special">&lt;</span><span class="identifier">Protocol</span><span class="special">,</span> <span class="identifier">Executor</span><span class="special">&gt;&amp;</span> <span class="identifier">stream</span><span class="special">;</span>
348
349         <span class="comment">// The shared pointer is used to extend the lifetime of the</span>
350         <span class="comment">// string until the last asynchronous operation completes.</span>
351         <span class="identifier">std</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;</span> <span class="identifier">s</span><span class="special">;</span>
352
353         <span class="comment">// This starts a new operation to read and echo a line</span>
354         <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()()</span>
355         <span class="special">{</span>
356             <span class="comment">// If a line is not sent and received within 30 seconds, then</span>
357             <span class="comment">// the connection will be closed and this algorithm will terminate.</span>
358
359             <span class="identifier">stream</span><span class="special">.</span><span class="identifier">expires_after</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">seconds</span><span class="special">(</span><span class="number">30</span><span class="special">));</span>
360
361             <span class="comment">// Read a line from the stream into our dynamic buffer, with a timeout</span>
362             <span class="identifier">net</span><span class="special">::</span><span class="identifier">async_read_until</span><span class="special">(</span><span class="identifier">stream</span><span class="special">,</span> <span class="identifier">net</span><span class="special">::</span><span class="identifier">dynamic_buffer</span><span class="special">(*</span><span class="identifier">s</span><span class="special">),</span> <span class="char">'\n'</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(*</span><span class="keyword">this</span><span class="special">));</span>
363         <span class="special">}</span>
364
365         <span class="comment">// This function is called when the read completes</span>
366         <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">error_code</span> <span class="identifier">ec</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">bytes_transferred</span><span class="special">)</span>
367         <span class="special">{</span>
368             <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span>
369                 <span class="keyword">return</span><span class="special">;</span>
370
371             <span class="identifier">net</span><span class="special">::</span><span class="identifier">async_write</span><span class="special">(</span><span class="identifier">stream</span><span class="special">,</span> <span class="identifier">buffers_prefix</span><span class="special">(</span><span class="identifier">bytes_transferred</span><span class="special">,</span> <span class="identifier">net</span><span class="special">::</span><span class="identifier">buffer</span><span class="special">(*</span><span class="identifier">s</span><span class="special">)),</span>
372                 <span class="special">[</span><span class="keyword">this</span><span class="special">](</span><span class="identifier">error_code</span> <span class="identifier">ec</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">bytes_transferred</span><span class="special">)</span>
373                 <span class="special">{</span>
374                     <span class="identifier">s</span><span class="special">-&gt;</span><span class="identifier">erase</span><span class="special">(</span><span class="identifier">s</span><span class="special">-&gt;</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">s</span><span class="special">-&gt;</span><span class="identifier">begin</span><span class="special">()</span> <span class="special">+</span> <span class="identifier">bytes_transferred</span><span class="special">);</span>
375
376                     <span class="keyword">if</span><span class="special">(!</span> <span class="identifier">ec</span><span class="special">)</span>
377                     <span class="special">{</span>
378                         <span class="comment">// Run this algorithm again</span>
379                         <span class="identifier">echo_line</span><span class="special">{</span><span class="identifier">stream</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">s</span><span class="special">)}();</span>
380                     <span class="special">}</span>
381                     <span class="keyword">else</span>
382                     <span class="special">{</span>
383                         <span class="identifier">std</span><span class="special">::</span><span class="identifier">cerr</span> <span class="special">&lt;&lt;</span> <span class="string">"Error: "</span> <span class="special">&lt;&lt;</span> <span class="identifier">ec</span><span class="special">.</span><span class="identifier">message</span><span class="special">()</span> <span class="special">&lt;&lt;</span> <span class="string">"\n"</span><span class="special">;</span>
384                     <span class="special">}</span>
385                 <span class="special">});</span>
386         <span class="special">}</span>
387     <span class="special">};</span>
388
389     <span class="comment">// Create the operation and run it</span>
390     <span class="identifier">echo_line</span><span class="special">{</span><span class="identifier">stream</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_shared</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;()}();</span>
391 <span class="special">}</span>
392 </pre>
393 <h5>
394 <a name="beast.using_io.timeouts.h3"></a>
395         <span class="phrase"><a name="beast.using_io.timeouts.https_get"></a></span><a class="link" href="timeouts.html#beast.using_io.timeouts.https_get">https_get</a>
396       </h5>
397 <p>
398         It is important to note that all of the examples thus far which perform reads
399         and writes with a timeout, make use of the existing networking stream algorithms.
400         As these algorithms are written generically to work with any object meeting
401         the stream requirements, they transparently support timeouts when used with
402         <code class="computeroutput"><span class="identifier">tcp_stream</span></code>. This can be used
403         to enable timeouts for stream wrappers that do not currently support timeouts.
404       </p>
405 <p>
406         The following code establishes an encrypted connection, writes an HTTP request,
407         reads the HTTP response, and closes the connection gracefully. If these operations
408         take longer than 30 seconds total, a timeout occurs. This code is intended
409         to show how <code class="computeroutput"><span class="identifier">tcp_stream</span></code> can
410         be used to enable timeouts across unmodified stream algorithms which were
411         not originally written to support timing out, and how a blocking algorithm
412         may be written from asynchronous intermediate operations.
413       </p>
414 <pre class="programlisting"><span class="comment">/** Request an HTTP resource from a TLS host and return it as a string, with a timeout.
415
416     This example uses fibers (stackful coroutines) and its own I/O context.
417 */</span>
418 <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span>
419 <span class="identifier">https_get</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">host</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">target</span><span class="special">,</span> <span class="identifier">error_code</span><span class="special">&amp;</span> <span class="identifier">ec</span><span class="special">)</span>
420 <span class="special">{</span>
421     <span class="comment">// It is the responsibility of the algorithm to clear the error first.</span>
422     <span class="identifier">ec</span> <span class="special">=</span> <span class="special">{};</span>
423
424     <span class="comment">// We use our own I/O context, to make this function blocking.</span>
425     <span class="identifier">net</span><span class="special">::</span><span class="identifier">io_context</span> <span class="identifier">ioc</span><span class="special">;</span>
426
427     <span class="comment">// This context is used to hold client and server certificates.</span>
428     <span class="comment">// We do not perform certificate verification in this example.</span>
429
430     <span class="identifier">net</span><span class="special">::</span><span class="identifier">ssl</span><span class="special">::</span><span class="identifier">context</span> <span class="identifier">ctx</span><span class="special">(</span><span class="identifier">net</span><span class="special">::</span><span class="identifier">ssl</span><span class="special">::</span><span class="identifier">context</span><span class="special">::</span><span class="identifier">tlsv12</span><span class="special">);</span>
431
432     <span class="comment">// This string will hold the body of the HTTP response, if any.</span>
433     <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">result</span><span class="special">;</span>
434
435     <span class="comment">// Note that Networking TS does not come with spawn. This function</span>
436     <span class="comment">// launches a "fiber" which is a coroutine that has its own separately</span>
437     <span class="comment">// allocated stack.</span>
438
439     <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">spawn</span><span class="special">(</span><span class="identifier">ioc</span><span class="special">,</span>
440     <span class="special">[&amp;](</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">yield_context</span> <span class="identifier">yield</span><span class="special">)</span>
441     <span class="special">{</span>
442         <span class="comment">// We use the Beast ssl_stream wrapped around a beast tcp_stream.</span>
443         <span class="identifier">ssl_stream</span><span class="special">&lt;</span><span class="identifier">tcp_stream</span><span class="special">&gt;</span> <span class="identifier">stream</span><span class="special">(</span><span class="identifier">ioc</span><span class="special">,</span> <span class="identifier">ctx</span><span class="special">);</span>
444
445         <span class="comment">// The resolver will be used to look up the IP addresses for the host name</span>
446         <span class="identifier">net</span><span class="special">::</span><span class="identifier">ip</span><span class="special">::</span><span class="identifier">tcp</span><span class="special">::</span><span class="identifier">resolver</span> <span class="identifier">resolver</span><span class="special">(</span><span class="identifier">ioc</span><span class="special">);</span>
447
448         <span class="comment">// First, look up the name. Networking has its own timeout for this.</span>
449         <span class="comment">// The `yield` object is a CompletionToken which specializes the</span>
450         <span class="comment">// `net::async_result` customization point to make the fiber work.</span>
451         <span class="comment">//</span>
452         <span class="comment">// This call will appear to "block" until the operation completes.</span>
453         <span class="comment">// It isn't really blocking. Instead, the fiber implementation saves</span>
454         <span class="comment">// the call stack and suspends the function until the asynchronous</span>
455         <span class="comment">// operation is complete. Then it restores the call stack, and resumes</span>
456         <span class="comment">// the function to the statement following the async_resolve. This</span>
457         <span class="comment">// allows an asynchronous algorithm to be expressed synchronously.</span>
458
459         <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">endpoints</span> <span class="special">=</span> <span class="identifier">resolver</span><span class="special">.</span><span class="identifier">async_resolve</span><span class="special">(</span><span class="identifier">host</span><span class="special">,</span> <span class="string">"https"</span><span class="special">,</span> <span class="special">{},</span> <span class="identifier">yield</span><span class="special">[</span><span class="identifier">ec</span><span class="special">]);</span>
460         <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span>
461             <span class="keyword">return</span><span class="special">;</span>
462
463         <span class="comment">// The function `get_lowest_layer` retrieves the "bottom most" object</span>
464         <span class="comment">// in the stack of stream layers. In this case it will be the tcp_stream.</span>
465         <span class="comment">// This timeout will apply to all subsequent operations collectively.</span>
466         <span class="comment">// That is to say, they must all complete within the same 30 second</span>
467         <span class="comment">// window.</span>
468
469         <span class="identifier">get_lowest_layer</span><span class="special">(</span><span class="identifier">stream</span><span class="special">).</span><span class="identifier">expires_after</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">seconds</span><span class="special">(</span><span class="number">30</span><span class="special">));</span>
470
471         <span class="comment">// `tcp_stream` range connect algorithms are member functions, unlike net::</span>
472         <span class="identifier">get_lowest_layer</span><span class="special">(</span><span class="identifier">stream</span><span class="special">).</span><span class="identifier">async_connect</span><span class="special">(</span><span class="identifier">endpoints</span><span class="special">,</span> <span class="identifier">yield</span><span class="special">[</span><span class="identifier">ec</span><span class="special">]);</span>
473         <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span>
474             <span class="keyword">return</span><span class="special">;</span>
475
476         <span class="comment">// Perform the TLS handshake</span>
477         <span class="identifier">stream</span><span class="special">.</span><span class="identifier">async_handshake</span><span class="special">(</span><span class="identifier">net</span><span class="special">::</span><span class="identifier">ssl</span><span class="special">::</span><span class="identifier">stream_base</span><span class="special">::</span><span class="identifier">client</span><span class="special">,</span> <span class="identifier">yield</span><span class="special">[</span><span class="identifier">ec</span><span class="special">]);</span>
478         <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span>
479             <span class="keyword">return</span><span class="special">;</span>
480
481         <span class="comment">// Send an HTTP GET request for the target</span>
482         <span class="special">{</span>
483             <span class="identifier">http</span><span class="special">::</span><span class="identifier">request</span><span class="special">&lt;</span><span class="identifier">http</span><span class="special">::</span><span class="identifier">empty_body</span><span class="special">&gt;</span> <span class="identifier">req</span><span class="special">;</span>
484             <span class="identifier">req</span><span class="special">.</span><span class="identifier">method</span><span class="special">(</span><span class="identifier">http</span><span class="special">::</span><span class="identifier">verb</span><span class="special">::</span><span class="identifier">get</span><span class="special">);</span>
485             <span class="identifier">req</span><span class="special">.</span><span class="identifier">target</span><span class="special">(</span><span class="identifier">target</span><span class="special">);</span>
486             <span class="identifier">req</span><span class="special">.</span><span class="identifier">version</span><span class="special">(</span><span class="number">11</span><span class="special">);</span>
487             <span class="identifier">req</span><span class="special">.</span><span class="identifier">set</span><span class="special">(</span><span class="identifier">http</span><span class="special">::</span><span class="identifier">field</span><span class="special">::</span><span class="identifier">host</span><span class="special">,</span> <span class="identifier">host</span><span class="special">);</span>
488             <span class="identifier">req</span><span class="special">.</span><span class="identifier">set</span><span class="special">(</span><span class="identifier">http</span><span class="special">::</span><span class="identifier">field</span><span class="special">::</span><span class="identifier">user_agent</span><span class="special">,</span> <span class="string">"Beast"</span><span class="special">);</span>
489             <span class="identifier">http</span><span class="special">::</span><span class="identifier">async_write</span><span class="special">(</span><span class="identifier">stream</span><span class="special">,</span> <span class="identifier">req</span><span class="special">,</span> <span class="identifier">yield</span><span class="special">[</span><span class="identifier">ec</span><span class="special">]);</span>
490             <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span>
491                 <span class="keyword">return</span><span class="special">;</span>
492         <span class="special">}</span>
493
494         <span class="comment">// Now read the response</span>
495         <span class="identifier">flat_buffer</span> <span class="identifier">buffer</span><span class="special">;</span>
496         <span class="identifier">http</span><span class="special">::</span><span class="identifier">response</span><span class="special">&lt;</span><span class="identifier">http</span><span class="special">::</span><span class="identifier">string_body</span><span class="special">&gt;</span> <span class="identifier">res</span><span class="special">;</span>
497         <span class="identifier">http</span><span class="special">::</span><span class="identifier">async_read</span><span class="special">(</span><span class="identifier">stream</span><span class="special">,</span> <span class="identifier">buffer</span><span class="special">,</span> <span class="identifier">res</span><span class="special">,</span> <span class="identifier">yield</span><span class="special">[</span><span class="identifier">ec</span><span class="special">]);</span>
498         <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span>
499             <span class="keyword">return</span><span class="special">;</span>
500
501         <span class="comment">// Try to perform the TLS shutdown handshake</span>
502         <span class="identifier">stream</span><span class="special">.</span><span class="identifier">async_shutdown</span><span class="special">(</span><span class="identifier">yield</span><span class="special">[</span><span class="identifier">ec</span><span class="special">]);</span>
503
504         <span class="comment">// `net::ssl::error::stream_truncated`, also known as an SSL "short read",</span>
505         <span class="comment">// indicates the peer closed the connection without performing the</span>
506         <span class="comment">// required closing handshake (for example, Google does this to</span>
507         <span class="comment">// improve performance). Generally this can be a security issue,</span>
508         <span class="comment">// but if your communication protocol is self-terminated (as</span>
509         <span class="comment">// it is with both HTTP and WebSocket) then you may simply</span>
510         <span class="comment">// ignore the lack of close_notify:</span>
511         <span class="comment">//</span>
512         <span class="comment">// https://github.com/boostorg/beast/issues/38</span>
513         <span class="comment">//</span>
514         <span class="comment">// https://security.stackexchange.com/questions/91435/how-to-handle-a-malicious-ssl-tls-shutdown</span>
515         <span class="comment">//</span>
516         <span class="comment">// When a short read would cut off the end of an HTTP message,</span>
517         <span class="comment">// Beast returns the error beast::http::error::partial_message.</span>
518         <span class="comment">// Therefore, if we see a short read here, it has occurred</span>
519         <span class="comment">// after the message has been completed, so it is safe to ignore it.</span>
520
521         <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span> <span class="special">==</span> <span class="identifier">net</span><span class="special">::</span><span class="identifier">ssl</span><span class="special">::</span><span class="identifier">error</span><span class="special">::</span><span class="identifier">stream_truncated</span><span class="special">)</span>
522             <span class="identifier">ec</span> <span class="special">=</span> <span class="special">{};</span>
523         <span class="keyword">else</span> <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span>
524             <span class="keyword">return</span><span class="special">;</span>
525
526         <span class="comment">// Set the string to return to the caller</span>
527         <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">res</span><span class="special">.</span><span class="identifier">body</span><span class="special">());</span>
528     <span class="special">});</span>
529
530     <span class="comment">// `run` will dispatch completion handlers, and block until there is</span>
531     <span class="comment">// no more "work" remaining. When this call returns, the operations</span>
532     <span class="comment">// are complete and we can give the caller the result.</span>
533     <span class="identifier">ioc</span><span class="special">.</span><span class="identifier">run</span><span class="special">();</span>
534
535     <span class="keyword">return</span> <span class="identifier">result</span><span class="special">;</span>
536 <span class="special">}</span>
537 </pre>
538 </div>
539 <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
540 <td align="left"></td>
541 <td align="right"><div class="copyright-footer">Copyright &#169; 2016-2019 Vinnie
542       Falco<p>
543         Distributed under the Boost Software License, Version 1.0. (See accompanying
544         file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
545       </p>
546 </div></td>
547 </tr></table>
548 <hr>
549 <div class="spirit-nav">
550 <a accesskey="p" href="stream_types.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../using_io.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="rate_limiting.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
551 </div>
552 </body>
553 </html>