| 250 | #include <boost/asio/yield.hpp> |
| 251 | |
| 252 | void |
| 253 | loop(beast::error_code ec, std::size_t bytes_transferred) |
| 254 | { |
| 255 | boost::ignore_unused(bytes_transferred); |
| 256 | reenter(*this) |
| 257 | { |
| 258 | for(;;) |
| 259 | { |
| 260 | // Make the request empty before reading, |
| 261 | // otherwise the operation behavior is undefined. |
| 262 | req_ = {}; |
| 263 | |
| 264 | // Set the timeout. |
| 265 | stream_.expires_after(std::chrono::seconds(30)); |
| 266 | |
| 267 | // Read a request |
| 268 | yield http::async_read(stream_, buffer_, req_, |
| 269 | beast::bind_front_handler( |
| 270 | &session::loop, |
| 271 | shared_from_this())); |
| 272 | |
| 273 | if(ec == http::error::end_of_stream) |
| 274 | { |
| 275 | // The remote host closed the connection |
| 276 | break; |
| 277 | } |
| 278 | if(ec) |
| 279 | return fail(ec, "read"); |
| 280 | |
| 281 | yield { |
| 282 | // Handle request |
| 283 | http::message_generator msg = |
| 284 | handle_request(*doc_root_, std::move(req_)); |
| 285 | |
| 286 | // Determine if we should close the connection |
| 287 | keep_alive_ = msg.keep_alive(); |
| 288 | |
| 289 | // Send the response |
| 290 | beast::async_write( |
| 291 | stream_, |
| 292 | std::move(msg), |
| 293 | beast::bind_front_handler( |
| 294 | &session::loop, shared_from_this())); |
| 295 | } |
| 296 | |
| 297 | if(ec) |
| 298 | return fail(ec, "write"); |
| 299 | if(! keep_alive_) |
| 300 | { |
| 301 | // This means we should close the connection, usually because |
| 302 | // the response indicated the "Connection: close" semantic. |
| 303 | break; |
| 304 | } |
| 305 | } |
| 306 | |
| 307 | // Send a TCP shutdown |
| 308 | stream_.socket().shutdown(tcp::socket::shutdown_send, ec); |
| 309 |
nothing calls this directly
no test coverage detected