@@ -114,7 +114,7 @@ void connection::handle_http_line(const boost::system::error_code& ec)
114114 }
115115 else
116116 {
117- m_request.reply (status_codes::InternalError );
117+ m_request.reply (status_codes::BadRequest );
118118 do_response ();
119119 }
120120 }
@@ -252,7 +252,13 @@ void connection::handle_chunked_body(const boost::system::error_code& ec, int to
252252 if (!ec)
253253 {
254254 auto writebuf = m_request._get_impl ()->outstream ().streambuf ();
255- writebuf.putn (buffer_cast<const uint8_t *>(m_request_buf.data ()), toWrite).then ([=](size_t ) {
255+ writebuf.putn (buffer_cast<const uint8_t *>(m_request_buf.data ()), toWrite).then ([=](pplx::task<size_t > writeChunkTask) {
256+ try {
257+ writeChunkTask.get ();
258+ } catch (...) {
259+ m_request._reply_if_not_already (status_codes::InternalError);
260+ return ;
261+ }
256262 m_request_buf.consume (2 + toWrite);
257263
258264 boost::asio::async_read_until (*m_socket, m_request_buf, CRLF,
@@ -275,7 +281,14 @@ void connection::handle_body(const boost::system::error_code& ec)
275281 else if (m_read < m_read_size) // there is more to read
276282 {
277283 auto writebuf = m_request._get_impl ()->outstream ().streambuf ();
278- writebuf.putn (boost::asio::buffer_cast<const uint8_t *>(m_request_buf.data ()), std::min (m_request_buf.size (), m_read_size - m_read)).then ([=](size_t writtenSize) {
284+ writebuf.putn (boost::asio::buffer_cast<const uint8_t *>(m_request_buf.data ()), std::min (m_request_buf.size (), m_read_size - m_read)).then ([=](pplx::task<size_t > writtenSizeTask) {
285+ size_t writtenSize = 0 ;
286+ try {
287+ writtenSize = writtenSizeTask.get ();
288+ } catch (...) {
289+ m_request._reply_if_not_already (status_codes::InternalError);
290+ return ;
291+ }
279292 m_read += writtenSize;
280293 m_request_buf.consume (writtenSize);
281294 async_read_until_buffersize (std::min (ChunkSize, m_read_size - m_read), boost::bind (&connection::handle_body, this , placeholders::error));
@@ -457,16 +470,33 @@ void connection::async_process_response(http_response response)
457470 boost::asio::async_write (*m_socket, m_response_buf, boost::bind (&connection::handle_headers_written, this , response, placeholders::error));
458471}
459472
473+ void connection::cancel_sending_response_with_error (http_response response, std::exception_ptr eptr)
474+ {
475+ auto * context = static_cast <linux_request_context*>(response._get_server_context ());
476+ context->m_response_completed .set_exception (eptr);
477+ // always terminate the connection since error happens
478+ finish_request_response ();
479+ }
480+
460481
461482void connection::handle_write_chunked_response (http_response response, const boost::system::error_code& ec)
462483{
463484 if (ec)
464485 return handle_response_written (response, ec);
465486
466487 auto readbuf = response._get_impl ()->instream ().streambuf ();
488+ if (readbuf.is_eof ())
489+ return cancel_sending_response_with_error (response, std::make_exception_ptr (http_exception (" Response stream close early!" )));
467490 auto membuf = m_response_buf.prepare (ChunkSize + http::details::chunked_encoding::additional_encoding_space);
468491
469- readbuf.getn (buffer_cast<uint8_t *>(membuf) + http::details::chunked_encoding::data_offset, ChunkSize).then ([=](size_t actualSize) {
492+ readbuf.getn (buffer_cast<uint8_t *>(membuf) + http::details::chunked_encoding::data_offset, ChunkSize).then ([=](pplx::task<size_t > actualSizeTask) {
493+
494+ size_t actualSize = 0 ;
495+ try {
496+ actualSize = actualSizeTask.get ();
497+ } catch (...) {
498+ return cancel_sending_response_with_error (response, std::current_exception ());
499+ }
470500 size_t offset = http::details::chunked_encoding::add_chunked_delimiters (buffer_cast<uint8_t *>(membuf), ChunkSize+http::details::chunked_encoding::additional_encoding_space, actualSize);
471501 m_response_buf.commit (actualSize + http::details::chunked_encoding::additional_encoding_space);
472502 m_response_buf.consume (offset);
@@ -482,8 +512,16 @@ void connection::handle_write_large_response(http_response response, const boost
482512 return handle_response_written (response, ec);
483513
484514 auto readbuf = response._get_impl ()->instream ().streambuf ();
515+ if (readbuf.is_eof ())
516+ return cancel_sending_response_with_error (response, std::make_exception_ptr (http_exception (" Response stream close early!" )));
485517 size_t readBytes = std::min (ChunkSize, m_write_size - m_write);
486- readbuf.getn (buffer_cast<uint8_t *>(m_response_buf.prepare (readBytes)), readBytes).then ([=](size_t actualSize) {
518+ readbuf.getn (buffer_cast<uint8_t *>(m_response_buf.prepare (readBytes)), readBytes).then ([=](pplx::task<size_t > actualSizeTask) {
519+ size_t actualSize = 0 ;
520+ try {
521+ actualSize = actualSizeTask.get ();
522+ } catch (...) {
523+ return cancel_sending_response_with_error (response, std::current_exception ());
524+ }
487525 m_write += actualSize;
488526 m_response_buf.commit (actualSize);
489527 boost::asio::async_write (*m_socket, m_response_buf, boost::bind (&connection::handle_write_large_response, this , response, placeholders::error));
@@ -494,9 +532,7 @@ void connection::handle_headers_written(http_response response, const boost::sys
494532{
495533 if (ec)
496534 {
497- auto * context = static_cast <linux_request_context*>(response._get_server_context ());
498- context->m_response_completed .set_exception (std::runtime_error (" error writing headers" ));
499- finish_request_response ();
535+ return cancel_sending_response_with_error (response, std::make_exception_ptr (http_exception (" error writing headers" )));
500536 }
501537 else
502538 {
@@ -512,9 +548,7 @@ void connection::handle_response_written(http_response response, const boost::sy
512548 auto * context = static_cast <linux_request_context*>(response._get_server_context ());
513549 if (ec)
514550 {
515- // printf("-> boost::system::error_code %d in handle_response_written\n", ec.value());
516- context->m_response_completed .set_exception (std::runtime_error (" error writing response" ));
517- finish_request_response ();
551+ return cancel_sending_response_with_error (response, std::make_exception_ptr (http_exception (" error writing response" )));
518552 }
519553 else
520554 {
@@ -532,7 +566,6 @@ void connection::handle_response_written(http_response response, const boost::sy
532566
533567void connection::finish_request_response ()
534568{
535- // usleep(100000);
536569 // kill the connection
537570 {
538571 pplx::scoped_lock<pplx::extensibility::recursive_lock_t > lock (m_p_parent->m_connections_lock );
@@ -548,7 +581,6 @@ void connection::finish_request_response()
548581
549582void hostport_listener::stop ()
550583{
551-
552584 // halt existing connections
553585 {
554586 pplx::scoped_lock<pplx::extensibility::recursive_lock_t > lock (m_connections_lock);
0 commit comments