Example #1
0
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;
}
Example #2
0
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;
}
Example #3
0
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());
}