]> git.proxmox.com Git - ceph.git/blob - ceph/src/Beast/include/beast/http/impl/read.ipp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / Beast / include / beast / http / impl / read.ipp
1 //
2 // Copyright (c) 2013-2017 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
8 #ifndef BEAST_HTTP_IMPL_READ_IPP_HPP
9 #define BEAST_HTTP_IMPL_READ_IPP_HPP
10
11 #include <beast/http/concepts.hpp>
12 #include <beast/http/error.hpp>
13 #include <beast/http/message_parser.hpp>
14 #include <beast/http/read.hpp>
15 #include <beast/core/bind_handler.hpp>
16 #include <beast/core/handler_helpers.hpp>
17 #include <beast/core/handler_ptr.hpp>
18 #include <beast/core/stream_concepts.hpp>
19 #include <boost/assert.hpp>
20 #include <boost/optional.hpp>
21
22 namespace beast {
23 namespace http {
24
25 namespace detail {
26
27 template<
28 class SyncReadStream,
29 class DynamicBuffer,
30 bool isRequest, bool isDirect, class Derived>
31 inline
32 std::size_t
33 read_some_buffer(
34 SyncReadStream& stream,
35 DynamicBuffer& dynabuf,
36 basic_parser<isRequest, isDirect, Derived>& parser,
37 error_code& ec)
38 {
39 std::size_t bytes_used;
40 if(dynabuf.size() == 0)
41 goto do_read;
42 for(;;)
43 {
44 bytes_used = parser.write(
45 dynabuf.data(), ec);
46 if(ec)
47 return 0;
48 if(bytes_used > 0)
49 goto do_finish;
50 do_read:
51 boost::optional<typename
52 DynamicBuffer::mutable_buffers_type> mb;
53 auto const size =
54 read_size_helper(dynabuf, 65536);
55 BOOST_ASSERT(size > 0);
56 try
57 {
58 mb.emplace(dynabuf.prepare(size));
59 }
60 catch(std::length_error const&)
61 {
62 ec = error::buffer_overflow;
63 return 0;
64 }
65 auto const bytes_transferred =
66 stream.read_some(*mb, ec);
67 if(ec == boost::asio::error::eof)
68 {
69 BOOST_ASSERT(bytes_transferred == 0);
70 bytes_used = 0;
71 if(parser.got_some())
72 {
73 // caller sees EOF on next read
74 ec = {};
75 parser.write_eof(ec);
76 if(ec)
77 return 0;
78 BOOST_ASSERT(parser.is_complete());
79 }
80 break;
81 }
82 else if(ec)
83 {
84 return 0;
85 }
86 BOOST_ASSERT(bytes_transferred > 0);
87 dynabuf.commit(bytes_transferred);
88 }
89 do_finish:
90 return bytes_used;
91 }
92
93 template<
94 class SyncReadStream,
95 class DynamicBuffer,
96 bool isRequest, class Derived>
97 inline
98 std::size_t
99 read_some_body(
100 SyncReadStream& stream,
101 DynamicBuffer& dynabuf,
102 basic_parser<isRequest, true, Derived>& parser,
103 error_code& ec)
104 {
105 if(dynabuf.size() > 0)
106 return parser.copy_body(dynabuf);
107 boost::optional<typename
108 Derived::mutable_buffers_type> mb;
109 try
110 {
111 parser.prepare_body(mb, 65536);
112 }
113 catch(std::length_error const&)
114 {
115 ec = error::buffer_overflow;
116 return 0;
117 }
118 auto const bytes_transferred =
119 stream.read_some(*mb, ec);
120 if(ec == boost::asio::error::eof)
121 {
122 BOOST_ASSERT(bytes_transferred == 0);
123 // caller sees EOF on next read
124 ec = {};
125 parser.write_eof(ec);
126 if(ec)
127 return 0;
128 BOOST_ASSERT(parser.is_complete());
129 }
130 else if(! ec)
131 {
132 parser.commit_body(bytes_transferred);
133 return 0;
134 }
135 return 0;
136 }
137
138 template<
139 class SyncReadStream,
140 class DynamicBuffer,
141 bool isRequest, class Derived>
142 inline
143 std::size_t
144 read_some(
145 SyncReadStream& stream,
146 DynamicBuffer& dynabuf,
147 basic_parser<isRequest, true, Derived>& parser,
148 error_code& ec)
149 {
150 switch(parser.state())
151 {
152 case parse_state::header:
153 case parse_state::chunk_header:
154 return detail::read_some_buffer(
155 stream, dynabuf, parser, ec);
156
157 default:
158 return detail::read_some_body(
159 stream, dynabuf, parser, ec);
160 }
161 }
162
163 template<
164 class SyncReadStream,
165 class DynamicBuffer,
166 bool isRequest, class Derived>
167 inline
168 std::size_t
169 read_some(
170 SyncReadStream& stream,
171 DynamicBuffer& dynabuf,
172 basic_parser<isRequest, false, Derived>& parser,
173 error_code& ec)
174 {
175 return detail::read_some_buffer(
176 stream, dynabuf, parser, ec);
177 }
178
179 } // detail
180
181 //------------------------------------------------------------------------------
182
183 template<
184 class SyncReadStream,
185 class DynamicBuffer,
186 bool isRequest, bool isDirect, class Derived>
187 std::size_t
188 read_some(
189 SyncReadStream& stream,
190 DynamicBuffer& dynabuf,
191 basic_parser<isRequest, isDirect, Derived>& parser)
192 {
193 static_assert(is_SyncReadStream<SyncReadStream>::value,
194 "SyncReadStream requirements not met");
195 static_assert(is_DynamicBuffer<DynamicBuffer>::value,
196 "DynamicBuffer requirements not met");
197 BOOST_ASSERT(! parser.is_complete());
198 error_code ec;
199 auto const bytes_used =
200 read_some(stream, dynabuf, parser, ec);
201 if(ec)
202 throw system_error{ec};
203 return bytes_used;
204 }
205
206 template<
207 class SyncReadStream,
208 class DynamicBuffer,
209 bool isRequest, bool isDirect, class Derived>
210 std::size_t
211 read_some(
212 SyncReadStream& stream,
213 DynamicBuffer& dynabuf,
214 basic_parser<isRequest, isDirect, Derived>& parser,
215 error_code& ec)
216 {
217 static_assert(is_SyncReadStream<SyncReadStream>::value,
218 "SyncReadStream requirements not met");
219 static_assert(is_DynamicBuffer<DynamicBuffer>::value,
220 "DynamicBuffer requirements not met");
221 BOOST_ASSERT(! parser.is_complete());
222 return detail::read_some(stream, dynabuf, parser, ec);
223 }
224
225 template<
226 class SyncReadStream,
227 class DynamicBuffer,
228 bool isRequest, bool isDirect, class Derived>
229 void
230 read(
231 SyncReadStream& stream,
232 DynamicBuffer& dynabuf,
233 basic_parser<isRequest, isDirect, Derived>& parser)
234 {
235 static_assert(is_SyncReadStream<SyncReadStream>::value,
236 "SyncReadStream requirements not met");
237 static_assert(is_DynamicBuffer<DynamicBuffer>::value,
238 "DynamicBuffer requirements not met");
239 BOOST_ASSERT(! parser.is_complete());
240 error_code ec;
241 read(stream, dynabuf, parser, ec);
242 if(ec)
243 throw system_error{ec};
244 }
245
246 template<
247 class SyncReadStream,
248 class DynamicBuffer,
249 bool isRequest, bool isDirect, class Derived>
250 void
251 read(
252 SyncReadStream& stream,
253 DynamicBuffer& dynabuf,
254 basic_parser<isRequest, isDirect, Derived>& parser,
255 error_code& ec)
256 {
257 static_assert(is_SyncReadStream<SyncReadStream>::value,
258 "SyncReadStream requirements not met");
259 static_assert(is_DynamicBuffer<DynamicBuffer>::value,
260 "DynamicBuffer requirements not met");
261 BOOST_ASSERT(! parser.is_complete());
262 do
263 {
264 auto const bytes_used =
265 read_some(stream, dynabuf, parser, ec);
266 if(ec)
267 return;
268 dynabuf.consume(bytes_used);
269 }
270 while(! parser.is_complete());
271 }
272
273 template<
274 class SyncReadStream,
275 class DynamicBuffer,
276 bool isRequest, class Body, class Fields>
277 void
278 read(
279 SyncReadStream& stream,
280 DynamicBuffer& dynabuf,
281 message<isRequest, Body, Fields>& msg)
282 {
283 static_assert(is_SyncReadStream<SyncReadStream>::value,
284 "SyncReadStream requirements not met");
285 static_assert(is_DynamicBuffer<DynamicBuffer>::value,
286 "DynamicBuffer requirements not met");
287 static_assert(is_Body<Body>::value,
288 "Body requirements not met");
289 static_assert(has_reader<Body>::value,
290 "Body has no reader");
291 static_assert(is_Reader<typename Body::reader,
292 message<isRequest, Body, Fields>>::value,
293 "Reader requirements not met");
294 error_code ec;
295 beast::http::read(stream, dynabuf, msg, ec);
296 if(ec)
297 throw system_error{ec};
298 }
299
300 template<
301 class SyncReadStream,
302 class DynamicBuffer,
303 bool isRequest, class Body, class Fields>
304 void
305 read(
306 SyncReadStream& stream,
307 DynamicBuffer& dynabuf,
308 message<isRequest, Body, Fields>& msg,
309 error_code& ec)
310 {
311 static_assert(is_SyncReadStream<SyncReadStream>::value,
312 "SyncReadStream requirements not met");
313 static_assert(is_DynamicBuffer<DynamicBuffer>::value,
314 "DynamicBuffer requirements not met");
315 static_assert(is_Body<Body>::value,
316 "Body requirements not met");
317 static_assert(has_reader<Body>::value,
318 "Body has no reader");
319 static_assert(is_Reader<typename Body::reader,
320 message<isRequest, Body, Fields>>::value,
321 "Reader requirements not met");
322 message_parser<isRequest, Body, Fields> p;
323 beast::http::read(stream, dynabuf, p, ec);
324 if(ec)
325 return;
326 msg = p.release();
327 }
328
329 } // http
330 } // beast
331
332 #endif