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  //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  {
51  this->init_next_write();
52  }
53  else
54  {
55  this->m_after_sendfile_cb(
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,
77  this->m_file_descriptor );
78 
79  if( desired_size != n )
80  {
81  this->m_after_sendfile_cb(
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  {
91  this->m_socket,
93  this->m_buffer.get(),
94  static_cast< std::size_t >( desired_size ) },
96  this->m_executor,
98  }
99  catch( ... )
100  {
101  this->m_after_sendfile_cb(
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  {
130  this->init_next_write();
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 */
sendfile_operation_runner_t(const sendfile_operation_runner_t &)=delete
std::enable_if< std::is_same< Parameter_Container, query_string_params_t >::value||std::is_same< Parameter_Container, router::route_params_t >::value, std::optional< Value_Type > >::type opt_value(const Parameter_Container &params, string_view_t key)
Gets the value of a parameter specified by key wrapped in std::optional<Value_Type> if parameter exis...
Definition: value_or.hpp:64
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
sendfile_operation_runner_t & operator=(const sendfile_operation_runner_t &)=delete