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