File indexing completed on 2025-01-18 09:29:30
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_BEAST_HTTP_IMPL_SERIALIZER_HPP
0011 #define BOOST_BEAST_HTTP_IMPL_SERIALIZER_HPP
0012
0013 #include <boost/beast/core/buffer_traits.hpp>
0014 #include <boost/beast/core/detail/buffers_ref.hpp>
0015 #include <boost/beast/http/error.hpp>
0016 #include <boost/beast/http/status.hpp>
0017 #include <boost/beast/core/detail/config.hpp>
0018 #include <boost/assert.hpp>
0019 #include <ostream>
0020
0021 namespace boost {
0022 namespace beast {
0023 namespace http {
0024
0025 template<
0026 bool isRequest, class Body, class Fields>
0027 void
0028 serializer<isRequest, Body, Fields>::
0029 fwrinit(std::true_type)
0030 {
0031 fwr_.emplace(m_, m_.version(), m_.method());
0032 }
0033
0034 template<
0035 bool isRequest, class Body, class Fields>
0036 void
0037 serializer<isRequest, Body, Fields>::
0038 fwrinit(std::false_type)
0039 {
0040 fwr_.emplace(m_, m_.version(), m_.result_int());
0041 }
0042
0043 template<
0044 bool isRequest, class Body, class Fields>
0045 template<std::size_t I, class Visit>
0046 inline
0047 void
0048 serializer<isRequest, Body, Fields>::
0049 do_visit(error_code& ec, Visit& visit)
0050 {
0051 pv_.template emplace<I>(limit_, v_.template get<I>());
0052 visit(ec, beast::detail::make_buffers_ref(
0053 pv_.template get<I>()));
0054 }
0055
0056
0057
0058 template<
0059 bool isRequest, class Body, class Fields>
0060 serializer<isRequest, Body, Fields>::
0061 serializer(value_type& m)
0062 : m_(m)
0063 , wr_(m_.base(), m_.body())
0064 {
0065 }
0066
0067 template<
0068 bool isRequest, class Body, class Fields>
0069 template<class Visit>
0070 void
0071 serializer<isRequest, Body, Fields>::
0072 next(error_code& ec, Visit&& visit)
0073 {
0074 switch(s_)
0075 {
0076 case do_construct:
0077 {
0078 fwrinit(std::integral_constant<bool,
0079 isRequest>{});
0080 if(m_.chunked())
0081 goto go_init_c;
0082 s_ = do_init;
0083 BOOST_FALLTHROUGH;
0084 }
0085
0086 case do_init:
0087 {
0088 wr_.init(ec);
0089 if(ec)
0090 return;
0091 if(split_)
0092 goto go_header_only;
0093 auto result = wr_.get(ec);
0094 if(ec == error::need_more)
0095 goto go_header_only;
0096 if(ec)
0097 return;
0098 if(! result)
0099 goto go_header_only;
0100 more_ = result->second;
0101 v_.template emplace<2>(
0102 boost::in_place_init,
0103 fwr_->get(),
0104 result->first);
0105 s_ = do_header;
0106 BOOST_FALLTHROUGH;
0107 }
0108
0109 case do_header:
0110 do_visit<2>(ec, visit);
0111 break;
0112
0113 go_header_only:
0114 v_.template emplace<1>(fwr_->get());
0115 s_ = do_header_only;
0116 BOOST_FALLTHROUGH;
0117 case do_header_only:
0118 do_visit<1>(ec, visit);
0119 break;
0120
0121 case do_body:
0122 s_ = do_body + 1;
0123 BOOST_FALLTHROUGH;
0124
0125 case do_body + 1:
0126 {
0127 auto result = wr_.get(ec);
0128 if(ec)
0129 return;
0130 if(! result)
0131 goto go_complete;
0132 more_ = result->second;
0133 v_.template emplace<3>(result->first);
0134 s_ = do_body + 2;
0135 BOOST_FALLTHROUGH;
0136 }
0137
0138 case do_body + 2:
0139 do_visit<3>(ec, visit);
0140 break;
0141
0142
0143
0144 go_init_c:
0145 s_ = do_init_c;
0146 BOOST_FALLTHROUGH;
0147 case do_init_c:
0148 {
0149 wr_.init(ec);
0150 if(ec)
0151 return;
0152 if(split_)
0153 goto go_header_only_c;
0154 auto result = wr_.get(ec);
0155 if(ec == error::need_more)
0156 goto go_header_only_c;
0157 if(ec)
0158 return;
0159 if(! result)
0160 goto go_header_only_c;
0161 more_ = result->second;
0162 if(! more_)
0163 {
0164
0165 v_.template emplace<7>(
0166 boost::in_place_init,
0167 fwr_->get(),
0168 buffer_bytes(result->first),
0169 net::const_buffer{nullptr, 0},
0170 chunk_crlf{},
0171 result->first,
0172 chunk_crlf{},
0173 detail::chunk_last(),
0174 net::const_buffer{nullptr, 0},
0175 chunk_crlf{});
0176 goto go_all_c;
0177 }
0178 v_.template emplace<4>(
0179 boost::in_place_init,
0180 fwr_->get(),
0181 buffer_bytes(result->first),
0182 net::const_buffer{nullptr, 0},
0183 chunk_crlf{},
0184 result->first,
0185 chunk_crlf{});
0186 s_ = do_header_c;
0187 BOOST_FALLTHROUGH;
0188 }
0189
0190 case do_header_c:
0191 do_visit<4>(ec, visit);
0192 break;
0193
0194 go_header_only_c:
0195 v_.template emplace<1>(fwr_->get());
0196 s_ = do_header_only_c;
0197 BOOST_FALLTHROUGH;
0198
0199 case do_header_only_c:
0200 do_visit<1>(ec, visit);
0201 break;
0202
0203 case do_body_c:
0204 s_ = do_body_c + 1;
0205 BOOST_FALLTHROUGH;
0206
0207 case do_body_c + 1:
0208 {
0209 auto result = wr_.get(ec);
0210 if(ec)
0211 return;
0212 if(! result)
0213 goto go_final_c;
0214 more_ = result->second;
0215 if(! more_)
0216 {
0217
0218 v_.template emplace<6>(
0219 boost::in_place_init,
0220 buffer_bytes(result->first),
0221 net::const_buffer{nullptr, 0},
0222 chunk_crlf{},
0223 result->first,
0224 chunk_crlf{},
0225 detail::chunk_last(),
0226 net::const_buffer{nullptr, 0},
0227 chunk_crlf{});
0228 goto go_body_final_c;
0229 }
0230 v_.template emplace<5>(
0231 boost::in_place_init,
0232 buffer_bytes(result->first),
0233 net::const_buffer{nullptr, 0},
0234 chunk_crlf{},
0235 result->first,
0236 chunk_crlf{});
0237 s_ = do_body_c + 2;
0238 BOOST_FALLTHROUGH;
0239 }
0240
0241 case do_body_c + 2:
0242 do_visit<5>(ec, visit);
0243 break;
0244
0245 go_body_final_c:
0246 s_ = do_body_final_c;
0247 BOOST_FALLTHROUGH;
0248 case do_body_final_c:
0249 do_visit<6>(ec, visit);
0250 break;
0251
0252 go_all_c:
0253 s_ = do_all_c;
0254 BOOST_FALLTHROUGH;
0255 case do_all_c:
0256 do_visit<7>(ec, visit);
0257 break;
0258
0259 go_final_c:
0260 case do_final_c:
0261 v_.template emplace<8>(
0262 boost::in_place_init,
0263 detail::chunk_last(),
0264 net::const_buffer{nullptr, 0},
0265 chunk_crlf{});
0266 s_ = do_final_c + 1;
0267 BOOST_FALLTHROUGH;
0268
0269 case do_final_c + 1:
0270 do_visit<8>(ec, visit);
0271 break;
0272
0273
0274
0275 default:
0276 case do_complete:
0277 BOOST_ASSERT(false);
0278 break;
0279
0280 go_complete:
0281 s_ = do_complete;
0282 break;
0283 }
0284 }
0285
0286 template<
0287 bool isRequest, class Body, class Fields>
0288 void
0289 serializer<isRequest, Body, Fields>::
0290 consume(std::size_t n)
0291 {
0292 switch(s_)
0293 {
0294 case do_header:
0295 BOOST_ASSERT(
0296 n <= buffer_bytes(v_.template get<2>()));
0297 v_.template get<2>().consume(n);
0298 if(buffer_bytes(v_.template get<2>()) > 0)
0299 break;
0300 header_done_ = true;
0301 v_.reset();
0302 if(! more_)
0303 goto go_complete;
0304 s_ = do_body + 1;
0305 break;
0306
0307 case do_header_only:
0308 BOOST_ASSERT(
0309 n <= buffer_bytes(v_.template get<1>()));
0310 v_.template get<1>().consume(n);
0311 if(buffer_bytes(v_.template get<1>()) > 0)
0312 break;
0313 fwr_ = boost::none;
0314 header_done_ = true;
0315 if(! split_)
0316 goto go_complete;
0317 s_ = do_body;
0318 break;
0319
0320 case do_body + 2:
0321 {
0322 BOOST_ASSERT(
0323 n <= buffer_bytes(v_.template get<3>()));
0324 v_.template get<3>().consume(n);
0325 if(buffer_bytes(v_.template get<3>()) > 0)
0326 break;
0327 v_.reset();
0328 if(! more_)
0329 goto go_complete;
0330 s_ = do_body + 1;
0331 break;
0332 }
0333
0334
0335
0336 case do_header_c:
0337 BOOST_ASSERT(
0338 n <= buffer_bytes(v_.template get<4>()));
0339 v_.template get<4>().consume(n);
0340 if(buffer_bytes(v_.template get<4>()) > 0)
0341 break;
0342 header_done_ = true;
0343 v_.reset();
0344 if(more_)
0345 s_ = do_body_c + 1;
0346 else
0347 s_ = do_final_c;
0348 break;
0349
0350 case do_header_only_c:
0351 {
0352 BOOST_ASSERT(
0353 n <= buffer_bytes(v_.template get<1>()));
0354 v_.template get<1>().consume(n);
0355 if(buffer_bytes(v_.template get<1>()) > 0)
0356 break;
0357 fwr_ = boost::none;
0358 header_done_ = true;
0359 if(! split_)
0360 {
0361 s_ = do_final_c;
0362 break;
0363 }
0364 s_ = do_body_c;
0365 break;
0366 }
0367
0368 case do_body_c + 2:
0369 BOOST_ASSERT(
0370 n <= buffer_bytes(v_.template get<5>()));
0371 v_.template get<5>().consume(n);
0372 if(buffer_bytes(v_.template get<5>()) > 0)
0373 break;
0374 v_.reset();
0375 if(more_)
0376 s_ = do_body_c + 1;
0377 else
0378 s_ = do_final_c;
0379 break;
0380
0381 case do_body_final_c:
0382 {
0383 BOOST_ASSERT(
0384 n <= buffer_bytes(v_.template get<6>()));
0385 v_.template get<6>().consume(n);
0386 if(buffer_bytes(v_.template get<6>()) > 0)
0387 break;
0388 v_.reset();
0389 s_ = do_complete;
0390 break;
0391 }
0392
0393 case do_all_c:
0394 {
0395 BOOST_ASSERT(
0396 n <= buffer_bytes(v_.template get<7>()));
0397 v_.template get<7>().consume(n);
0398 if(buffer_bytes(v_.template get<7>()) > 0)
0399 break;
0400 header_done_ = true;
0401 v_.reset();
0402 s_ = do_complete;
0403 break;
0404 }
0405
0406 case do_final_c + 1:
0407 BOOST_ASSERT(buffer_bytes(v_.template get<8>()));
0408 v_.template get<8>().consume(n);
0409 if(buffer_bytes(v_.template get<8>()) > 0)
0410 break;
0411 v_.reset();
0412 goto go_complete;
0413
0414
0415
0416 default:
0417 BOOST_ASSERT(false);
0418 case do_complete:
0419 break;
0420
0421 go_complete:
0422 s_ = do_complete;
0423 break;
0424 }
0425 }
0426
0427 }
0428 }
0429 }
0430
0431 #endif