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
20namespace boost {
21namespace beast {
22namespace 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*/
61template<class NextLayer>
62class 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
78public:
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 If the handler has an associated immediate executor,
216 an immediate completion will be dispatched to it.
217 Otherwise, the handler will not be invoked from within
218 this function. Invocation of the handler will be performed
219 by dispatching to the immediate executor. If no
220 immediate executor is specified, this is equivalent
221 to using `net::post`.
222 @note The `async_read_some` operation may not read all of the requested number of
223 bytes. Consider using the function `net::async_read` if you need
224 to ensure that the requested amount of data is read before the asynchronous
225 operation completes.
226 */
227 template<
228 class MutableBufferSequence,
229 BOOST_BEAST_ASYNC_TPARAM2 ReadHandler =
230 net::default_completion_token_t<executor_type>
231 >
232 BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
233 async_read_some(
234 MutableBufferSequence const& buffers,
235 ReadHandler&& handler =
236 net::default_completion_token_t<executor_type>{});
237
238 /** Write some data to the stream.
239
240 This function is used to write data on the stream. The function call will
241 block until one or more bytes of data has been written successfully, or
242 until an error occurs.
243
244 @param buffers The data to be written.
245
246 @returns The number of bytes written.
247
248 @throws system_error Thrown on failure.
249
250 @note The `write_some` operation may not transmit all of the data to the
251 peer. Consider using the function `net::write` if you need to
252 ensure that all data is written before the blocking operation completes.
253 */
254 template<class ConstBufferSequence>
255 std::size_t
256 write_some(ConstBufferSequence const& buffers);
257
258 /** Write some data to the stream.
259
260 This function is used to write data on the stream. The function call will
261 block until one or more bytes of data has been written successfully, or
262 until an error occurs.
263
264 @param buffers The data to be written.
265
266 @param ec Set to indicate what error occurred, if any.
267
268 @returns The number of bytes written.
269
270 @note The `write_some` operation may not transmit all of the data to the
271 peer. Consider using the function `net::write` if you need to
272 ensure that all data is written before the blocking operation completes.
273 */
274 template<class ConstBufferSequence>
275 std::size_t
276 write_some(
277 ConstBufferSequence const& buffers,
278 error_code& ec);
279
280 /** Start an asynchronous write.
281
282 This function is used to asynchronously write one or more bytes of data to
283 the stream. The function call always returns immediately.
284
285 @param buffers The data to be written to the stream. Although the buffers
286 object may be copied as necessary, ownership of the underlying buffers is
287 retained by the caller, which must guarantee that they remain valid until
288 the handler is called.
289
290 @param handler The completion handler to invoke when the operation
291 completes. The implementation takes ownership of the handler by
292 performing a decay-copy. The equivalent function signature of
293 the handler must be:
294 @code
295 void handler(
296 error_code const& error, // Result of operation.
297 std::size_t bytes_transferred // Number of bytes written.
298 );
299 @endcode
300 If the handler has an associated immediate executor,
301 an immediate completion will be dispatched to it.
302 Otherwise, the handler will not be invoked from within
303 this function. Invocation of the handler will be performed
304 by dispatching to the immediate executor. If no
305 immediate executor is specified, this is equivalent
306 to using `net::post`.
307 @note The `async_write_some` operation may not transmit all of the data to
308 the peer. Consider using the function `net::async_write` if you need
309 to ensure that all data is written before the asynchronous operation completes.
310 */
311 template<
312 class ConstBufferSequence,
313 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler =
314 net::default_completion_token_t<executor_type>
315 >
316 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
317 async_write_some(
318 ConstBufferSequence const& buffers,
319 WriteHandler&& handler =
320 net::default_completion_token_t<executor_type>{});
321};
322
323} // http
324} // beast
325} // boost
326
327#include <boost/beast/_experimental/http/impl/icy_stream.hpp>
328
329#endif
330

source code of boost/libs/beast/include/boost/beast/_experimental/http/icy_stream.hpp