RESTinio
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 
11 namespace restinio
12 {
13 
14 namespace impl
15 {
16 
17 //
18 // sendfile_operation_runner_t
19 //
20 
21 //! A runner of sendfile operation
22 template < typename Socket >
25 {
26  public:
28 
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(
55  this->m_transfered_size );
56  return;
57  }
58  }
59 
60  /*!
61  * @note
62  * This method is noexcept since v.0.6.0.
63  */
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,
75  this->m_file_descriptor );
76 
77  if( desired_size != n )
78  {
79  this->m_after_sendfile_cb(
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  {
89  this->m_socket,
91  this->m_buffer.get(),
92  static_cast< std::size_t >( desired_size ) },
94  this->m_executor,
96  }
97  catch( ... )
98  {
99  this->m_after_sendfile_cb(
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 
110  //! Helper method for making a lambda for async_write completion handler.
111  auto
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 */
sendfile_operation_runner_t(const sendfile_operation_runner_t &)=delete
sendfile_operation_runner_t(sendfile_operation_runner_t &&)=delete
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
RESTINIO_NODISCARD char to_lower_case(unsigned char ch)
std::enable_if< std::is_same< Parameter_Container, query_string_params_t >::value||std::is_same< Parameter_Container, router::route_params_t >::value, optional_t< Value_Type > >::type opt_value(const Parameter_Container &params, string_view_t key)
Gets the value of a parameter specified by key wrapped in optional_t<Value_Type> if parameter exists ...
Definition: value_or.hpp:64
sendfile_operation_runner_t & operator=(const sendfile_operation_runner_t &)=delete