RESTinio

sendfile_operation_default.ipp
Go to the documentation of this file.
1/*
2 restinio
3*/
4
9#include <cstdio>
10
11 namespace restinio
12{
13
14 namespace impl
15{
16
17//
18// sendfile_operation_runner_t
19//
20
22 template < typename Socket >
23 class sendfile_operation_runner_t final
24 : public sendfile_operation_runner_base_t< Socket >
25{
26 public:
27 using base_type_t = sendfile_operation_runner_base_t< Socket >;
28
29 sendfile_operation_runner_t( const sendfile_operation_runner_t & ) = delete;
30 sendfile_operation_runner_t( sendfile_operation_runner_t && ) = delete;
31 sendfile_operation_runner_t & operator = ( const sendfile_operation_runner_t & ) = delete;
32 sendfile_operation_runner_t & operator = ( sendfile_operation_runner_t && ) = delete;
33
34 // Reuse construstors from base.
35 using base_type_t::base_type_t;
36
37
38 virtual void
39 start() override
40 {
41 const auto n =
42 std::fseek(
43 this->m_file_descriptor,
44 this->m_next_write_offset,
45 SEEK_SET );
46
47 if( 0 == n )
48 {
49 this->init_next_write();
50 }
51 else
52 {
53 this->m_after_sendfile_cb(
54 make_error_code( std::ferror( this->m_file_descriptor ) ),
55 this->m_transfered_size );
56 return;
57 }
58 }
59
64 void
65 init_next_write() noexcept
66 {
67 const auto desired_size =
68 std::min< file_size_t >( this->m_remained_size, this->m_chunk_size );
69
70 const auto n =
71 std::fread(
72 this->m_buffer.get(),
73 1,
74 desired_size,
75 this->m_file_descriptor );
76
77 if( desired_size != n )
78 {
79 this->m_after_sendfile_cb(
80 make_error_code( std::ferror( this->m_file_descriptor ) ),
81 this->m_transfered_size );
82 }
83 else
84 {
85 // If asio_ns::async_write fails we'll call m_after_sendfile_cb.
86 try
87 {
88 asio_ns::async_write(
89 this->m_socket,
90 asio_ns::const_buffer{
91 this->m_buffer.get(),
92 static_cast< std::size_t >( desired_size ) },
93 asio_ns::bind_executor(
94 this->m_executor,
95 make_async_write_handler() ) );
96 }
97 catch( ... )
98 {
99 this->m_after_sendfile_cb(
100 make_asio_compaible_error(
101 asio_convertible_error_t::async_write_call_failed ),
102 this->m_transfered_size );
103 }
104 }
105 }
106
107 private:
108 std::unique_ptr< char[] > m_buffer{ new char [ this->m_chunk_size ] };
109
111 auto
112 make_async_write_handler() noexcept
113 {
114 return [ this, ctx = this->shared_from_this() ]
115 // NOTE: this lambda is noexcept since v.0.6.0.
116 ( const asio_ns::error_code & ec, std::size_t written ) noexcept
117 {
118 if( !ec )
119 {
120 this->m_remained_size -= written;
121 this->m_transfered_size += written;
122 if( 0 == this->m_remained_size )
123 {
124 this->m_after_sendfile_cb( ec, this->m_transfered_size );
125 }
126 else
127 {
128 this->init_next_write();
129 }
130 }
131 else
132 {
133 this->m_after_sendfile_cb( ec, this->m_transfered_size );
134 }
135 };
136 }
137};
138
139} /* namespace impl */
140
141} /* namespace restinio */
142
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