std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, CompletionCondition completion_condition, pdalboost::system::error_code& ec) { ec = pdalboost::system::error_code(); pdalboost::asio::detail::consuming_buffers< mutable_buffer, MutableBufferSequence> tmp(buffers); std::size_t total_transferred = 0; tmp.prepare(detail::adapt_completion_condition_result( completion_condition(ec, total_transferred))); while (tmp.begin() != tmp.end()) { std::size_t bytes_transferred = s.read_some(tmp, ec); tmp.consume(bytes_transferred); total_transferred += bytes_transferred; tmp.prepare(detail::adapt_completion_condition_result( completion_condition(ec, total_transferred))); } return total_transferred; }
std::size_t read(SyncReadStream& s, asio::basic_streambuf<Allocator>& b, CompletionCondition completion_condition, asio::error_code& ec) { ec = asio::error_code(); std::size_t total_transferred = 0; std::size_t max_size = detail::adapt_completion_condition_result( completion_condition(ec, total_transferred)); std::size_t bytes_available = read_size_helper(b, max_size); while (bytes_available > 0) { std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec); b.commit(bytes_transferred); total_transferred += bytes_transferred; max_size = detail::adapt_completion_condition_result( completion_condition(ec, total_transferred)); bytes_available = read_size_helper(b, max_size); } return total_transferred; }
void send_cgi_response( SyncReadStream& input, SyncWriteStream& output, error_code& ec) { static_assert(is_sync_read_stream<SyncReadStream>::value, "SyncReadStream requirements not met"); static_assert(is_sync_write_stream<SyncWriteStream>::value, "SyncWriteStream requirements not met"); using boost::asio::buffer_cast; using boost::asio::buffer_size; // Set up the response. We use the buffer_body type, // allowing serialization to use manually provided buffers. response<buffer_body> res; res.result(status::ok); res.version = 11; res.set(field::server, "Beast"); res.set(field::transfer_encoding, "chunked"); // No data yet, but we set more = true to indicate // that it might be coming later. Otherwise the // serializer::is_done would return true right after // sending the header. res.body.data = nullptr; res.body.more = true; // Create the serializer. response_serializer<buffer_body, fields> sr{res}; // Send the header immediately. write_header(output, sr, ec); if(ec) return; // Alternate between reading from the child process // and sending all the process output until there // is no more output. do { // Read a buffer from the child process char buffer[2048]; auto bytes_transferred = input.read_some( boost::asio::buffer(buffer, sizeof(buffer)), ec); if(ec == boost::asio::error::eof) { ec = {}; // `nullptr` indicates there is no buffer res.body.data = nullptr; // `false` means no more data is coming res.body.more = false; } else { if(ec) return; // Point to our buffer with the bytes that // we received, and indicate that there may // be some more data coming res.body.data = buffer; res.body.size = bytes_transferred; res.body.more = true; } // Write everything in the body buffer write(output, sr, ec); // This error is returned by body_buffer during // serialization when it is done sending the data // provided and needs another buffer. if(ec == error::need_buffer) { ec = {}; continue; } if(ec) return; } while(! sr.is_done()); }