Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / beast / _experimental / http / icy_stream.hpp
1 //
2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9
10 #ifndef BOOST_BEAST_HTTP_ICY_STREAM_HPP
11 #define BOOST_BEAST_HTTP_ICY_STREAM_HPP
12
13 #include <boost/beast/core/detail/config.hpp>
14 #include <boost/beast/core/error.hpp>
15 #include <boost/asio/async_result.hpp>
16 #include <boost/asio/buffer.hpp>
17 #include <boost/logic/tribool.hpp>
18 #include <type_traits>
19
20 namespace boost {
21 namespace beast {
22 namespace http {
23
24 /** Stream wrapper to process Shoutcast HTTP responses
25
26     This wrapper replaces the word "ICY" in the first
27     HTTP response received on the connection, with "HTTP/1.1".
28     This allows the Beast parser to be used with Shoutcast
29     servers, which send a non-standard HTTP message as the
30     response.
31
32     For asynchronous operations, the application must ensure
33     that they are are all performed within the same implicit
34     or explicit strand.
35
36     @par Thread Safety
37     @e Distinct @e objects: Safe.@n
38     @e Shared @e objects: Unsafe.
39     The application must also ensure that all asynchronous
40     operations are performed within the same implicit or explicit strand.
41
42     @par Example
43     To use the @ref icy_stream template with an @ref tcp_stream
44     you would write:
45     @code
46     http::icy_stream<tcp_stream> is(ioc);
47     @endcode
48
49     @tparam NextLayer The type representing the next layer, to which
50     data will be read and written during operations. For synchronous
51     operations, the type must support the <em>SyncStream</em> concept.
52     For asynchronous operations, the type must support the
53     <em>AsyncStream</em> concept.
54
55     @note A stream object must not be moved or destroyed while there
56     are pending asynchronous operations associated with it.
57
58     @par Concepts
59     <em>AsyncStream</em>, <em>SyncStream</em>
60 */
61 template<class NextLayer>
62 class icy_stream
63 {
64     NextLayer stream_;
65     char buf_[8];
66     unsigned char n_ = 0;
67     bool detect_ = true;
68
69     struct ops;
70
71     static
72     net::const_buffer
73     version()
74     {
75         return {"HTTP/1.1", 8};
76     }
77
78 public:
79     /// The type of the next layer.
80     using next_layer_type =
81         typename std::remove_reference<NextLayer>::type;
82
83     /// The type of the executor associated with the object.
84     using executor_type = typename next_layer_type::executor_type;
85
86     icy_stream(icy_stream&&) = default;
87     icy_stream(icy_stream const&) = default;
88     icy_stream& operator=(icy_stream&&) = default;
89     icy_stream& operator=(icy_stream const&) = default;
90
91     /** Destructor
92
93         The treatment of pending operations will be the same as that
94         of the next layer.
95     */
96     ~icy_stream() = default;
97
98     /** Constructor
99
100         Arguments, if any, are forwarded to the next layer's constructor.
101     */
102     template<class... Args>
103     explicit
104     icy_stream(Args&&... args);
105
106     //--------------------------------------------------------------------------
107
108     /** Get the executor associated with the object.
109     
110         This function may be used to obtain the executor object that the
111         stream uses to dispatch handlers for asynchronous operations.
112
113         @return A copy of the executor that stream will use to dispatch handlers.
114     */
115     executor_type
116     get_executor() noexcept
117     {
118         return stream_.get_executor();
119     }
120
121     /** Get a reference to the next layer
122
123         This function returns a reference to the next layer
124         in a stack of stream layers.
125
126         @return A reference to the next layer in the stack of
127         stream layers.
128     */
129     next_layer_type&
130     next_layer()
131     {
132         return stream_;
133     }
134
135     /** Get a reference to the next layer
136
137         This function returns a reference to the next layer in a
138         stack of stream layers.
139
140         @return A reference to the next layer in the stack of
141         stream layers.
142     */
143     next_layer_type const&
144     next_layer() const
145     {
146         return stream_;
147     }
148
149     //--------------------------------------------------------------------------
150
151     /** Read some data from the stream.
152
153         This function is used to read data from the stream. The function call will
154         block until one or more bytes of data has been read successfully, or until
155         an error occurs.
156         
157         @param buffers The buffers into which the data will be read.
158         
159         @returns The number of bytes read.
160         
161         @throws system_error Thrown on failure.
162         
163         @note The `read_some` operation may not read all of the requested number of
164         bytes. Consider using the function `net::read` if you need to ensure
165         that the requested amount of data is read before the blocking operation
166         completes.
167     */
168     template<class MutableBufferSequence>
169     std::size_t
170     read_some(MutableBufferSequence const& buffers);
171
172     /** Read some data from the stream.
173
174         This function is used to read data from the stream. The function call will
175         block until one or more bytes of data has been read successfully, or until
176         an error occurs.
177         
178         @param buffers The buffers into which the data will be read.
179         
180         @param ec Set to indicate what error occurred, if any.
181
182         @returns The number of bytes read.
183                 
184         @note The `read_some` operation may not read all of the requested number of
185         bytes. Consider using the function `net::read` if you need to ensure
186         that the requested amount of data is read before the blocking operation
187         completes.
188     */
189     template<class MutableBufferSequence>
190     std::size_t
191     read_some(
192         MutableBufferSequence const& buffers,
193         error_code& ec);
194
195     /** Start an asynchronous read.
196     
197         This function is used to asynchronously read one or more bytes of data from
198         the stream. The function call always returns immediately.
199         
200         @param buffers The buffers into which the data will be read. Although the
201         buffers object may be copied as necessary, ownership of the underlying
202         buffers is retained by the caller, which must guarantee that they remain
203         valid until the handler is called.
204
205         @param handler The completion handler to invoke when the operation
206         completes. The implementation takes ownership of the handler by
207         performing a decay-copy. The equivalent function signature of
208         the handler must be:
209         @code
210         void handler(
211           const boost::system::error_code& error, // Result of operation.
212           std::size_t bytes_transferred           // Number of bytes read.
213         );
214         @endcode
215         Regardless of whether the asynchronous operation completes
216         immediately or not, the handler will not be invoked from within
217         this function. Invocation of the handler will be performed in a
218         manner equivalent to using `net::post`.
219
220         @note The `async_read_some` operation may not read all of the requested number of
221         bytes. Consider using the function `net::async_read` if you need
222         to ensure that the requested amount of data is read before the asynchronous
223         operation completes.
224     */
225     template<
226         class MutableBufferSequence,
227         BOOST_BEAST_ASYNC_TPARAM2 ReadHandler =
228             net::default_completion_token_t<executor_type>
229     >
230     BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
231     async_read_some(
232         MutableBufferSequence const& buffers,
233         ReadHandler&& handler =
234             net::default_completion_token_t<executor_type>{});
235
236     /** Write some data to the stream.
237     
238         This function is used to write data on the stream. The function call will
239         block until one or more bytes of data has been written successfully, or
240         until an error occurs.
241         
242         @param buffers The data to be written.
243         
244         @returns The number of bytes written.
245         
246         @throws system_error Thrown on failure.
247         
248         @note The `write_some` operation may not transmit all of the data to the
249         peer. Consider using the function `net::write` if you need to
250         ensure that all data is written before the blocking operation completes.
251     */
252     template<class ConstBufferSequence>
253     std::size_t
254     write_some(ConstBufferSequence const& buffers);
255
256     /** Write some data to the stream.
257     
258         This function is used to write data on the stream. The function call will
259         block until one or more bytes of data has been written successfully, or
260         until an error occurs.
261         
262         @param buffers The data to be written.
263         
264         @param ec Set to indicate what error occurred, if any.
265
266         @returns The number of bytes written.
267                 
268         @note The `write_some` operation may not transmit all of the data to the
269         peer. Consider using the function `net::write` if you need to
270         ensure that all data is written before the blocking operation completes.
271     */
272     template<class ConstBufferSequence>
273     std::size_t
274     write_some(
275         ConstBufferSequence const& buffers,
276         error_code& ec);
277
278     /** Start an asynchronous write.
279         
280         This function is used to asynchronously write one or more bytes of data to
281         the stream. The function call always returns immediately.
282         
283         @param buffers The data to be written to the stream. Although the buffers
284         object may be copied as necessary, ownership of the underlying buffers is
285         retained by the caller, which must guarantee that they remain valid until
286         the handler is called.
287         
288         @param handler The completion handler to invoke when the operation
289         completes. The implementation takes ownership of the handler by
290         performing a decay-copy. The equivalent function signature of
291         the handler must be:
292         @code
293         void handler(
294           error_code const& error,          // Result of operation.
295           std::size_t bytes_transferred     // Number of bytes written.
296         );
297         @endcode
298         Regardless of whether the asynchronous operation completes
299         immediately or not, the handler will not be invoked from within
300         this function. Invocation of the handler will be performed in a
301         manner equivalent to using `net::post`.
302         
303         @note The `async_write_some` operation may not transmit all of the data to
304         the peer. Consider using the function `net::async_write` if you need
305         to ensure that all data is written before the asynchronous operation completes.
306     */
307     template<
308         class ConstBufferSequence,
309         BOOST_BEAST_ASYNC_TPARAM2 WriteHandler =
310             net::default_completion_token_t<executor_type>
311     >
312     BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
313     async_write_some(
314         ConstBufferSequence const& buffers,
315         WriteHandler&& handler =
316             net::default_completion_token_t<executor_type>{});
317 };
318
319 } // http
320 } // beast
321 } // boost
322
323 #include <boost/beast/_experimental/http/impl/icy_stream.hpp>
324
325 #endif