2017-07-07 09:03:06 -07:00
|
|
|
//
|
2017-07-24 09:42:36 -07:00
|
|
|
// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
|
2017-07-07 09:03:06 -07:00
|
|
|
//
|
|
|
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
|
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
|
//
|
2017-07-20 13:40:34 -07:00
|
|
|
// Official repository: https://github.com/boostorg/beast
|
|
|
|
|
//
|
2017-07-07 09:03:06 -07:00
|
|
|
|
2017-07-20 13:40:34 -07:00
|
|
|
#ifndef BOOST_BEAST_HTTP_IMPL_FILE_BODY_WIN32_IPP
|
|
|
|
|
#define BOOST_BEAST_HTTP_IMPL_FILE_BODY_WIN32_IPP
|
2017-07-07 09:03:06 -07:00
|
|
|
|
2017-07-20 13:40:34 -07:00
|
|
|
#if BOOST_BEAST_USE_WIN32_FILE
|
2017-07-07 09:03:06 -07:00
|
|
|
|
2017-07-20 13:40:34 -07:00
|
|
|
#include <boost/beast/core/bind_handler.hpp>
|
|
|
|
|
#include <boost/beast/core/type_traits.hpp>
|
|
|
|
|
#include <boost/beast/core/detail/clamp.hpp>
|
|
|
|
|
#include <boost/beast/http/serializer.hpp>
|
2017-09-07 07:39:52 -07:00
|
|
|
#include <boost/asio/associated_allocator.hpp>
|
|
|
|
|
#include <boost/asio/associated_executor.hpp>
|
|
|
|
|
#include <boost/asio/async_result.hpp>
|
2017-07-07 09:03:06 -07:00
|
|
|
#include <boost/asio/basic_stream_socket.hpp>
|
|
|
|
|
#include <boost/asio/handler_continuation_hook.hpp>
|
|
|
|
|
#include <boost/asio/windows/overlapped_ptr.hpp>
|
|
|
|
|
#include <boost/make_unique.hpp>
|
|
|
|
|
#include <boost/smart_ptr/make_shared_array.hpp>
|
2017-10-24 21:25:23 +03:00
|
|
|
#include <boost/winapi/basic_types.hpp>
|
2017-07-07 09:03:06 -07:00
|
|
|
#include <algorithm>
|
|
|
|
|
#include <cstring>
|
|
|
|
|
|
2017-07-20 13:40:34 -07:00
|
|
|
namespace boost {
|
2017-07-07 09:03:06 -07:00
|
|
|
namespace beast {
|
|
|
|
|
namespace http {
|
|
|
|
|
|
|
|
|
|
namespace detail {
|
2017-07-09 20:09:30 -07:00
|
|
|
template<class, class, bool, class>
|
2017-07-07 09:03:06 -07:00
|
|
|
class write_some_win32_op;
|
|
|
|
|
} // detail
|
|
|
|
|
|
|
|
|
|
template<>
|
|
|
|
|
struct basic_file_body<file_win32>
|
|
|
|
|
{
|
|
|
|
|
using file_type = file_win32;
|
|
|
|
|
|
|
|
|
|
class writer;
|
2017-10-30 17:08:52 -07:00
|
|
|
class reader;
|
2017-07-07 09:03:06 -07:00
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
class value_type
|
|
|
|
|
{
|
|
|
|
|
friend class writer;
|
2017-10-30 17:08:52 -07:00
|
|
|
friend class reader;
|
2017-07-07 09:03:06 -07:00
|
|
|
friend struct basic_file_body<file_win32>;
|
|
|
|
|
|
2017-07-09 20:09:30 -07:00
|
|
|
template<class, class, bool, class>
|
2017-07-07 09:03:06 -07:00
|
|
|
friend class detail::write_some_win32_op;
|
2017-07-09 20:09:30 -07:00
|
|
|
template<
|
|
|
|
|
class Protocol, bool isRequest, class Fields>
|
2017-07-07 09:03:06 -07:00
|
|
|
friend
|
2017-09-03 18:06:09 -07:00
|
|
|
std::size_t
|
2017-07-07 09:03:06 -07:00
|
|
|
write_some(
|
|
|
|
|
boost::asio::basic_stream_socket<Protocol>& sock,
|
2017-07-09 20:09:30 -07:00
|
|
|
serializer<isRequest,
|
|
|
|
|
basic_file_body<file_win32>, Fields>& sr,
|
2017-07-07 09:03:06 -07:00
|
|
|
error_code& ec);
|
|
|
|
|
|
|
|
|
|
file_win32 file_;
|
|
|
|
|
std::uint64_t size_ = 0; // cached file size
|
|
|
|
|
std::uint64_t first_; // starting offset of the range
|
|
|
|
|
std::uint64_t last_; // ending offset of the range
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
~value_type() = default;
|
|
|
|
|
value_type() = default;
|
|
|
|
|
value_type(value_type&& other) = default;
|
|
|
|
|
value_type& operator=(value_type&& other) = default;
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
is_open() const
|
|
|
|
|
{
|
|
|
|
|
return file_.is_open();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::uint64_t
|
|
|
|
|
size() const
|
|
|
|
|
{
|
|
|
|
|
return size_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
close();
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
open(char const* path, file_mode mode, error_code& ec);
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
reset(file_win32&& file, error_code& ec);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
2017-10-30 17:08:52 -07:00
|
|
|
class writer
|
2017-07-07 09:03:06 -07:00
|
|
|
{
|
2017-07-09 20:09:30 -07:00
|
|
|
template<class, class, bool, class>
|
2017-07-07 09:03:06 -07:00
|
|
|
friend class detail::write_some_win32_op;
|
2017-07-09 20:09:30 -07:00
|
|
|
template<
|
|
|
|
|
class Protocol, bool isRequest, class Fields>
|
2017-07-07 09:03:06 -07:00
|
|
|
friend
|
2017-09-03 18:06:09 -07:00
|
|
|
std::size_t
|
2017-07-07 09:03:06 -07:00
|
|
|
write_some(
|
|
|
|
|
boost::asio::basic_stream_socket<Protocol>& sock,
|
2017-07-09 20:09:30 -07:00
|
|
|
serializer<isRequest,
|
|
|
|
|
basic_file_body<file_win32>, Fields>& sr,
|
2017-07-07 09:03:06 -07:00
|
|
|
error_code& ec);
|
|
|
|
|
|
|
|
|
|
value_type& body_; // The body we are reading from
|
|
|
|
|
std::uint64_t pos_; // The current position in the file
|
|
|
|
|
char buf_[4096]; // Small buffer for reading
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
using const_buffers_type =
|
2017-09-07 07:39:52 -07:00
|
|
|
boost::asio::const_buffer;
|
2017-07-07 09:03:06 -07:00
|
|
|
|
|
|
|
|
template<bool isRequest, class Fields>
|
2017-10-30 17:08:52 -07:00
|
|
|
writer(message<isRequest,
|
2017-07-07 09:03:06 -07:00
|
|
|
basic_file_body<file_win32>, Fields>& m)
|
2017-09-12 12:45:52 -07:00
|
|
|
: body_(m.body())
|
2017-07-07 09:03:06 -07:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
init(error_code&)
|
|
|
|
|
{
|
|
|
|
|
BOOST_ASSERT(body_.file_.is_open());
|
|
|
|
|
pos_ = body_.first_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boost::optional<std::pair<const_buffers_type, bool>>
|
|
|
|
|
get(error_code& ec)
|
|
|
|
|
{
|
|
|
|
|
std::size_t const n = (std::min)(sizeof(buf_),
|
|
|
|
|
beast::detail::clamp(body_.last_ - pos_));
|
|
|
|
|
if(n == 0)
|
|
|
|
|
{
|
|
|
|
|
ec.assign(0, ec.category());
|
|
|
|
|
return boost::none;
|
|
|
|
|
}
|
|
|
|
|
auto const nread = body_.file_.read(buf_, n, ec);
|
|
|
|
|
if(ec)
|
|
|
|
|
return boost::none;
|
|
|
|
|
BOOST_ASSERT(nread != 0);
|
|
|
|
|
pos_ += nread;
|
|
|
|
|
ec.assign(0, ec.category());
|
|
|
|
|
return {{
|
|
|
|
|
{buf_, nread}, // buffer to return.
|
|
|
|
|
pos_ < body_.last_}}; // `true` if there are more buffers.
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
2017-10-30 17:08:52 -07:00
|
|
|
class reader
|
2017-07-07 09:03:06 -07:00
|
|
|
{
|
|
|
|
|
value_type& body_;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
template<bool isRequest, class Fields>
|
|
|
|
|
explicit
|
2017-10-30 17:08:52 -07:00
|
|
|
reader(message<isRequest, basic_file_body, Fields>& m)
|
2017-09-12 12:45:52 -07:00
|
|
|
: body_(m.body())
|
2017-07-07 09:03:06 -07:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
init(boost::optional<
|
|
|
|
|
std::uint64_t> const& content_length,
|
|
|
|
|
error_code& ec)
|
|
|
|
|
{
|
|
|
|
|
// VFALCO We could reserve space in the file
|
|
|
|
|
boost::ignore_unused(content_length);
|
|
|
|
|
BOOST_ASSERT(body_.file_.is_open());
|
|
|
|
|
ec.assign(0, ec.category());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class ConstBufferSequence>
|
|
|
|
|
std::size_t
|
|
|
|
|
put(ConstBufferSequence const& buffers,
|
|
|
|
|
error_code& ec)
|
|
|
|
|
{
|
|
|
|
|
std::size_t nwritten = 0;
|
2017-09-07 07:39:52 -07:00
|
|
|
for(auto buffer : beast::detail::buffers_range(buffers))
|
2017-07-07 09:03:06 -07:00
|
|
|
{
|
|
|
|
|
nwritten += body_.file_.write(
|
2017-09-07 07:39:52 -07:00
|
|
|
buffer.data(), buffer.size(), ec);
|
2017-07-07 09:03:06 -07:00
|
|
|
if(ec)
|
|
|
|
|
return nwritten;
|
|
|
|
|
}
|
|
|
|
|
ec.assign(0, ec.category());
|
|
|
|
|
return nwritten;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
finish(error_code& ec)
|
|
|
|
|
{
|
|
|
|
|
ec.assign(0, ec.category());
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
|
std::uint64_t
|
|
|
|
|
size(value_type const& body)
|
|
|
|
|
{
|
|
|
|
|
return body.size();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
inline
|
|
|
|
|
void
|
|
|
|
|
basic_file_body<file_win32>::
|
|
|
|
|
value_type::
|
|
|
|
|
close()
|
|
|
|
|
{
|
|
|
|
|
error_code ignored;
|
|
|
|
|
file_.close(ignored);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline
|
|
|
|
|
void
|
|
|
|
|
basic_file_body<file_win32>::
|
|
|
|
|
value_type::
|
|
|
|
|
open(char const* path, file_mode mode, error_code& ec)
|
|
|
|
|
{
|
|
|
|
|
file_.open(path, mode, ec);
|
|
|
|
|
if(ec)
|
|
|
|
|
return;
|
|
|
|
|
size_ = file_.size(ec);
|
|
|
|
|
if(ec)
|
|
|
|
|
{
|
|
|
|
|
close();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
first_ = 0;
|
|
|
|
|
last_ = size_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline
|
|
|
|
|
void
|
|
|
|
|
basic_file_body<file_win32>::
|
|
|
|
|
value_type::
|
|
|
|
|
reset(file_win32&& file, error_code& ec)
|
|
|
|
|
{
|
|
|
|
|
if(file_.is_open())
|
|
|
|
|
{
|
|
|
|
|
error_code ignored;
|
|
|
|
|
file_.close(ignored);
|
|
|
|
|
}
|
|
|
|
|
file_ = std::move(file);
|
|
|
|
|
if(file_.is_open())
|
|
|
|
|
{
|
|
|
|
|
size_ = file_.size(ec);
|
|
|
|
|
if(ec)
|
|
|
|
|
{
|
|
|
|
|
close();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
first_ = 0;
|
|
|
|
|
last_ = size_;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
|
|
|
|
|
|
template<class Unsigned>
|
|
|
|
|
inline
|
2017-10-24 21:25:23 +03:00
|
|
|
boost::winapi::DWORD_
|
2017-07-07 09:03:06 -07:00
|
|
|
lowPart(Unsigned n)
|
|
|
|
|
{
|
|
|
|
|
return static_cast<
|
2017-10-24 21:25:23 +03:00
|
|
|
boost::winapi::DWORD_>(
|
2017-07-07 09:03:06 -07:00
|
|
|
n & 0xffffffff);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class Unsigned>
|
|
|
|
|
inline
|
2017-10-24 21:25:23 +03:00
|
|
|
boost::winapi::DWORD_
|
2017-07-07 09:03:06 -07:00
|
|
|
highPart(Unsigned n, std::true_type)
|
|
|
|
|
{
|
|
|
|
|
return static_cast<
|
2017-10-24 21:25:23 +03:00
|
|
|
boost::winapi::DWORD_>(
|
2017-07-07 09:03:06 -07:00
|
|
|
(n>>32)&0xffffffff);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class Unsigned>
|
|
|
|
|
inline
|
2017-10-24 21:25:23 +03:00
|
|
|
boost::winapi::DWORD_
|
2017-07-07 09:03:06 -07:00
|
|
|
highPart(Unsigned, std::false_type)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class Unsigned>
|
|
|
|
|
inline
|
2017-10-24 21:25:23 +03:00
|
|
|
boost::winapi::DWORD_
|
2017-07-07 09:03:06 -07:00
|
|
|
highPart(Unsigned n)
|
|
|
|
|
{
|
|
|
|
|
return highPart(n, std::integral_constant<
|
|
|
|
|
bool, (sizeof(Unsigned)>4)>{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class null_lambda
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
template<class ConstBufferSequence>
|
|
|
|
|
void
|
|
|
|
|
operator()(error_code&,
|
|
|
|
|
ConstBufferSequence const&) const
|
|
|
|
|
{
|
|
|
|
|
BOOST_ASSERT(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
#if BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR
|
|
|
|
|
|
2017-07-09 20:09:30 -07:00
|
|
|
template<
|
|
|
|
|
class Protocol, class Handler,
|
|
|
|
|
bool isRequest, class Fields>
|
2017-07-07 09:03:06 -07:00
|
|
|
class write_some_win32_op
|
|
|
|
|
{
|
|
|
|
|
boost::asio::basic_stream_socket<Protocol>& sock_;
|
2017-07-09 20:09:30 -07:00
|
|
|
serializer<isRequest,
|
|
|
|
|
basic_file_body<file_win32>, Fields>& sr_;
|
2017-09-03 18:06:09 -07:00
|
|
|
std::size_t bytes_transferred_ = 0;
|
2017-07-07 09:03:06 -07:00
|
|
|
Handler h_;
|
2017-09-03 18:06:09 -07:00
|
|
|
bool header_ = false;
|
2017-07-07 09:03:06 -07:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
write_some_win32_op(write_some_win32_op&&) = default;
|
|
|
|
|
write_some_win32_op(write_some_win32_op const&) = default;
|
|
|
|
|
|
|
|
|
|
template<class DeducedHandler>
|
|
|
|
|
write_some_win32_op(
|
|
|
|
|
DeducedHandler&& h,
|
|
|
|
|
boost::asio::basic_stream_socket<Protocol>& s,
|
2017-07-09 20:09:30 -07:00
|
|
|
serializer<isRequest,
|
|
|
|
|
basic_file_body<file_win32>,Fields>& sr)
|
2017-07-07 09:03:06 -07:00
|
|
|
: sock_(s)
|
|
|
|
|
, sr_(sr)
|
|
|
|
|
, h_(std::forward<DeducedHandler>(h))
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-07 07:39:52 -07:00
|
|
|
using allocator_type =
|
|
|
|
|
boost::asio::associated_allocator_t<Handler>;
|
|
|
|
|
|
|
|
|
|
allocator_type
|
|
|
|
|
get_allocator() const noexcept
|
|
|
|
|
{
|
|
|
|
|
return boost::asio::get_associated_allocator(h_);
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-24 06:40:22 -07:00
|
|
|
using executor_type =
|
|
|
|
|
boost::asio::associated_executor_t<Handler, decltype(std::declval<
|
|
|
|
|
boost::asio::basic_stream_socket<Protocol>&>().get_executor())>;
|
2017-09-07 07:39:52 -07:00
|
|
|
|
2017-10-24 06:40:22 -07:00
|
|
|
executor_type
|
|
|
|
|
get_executor() const noexcept
|
2017-09-07 07:39:52 -07:00
|
|
|
{
|
|
|
|
|
return boost::asio::get_associated_executor(
|
|
|
|
|
h_, sock_.get_executor());
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-07 09:03:06 -07:00
|
|
|
void
|
|
|
|
|
operator()();
|
|
|
|
|
|
|
|
|
|
void
|
2017-09-03 18:06:09 -07:00
|
|
|
operator()(
|
|
|
|
|
error_code ec,
|
2017-07-07 09:03:06 -07:00
|
|
|
std::size_t bytes_transferred = 0);
|
|
|
|
|
|
|
|
|
|
friend
|
|
|
|
|
bool asio_handler_is_continuation(write_some_win32_op* op)
|
|
|
|
|
{
|
|
|
|
|
using boost::asio::asio_handler_is_continuation;
|
|
|
|
|
return asio_handler_is_continuation(
|
|
|
|
|
std::addressof(op->h_));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2017-07-09 20:09:30 -07:00
|
|
|
template<
|
|
|
|
|
class Protocol, class Handler,
|
|
|
|
|
bool isRequest, class Fields>
|
2017-07-07 09:03:06 -07:00
|
|
|
void
|
|
|
|
|
write_some_win32_op<
|
2017-07-09 20:09:30 -07:00
|
|
|
Protocol, Handler, isRequest, Fields>::
|
2017-07-07 09:03:06 -07:00
|
|
|
operator()()
|
|
|
|
|
{
|
|
|
|
|
if(! sr_.is_header_done())
|
|
|
|
|
{
|
|
|
|
|
header_ = true;
|
|
|
|
|
sr_.split(true);
|
2017-11-18 11:31:17 -08:00
|
|
|
return detail::async_write_some_impl(
|
2017-07-07 09:03:06 -07:00
|
|
|
sock_, sr_, std::move(*this));
|
|
|
|
|
}
|
2017-10-24 17:23:38 -07:00
|
|
|
if(sr_.get().chunked())
|
2017-07-07 09:03:06 -07:00
|
|
|
{
|
2017-11-18 11:31:17 -08:00
|
|
|
return detail::async_write_some_impl(
|
2017-07-07 09:03:06 -07:00
|
|
|
sock_, sr_, std::move(*this));
|
|
|
|
|
}
|
|
|
|
|
auto& r = sr_.reader_impl();
|
2017-10-24 21:25:23 +03:00
|
|
|
boost::winapi::DWORD_ const nNumberOfBytesToWrite =
|
2017-11-07 07:09:57 -08:00
|
|
|
static_cast<boost::winapi::DWORD_>(
|
|
|
|
|
(std::min<std::uint64_t>)(
|
|
|
|
|
(std::min<std::uint64_t>)(r.body_.last_ - r.pos_, sr_.limit()),
|
|
|
|
|
(std::numeric_limits<boost::winapi::DWORD_>::max)()));
|
2017-07-07 09:03:06 -07:00
|
|
|
boost::asio::windows::overlapped_ptr overlapped{
|
2017-09-07 07:39:52 -07:00
|
|
|
sock_.get_executor().context(), *this};
|
2017-07-07 09:03:06 -07:00
|
|
|
auto& ov = *overlapped.get();
|
|
|
|
|
ov.Offset = lowPart(r.pos_);
|
|
|
|
|
ov.OffsetHigh = highPart(r.pos_);
|
|
|
|
|
auto const bSuccess = ::TransmitFile(
|
|
|
|
|
sock_.native_handle(),
|
2017-09-12 12:45:52 -07:00
|
|
|
sr_.get().body().file_.native_handle(),
|
2017-07-07 09:03:06 -07:00
|
|
|
nNumberOfBytesToWrite,
|
|
|
|
|
0,
|
|
|
|
|
overlapped.get(),
|
|
|
|
|
nullptr,
|
|
|
|
|
0);
|
|
|
|
|
auto const dwError = ::GetLastError();
|
|
|
|
|
if(! bSuccess && dwError !=
|
2017-10-24 21:25:23 +03:00
|
|
|
boost::winapi::ERROR_IO_PENDING_)
|
2017-07-07 09:03:06 -07:00
|
|
|
{
|
2017-09-03 18:06:09 -07:00
|
|
|
// VFALCO This needs review, is 0 the right number?
|
|
|
|
|
// completed immediately (with error?)
|
2017-07-07 09:03:06 -07:00
|
|
|
overlapped.complete(error_code{static_cast<int>(
|
2017-10-24 21:25:23 +03:00
|
|
|
boost::winapi::GetLastError()),
|
2017-07-07 09:03:06 -07:00
|
|
|
system_category()}, 0);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
overlapped.release();
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-09 20:09:30 -07:00
|
|
|
template<
|
|
|
|
|
class Protocol, class Handler,
|
|
|
|
|
bool isRequest, class Fields>
|
2017-07-07 09:03:06 -07:00
|
|
|
void
|
|
|
|
|
write_some_win32_op<
|
2017-07-09 20:09:30 -07:00
|
|
|
Protocol, Handler, isRequest, Fields>::
|
2017-09-03 18:06:09 -07:00
|
|
|
operator()(
|
|
|
|
|
error_code ec, std::size_t bytes_transferred)
|
2017-07-07 09:03:06 -07:00
|
|
|
{
|
2017-09-03 18:06:09 -07:00
|
|
|
bytes_transferred_ += bytes_transferred;
|
2017-07-07 09:03:06 -07:00
|
|
|
if(! ec)
|
|
|
|
|
{
|
|
|
|
|
if(header_)
|
|
|
|
|
{
|
|
|
|
|
header_ = false;
|
|
|
|
|
return (*this)();
|
|
|
|
|
}
|
|
|
|
|
auto& r = sr_.reader_impl();
|
|
|
|
|
r.pos_ += bytes_transferred;
|
|
|
|
|
BOOST_ASSERT(r.pos_ <= r.body_.last_);
|
|
|
|
|
if(r.pos_ >= r.body_.last_)
|
|
|
|
|
{
|
|
|
|
|
sr_.next(ec, null_lambda{});
|
|
|
|
|
BOOST_ASSERT(! ec);
|
|
|
|
|
BOOST_ASSERT(sr_.is_done());
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-09-03 18:06:09 -07:00
|
|
|
h_(ec, bytes_transferred_);
|
2017-07-07 09:03:06 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
} // detail
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
2017-07-09 20:09:30 -07:00
|
|
|
template<class Protocol, bool isRequest, class Fields>
|
2017-09-03 18:06:09 -07:00
|
|
|
std::size_t
|
2017-07-07 09:03:06 -07:00
|
|
|
write_some(
|
|
|
|
|
boost::asio::basic_stream_socket<Protocol>& sock,
|
2017-07-09 20:09:30 -07:00
|
|
|
serializer<isRequest,
|
|
|
|
|
basic_file_body<file_win32>, Fields>& sr,
|
2017-07-07 09:03:06 -07:00
|
|
|
error_code& ec)
|
|
|
|
|
{
|
|
|
|
|
if(! sr.is_header_done())
|
|
|
|
|
{
|
|
|
|
|
sr.split(true);
|
2017-09-03 18:06:09 -07:00
|
|
|
auto const bytes_transferred =
|
2017-11-18 11:31:17 -08:00
|
|
|
detail::write_some_impl(sock, sr, ec);
|
2017-07-07 09:03:06 -07:00
|
|
|
if(ec)
|
2017-09-03 18:06:09 -07:00
|
|
|
return bytes_transferred;
|
|
|
|
|
return bytes_transferred;
|
2017-07-07 09:03:06 -07:00
|
|
|
}
|
2017-10-24 17:23:38 -07:00
|
|
|
if(sr.get().chunked())
|
2017-07-07 09:03:06 -07:00
|
|
|
{
|
2017-09-03 18:06:09 -07:00
|
|
|
auto const bytes_transferred =
|
2017-11-18 11:31:17 -08:00
|
|
|
detail::write_some_impl(sock, sr, ec);
|
2017-07-07 09:03:06 -07:00
|
|
|
if(ec)
|
2017-09-03 18:06:09 -07:00
|
|
|
return bytes_transferred;
|
|
|
|
|
return bytes_transferred;
|
2017-07-07 09:03:06 -07:00
|
|
|
}
|
|
|
|
|
auto& r = sr.reader_impl();
|
|
|
|
|
r.body_.file_.seek(r.pos_, ec);
|
|
|
|
|
if(ec)
|
2017-09-03 18:06:09 -07:00
|
|
|
return 0;
|
2017-10-24 21:25:23 +03:00
|
|
|
boost::winapi::DWORD_ const nNumberOfBytesToWrite =
|
2017-11-07 07:09:57 -08:00
|
|
|
static_cast<boost::winapi::DWORD_>(
|
|
|
|
|
(std::min<std::uint64_t>)(
|
|
|
|
|
(std::min<std::uint64_t>)(r.body_.last_ - r.pos_, sr.limit()),
|
|
|
|
|
(std::numeric_limits<boost::winapi::DWORD_>::max)()));
|
2017-07-07 09:03:06 -07:00
|
|
|
auto const bSuccess = ::TransmitFile(
|
|
|
|
|
sock.native_handle(),
|
|
|
|
|
r.body_.file_.native_handle(),
|
|
|
|
|
nNumberOfBytesToWrite,
|
|
|
|
|
0,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
0);
|
|
|
|
|
if(! bSuccess)
|
|
|
|
|
{
|
|
|
|
|
ec.assign(static_cast<int>(
|
2017-10-24 21:25:23 +03:00
|
|
|
boost::winapi::GetLastError()),
|
2017-07-07 09:03:06 -07:00
|
|
|
system_category());
|
2017-09-03 18:06:09 -07:00
|
|
|
return 0;
|
2017-07-07 09:03:06 -07:00
|
|
|
}
|
|
|
|
|
r.pos_ += nNumberOfBytesToWrite;
|
|
|
|
|
BOOST_ASSERT(r.pos_ <= r.body_.last_);
|
|
|
|
|
if(r.pos_ < r.body_.last_)
|
|
|
|
|
{
|
|
|
|
|
ec.assign(0, ec.category());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
sr.next(ec, detail::null_lambda{});
|
|
|
|
|
BOOST_ASSERT(! ec);
|
|
|
|
|
BOOST_ASSERT(sr.is_done());
|
|
|
|
|
}
|
2017-09-03 18:06:09 -07:00
|
|
|
return nNumberOfBytesToWrite;
|
2017-07-07 09:03:06 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR
|
|
|
|
|
|
|
|
|
|
template<
|
|
|
|
|
class Protocol,
|
2017-07-09 20:09:30 -07:00
|
|
|
bool isRequest, class Fields,
|
2017-07-07 09:03:06 -07:00
|
|
|
class WriteHandler>
|
2017-09-07 07:39:52 -07:00
|
|
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
|
|
|
|
WriteHandler, void(error_code, std::size_t))
|
2017-07-07 09:03:06 -07:00
|
|
|
async_write_some(
|
|
|
|
|
boost::asio::basic_stream_socket<Protocol>& sock,
|
2017-07-09 20:09:30 -07:00
|
|
|
serializer<isRequest,
|
|
|
|
|
basic_file_body<file_win32>, Fields>& sr,
|
2017-07-07 09:03:06 -07:00
|
|
|
WriteHandler&& handler)
|
|
|
|
|
{
|
2017-09-07 07:39:52 -07:00
|
|
|
boost::asio::async_completion<WriteHandler,
|
2017-07-07 09:03:06 -07:00
|
|
|
void(error_code)> init{handler};
|
2017-09-03 18:06:09 -07:00
|
|
|
detail::write_some_win32_op<
|
|
|
|
|
Protocol,
|
2017-09-07 07:39:52 -07:00
|
|
|
BOOST_ASIO_HANDLER_TYPE(WriteHandler,
|
|
|
|
|
void(error_code, std::size_t)),
|
2017-09-03 18:06:09 -07:00
|
|
|
isRequest, Fields>{
|
2017-07-09 20:09:30 -07:00
|
|
|
init.completion_handler, sock, sr}();
|
2017-07-07 09:03:06 -07:00
|
|
|
return init.result.get();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
} // http
|
|
|
|
|
} // beast
|
2017-07-20 13:40:34 -07:00
|
|
|
} // boost
|
2017-07-07 09:03:06 -07:00
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#endif
|