2
3
6
7
9#if defined(RESTINIO_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
13#include <restinio/utils/impl/safe_uint_truncate.hpp>
24#if RESTINIO_ASIO_VERSION < 101300
26template<
typename Socket >
28executor_or_context_from_socket( Socket & socket )
30 return socket.get_executor().context();
35template<
typename Socket >
37executor_or_context_from_socket( Socket & socket )
39 return socket.get_executor();
51template <
typename Socket >
52class sendfile_operation_runner_t final
53 :
public sendfile_operation_runner_base_t< Socket >
56 using base_type_t = sendfile_operation_runner_base_t< Socket >;
58 sendfile_operation_runner_t(
const sendfile_operation_runner_t & ) =
delete;
59 sendfile_operation_runner_t( sendfile_operation_runner_t && ) =
delete;
60 sendfile_operation_runner_t & operator = (
const sendfile_operation_runner_t & ) =
delete;
61 sendfile_operation_runner_t & operator = ( sendfile_operation_runner_t && ) =
delete;
63 sendfile_operation_runner_t(
65 default_asio_executor executor,
67 after_sendfile_cb_t after_sendfile_cb )
68 : base_type_t{ sf, std::move( executor), socket, std::move( after_sendfile_cb ) }
75 takeaway_file_descriptor(sf).release();
81 init_next_read_some_from_file();
85
86
87
89 init_next_read_some_from_file()
noexcept
91 const auto desired_size =
92 std::min< file_size_t >(
this->m_remained_size,
this->m_chunk_size );
96 this->m_file_handle.async_read_some_at(
97 this->m_next_write_offset,
100 static_cast< std::size_t >( desired_size ) ),
101 asio_ns::bind_executor(
103 make_async_read_some_at_handler() ) );
107 this->m_after_sendfile_cb(
108 make_asio_compaible_error(
109 asio_convertible_error_t::async_read_some_at_call_failed ),
110 this->m_transfered_size );
115
116
117
119 init_next_write( std::size_t len )
noexcept
123 asio_ns::async_write(
125 asio_ns::const_buffer{
126 this->m_buffer.get(),
127 static_cast< std::size_t >( len ) },
128 asio_ns::bind_executor(
130 make_async_write_handler() ) );
134 this->m_after_sendfile_cb(
135 make_asio_compaible_error(
136 asio_convertible_error_t::async_write_call_failed ),
137 this->m_transfered_size );
142 std::unique_ptr<
char[] > m_buffer{
new char [
this->m_chunk_size ] };
143 asio_ns::windows::random_access_handle m_file_handle{
144 asio_details::executor_or_context_from_socket(
this->m_socket),
145 this->m_file_descriptor
149 make_async_read_some_at_handler()
noexcept
151 return [
this, ctx =
this->shared_from_this()]
153 (
const asio_ns::error_code & ec, std::size_t len )
noexcept
155 if( ec || 0 ==
this->m_remained_size )
157 this->m_after_sendfile_cb( ec,
this->m_transfered_size );
162 init_next_write( len );
165 this->m_after_sendfile_cb(
166 make_error_code( asio_ec::eof ),
167 this->m_transfered_size );
172 this->m_after_sendfile_cb( ec,
this->m_transfered_size );
178 make_async_write_handler()
noexcept
180 return [
this, ctx =
this->shared_from_this() ]
182 (
const asio_ns::error_code & ec, std::size_t written )
noexcept
186 this->m_remained_size -= written;
187 this->m_transfered_size += written;
188 this->m_next_write_offset += written;
190 if( 0 ==
this->m_remained_size )
192 this->m_after_sendfile_cb( ec,
this->m_transfered_size );
196 this->init_next_read_some_from_file();
201 this->m_after_sendfile_cb( ec,
this->m_transfered_size );
209class sendfile_operation_runner_t < asio_ns::ip::tcp::socket > final
210 :
public sendfile_operation_runner_base_t< asio_ns::ip::tcp::socket >
213 make_completion_handler()
noexcept
215 return [
this, ctx = shared_from_this() ]
217 (
const asio_ns::error_code & ec, std::size_t written )
221 m_remained_size -= written;
222 m_transfered_size += written;
223 m_next_write_offset += written;
225 if( 0 == m_remained_size )
227 m_after_sendfile_cb( ec, m_transfered_size );
236 m_after_sendfile_cb( ec, m_transfered_size );
242 using base_type_t = sendfile_operation_runner_base_t< asio_ns::ip::tcp::socket >;
244 sendfile_operation_runner_t(
const sendfile_operation_runner_t & ) =
delete;
245 sendfile_operation_runner_t( sendfile_operation_runner_t && ) =
delete;
246 sendfile_operation_runner_t & operator = (
const sendfile_operation_runner_t & ) =
delete;
247 sendfile_operation_runner_t & operator = ( sendfile_operation_runner_t && ) =
delete;
249 sendfile_operation_runner_t(
251 default_asio_executor executor,
252 asio_ns::ip::tcp::socket & socket,
253 after_sendfile_cb_t after_sendfile_cb )
254 : base_type_t{ sf, std::move( executor), socket, std::move( after_sendfile_cb ) }
261 takeaway_file_descriptor(sf).release();
271
272
273
275 init_next_write()
noexcept
282 asio_ns::windows::overlapped_ptr overlapped{
283 asio_details::executor_or_context_from_socket( m_socket ),
284 asio_ns::bind_executor(
286 make_completion_handler() )
290 overlapped.get()->Offset =
291 static_cast< DWORD >( m_next_write_offset & 0xFFFFFFFFULL );
292 overlapped.get()->OffsetHigh =
293 static_cast< DWORD >( (m_next_write_offset>>32) & 0xFFFFFFFFULL );
296 const auto desired_size =
297 std::min< file_size_t >(
this->m_remained_size,
this->m_chunk_size );
302 m_socket.native_handle(),
303 m_file_handle.native_handle(),
304 static_cast< DWORD >( desired_size ),
310 DWORD last_error = ::GetLastError();
313 if( !ok && last_error != ERROR_IO_PENDING )
318 overlapped.complete( make_error_code( last_error ) , 0 );
324 overlapped.release();
330 this->m_after_sendfile_cb(
331 make_asio_compaible_error(
332 asio_convertible_error_t::async_write_call_failed ),
333 this->m_transfered_size );
338 std::unique_ptr<
char[] > m_buffer{
339 std::make_unique<
char[] >(
340 ::restinio::utils::impl::uint64_to_size_t(
343 asio_ns::windows::random_access_handle m_file_handle{
344 asio_details::executor_or_context_from_socket(m_socket),