sendfile_operation_default.ipp
Go to the documentation of this file.
/*
restinio
*/
#include <cstdio>
namespace restinio
{
namespace impl
{
//
// sendfile_operation_runner_t
//
template < typename Socket >
class sendfile_operation_runner_t final
: public sendfile_operation_runner_base_t< Socket >
{
public:
using base_type_t = sendfile_operation_runner_base_t< Socket >;
sendfile_operation_runner_t( const sendfile_operation_runner_t & ) = delete;
sendfile_operation_runner_t( sendfile_operation_runner_t && ) = delete;
sendfile_operation_runner_t & operator = ( const sendfile_operation_runner_t & ) = delete;
sendfile_operation_runner_t & operator = ( sendfile_operation_runner_t && ) = delete;
// Reuse construstors from base.
using base_type_t::base_type_t;
virtual void
start() override
{
const auto n =
std::fseek(
this->m_file_descriptor,
this->m_next_write_offset,
SEEK_SET );
if( 0 == n )
{
this->init_next_write();
}
else
{
this->m_after_sendfile_cb(
make_error_code( std::ferror( this->m_file_descriptor ) ),
this->m_transfered_size );
return;
}
}
void
init_next_write() noexcept
{
const auto desired_size =
std::min< file_size_t >( this->m_remained_size, this->m_chunk_size );
const auto n =
std::fread(
this->m_buffer.get(),
1,
desired_size,
this->m_file_descriptor );
if( desired_size != n )
{
this->m_after_sendfile_cb(
make_error_code( std::ferror( this->m_file_descriptor ) ),
this->m_transfered_size );
}
else
{
// If asio_ns::async_write fails we'll call m_after_sendfile_cb.
try
{
asio_ns::async_write(
this->m_socket,
asio_ns::const_buffer{
this->m_buffer.get(),
static_cast< std::size_t >( desired_size ) },
asio_ns::bind_executor(
this->m_executor,
make_async_write_handler() ) );
}
catch( ... )
{
this->m_after_sendfile_cb(
make_asio_compaible_error(
asio_convertible_error_t::async_write_call_failed ),
this->m_transfered_size );
}
}
}
private:
std::unique_ptr< char[] > m_buffer{ new char [ this->m_chunk_size ] };
auto
make_async_write_handler() noexcept
{
return [ this, ctx = this->shared_from_this() ]
// NOTE: this lambda is noexcept since v.0.6.0.
( const asio_ns::error_code & ec, std::size_t written ) noexcept
{
if( !ec )
{
this->m_remained_size -= written;
this->m_transfered_size += written;
if( 0 == this->m_remained_size )
{
this->m_after_sendfile_cb( ec, this->m_transfered_size );
}
else
{
this->init_next_write();
}
}
else
{
this->m_after_sendfile_cb( ec, this->m_transfered_size );
}
};
}
};
} /* namespace impl */
} /* namespace restinio */
restinio::impl::sendfile_operation_runner_base_t
A base runner of sendfile operation (keeps all the data).
Definition: sendfile_operation.hpp:50
restinio::impl::sendfile_operation_runner_base_t::m_after_sendfile_cb
after_sendfile_cb_t m_after_sendfile_cb
Definition: sendfile_operation.hpp:83
restinio::impl::sendfile_operation_runner_base_t::m_chunk_size
const file_size_t m_chunk_size
Definition: sendfile_operation.hpp:77
restinio::impl::sendfile_operation_runner_base_t::m_remained_size
file_size_t m_remained_size
Definition: sendfile_operation.hpp:74
restinio::impl::sendfile_operation_runner_base_t::m_next_write_offset
file_offset_t m_next_write_offset
Definition: sendfile_operation.hpp:73
restinio::impl::sendfile_operation_runner_base_t::m_file_descriptor
file_descriptor_t m_file_descriptor
Definition: sendfile_operation.hpp:72
restinio::impl::sendfile_operation_runner_base_t::m_executor
default_asio_executor m_executor
Definition: sendfile_operation.hpp:81
restinio::impl::sendfile_operation_runner_base_t::m_socket
Socket & m_socket
Definition: sendfile_operation.hpp:82
restinio::impl::sendfile_operation_runner_base_t::m_transfered_size
file_size_t m_transfered_size
Definition: sendfile_operation.hpp:75
restinio::impl::sendfile_operation_runner_t
A runner of sendfile operation.
Definition: sendfile_operation_default.ipp:25
restinio::impl::sendfile_operation_runner_t::m_buffer
std::unique_ptr< char[] > m_buffer
Definition: sendfile_operation_default.ipp:108
restinio::impl::sendfile_operation_runner_t::make_async_write_handler
auto make_async_write_handler() noexcept
Helper method for making a lambda for async_write completion handler.
Definition: sendfile_operation_default.ipp:112
restinio::impl::sendfile_operation_runner_t::start
virtual void start() override
Definition: sendfile_operation_default.ipp:39
restinio::impl::sendfile_operation_runner_t::sendfile_operation_runner_t
sendfile_operation_runner_t(const sendfile_operation_runner_t &)=delete
restinio::impl::sendfile_operation_runner_t::operator=
sendfile_operation_runner_t & operator=(const sendfile_operation_runner_t &)=delete
restinio::impl::sendfile_operation_runner_t::init_next_write
void init_next_write() noexcept
Definition: sendfile_operation_default.ipp:65
restinio::impl::sendfile_operation_runner_t::sendfile_operation_runner_t
sendfile_operation_runner_t(sendfile_operation_runner_t &&)=delete
restinio::impl::make_error_code
auto make_error_code(const Error_Type &e) noexcept
Definition: sendfile_operation.hpp:88
restinio
Definition: asio_include.hpp:21
restinio::asio_convertible_error_t::async_write_call_failed
@ async_write_call_failed
A call to async_write failed. The corresponding write operation wasn't done.
restinio::const_buffer
constexpr const_buffer_t const_buffer(const void *str, std::size_t size) noexcept
Definition: buffers.hpp:424
restinio::make_asio_compaible_error
asio_ns::error_code make_asio_compaible_error(asio_convertible_error_t err) noexcept
Make restinio error_code compatible with asio_ns::error_code.
Definition: asio_include.hpp:210
SEEK_SET
#define SEEK_SET
Definition: zconf.h:498