RESTinio
connection.hpp
Go to the documentation of this file.
1 /*
2  restinio
3 */
4 
9 #pragma once
10 
12 
13 #include <http_parser.h>
14 
16 
17 #include <restinio/exception.hpp>
29 
32 
33 namespace restinio
34 {
35 
36 namespace impl
37 {
38 
39 //
40 // http_parser_ctx_t
41 //
42 
44 
49 {
53  std::string m_body;
55 
58  std::string m_current_field_name;
59  std::size_t m_last_value_total_size{ 0u };
60  bool m_last_was_value{ true };
61 
66 
72 
74  bool m_message_complete{ false };
75 
84  std::size_t m_total_field_count{ 0u };
85 
92 
100  : m_limits{ limits }
101  {}
102 
104  void
106  {
108  m_body.clear();
109  m_current_field_name.clear();
111  m_last_was_value = true;
113  m_message_complete = false;
114  m_total_field_count = 0u;
115  }
116 
119 
125  {
127 
128  if( !m_chunked_info_block.m_chunks.empty() ||
130  {
131  result = std::make_unique< chunked_input_info_t >(
133  }
134 
135  return result;
136  }
137 };
138 
140 #include "parser_callbacks.ipp"
141 
142 //
143 // create_parser_settings()
144 //
145 
147 
150 template< typename Http_Methods >
151 inline http_parser_settings
153 {
154  http_parser_settings parser_settings;
155  http_parser_settings_init( &parser_settings );
156 
157  parser_settings.on_url =
158  []( http_parser * parser, const char * at, size_t length ) -> int {
159  return restinio_url_cb( parser, at, length );
160  };
161 
162  parser_settings.on_header_field =
163  []( http_parser * parser, const char * at, size_t length ) -> int {
164  return restinio_header_field_cb( parser, at, length );
165  };
166 
167  parser_settings.on_header_value =
168  []( http_parser * parser, const char * at, size_t length ) -> int {
169  return restinio_header_value_cb( parser, at, length );
170  };
171 
172  parser_settings.on_headers_complete =
173  []( http_parser * parser ) -> int {
174  return restinio_headers_complete_cb( parser );
175  };
176 
177  parser_settings.on_body =
178  []( http_parser * parser, const char * at, size_t length ) -> int {
179  return restinio_body_cb( parser, at, length );
180  };
181 
182  parser_settings.on_chunk_header =
183  []( http_parser * parser ) -> int {
184  return restinio_chunk_header_cb( parser );
185  };
186 
187  parser_settings.on_chunk_complete =
188  []( http_parser * parser ) -> int {
189  return restinio_chunk_complete_cb( parser );
190  };
191 
192  parser_settings.on_message_complete =
193  []( http_parser * parser ) -> int {
194  return restinio_message_complete_cb< Http_Methods >( parser );
195  };
196 
197  return parser_settings;
198 }
199 
200 //
201 // connection_upgrade_stage_t
202 //
203 
205 enum class connection_upgrade_stage_t : std::uint8_t
206 {
208  none,
212  pending_upgrade_handling,
218 };
219 
220 //
221 // connection_input_t
222 //
223 
226 {
228  std::size_t buffer_size,
230  : m_parser_ctx{ limits }
231  , m_buf{ buffer_size }
232  {}
233 
236  http_parser m_parser;
239 
242 
246 
249 
251  void
253  {
254  // Reinit parser.
255  http_parser_init( &m_parser, HTTP_REQUEST);
256 
257  // Reset context and attach it to parser.
259  m_parser.data = &m_parser_ctx;
260  }
261 };
262 
263 template < typename Connection, typename Start_Read_CB, typename Failed_CB >
264 void
266  asio_ns::ip::tcp::socket & ,
267  Connection & ,
268  Start_Read_CB start_read_cb,
269  Failed_CB )
270 {
271  // No preparation is needed, start
272  start_read_cb();
273 }
274 
275 // An overload for the case of non-TLS-connection.
276 inline tls_socket_t *
278  asio_ns::ip::tcp::socket & ) noexcept
279 {
280  return nullptr;
281 }
282 
283 //
284 // connection_t
285 //
286 
288 /*
289  Working circle consists of the following steps:
290  * wait for request -- reading from socket and parsing header and body;
291  * handling request -- once the request is completely obtained it's handling
292  is deligated to a handler chosen by handler factory;
293  * writing response -- writing response to socket;
294  * back to first step o close connection -- depending on keep-alive property
295  of the last response the connection goes back to first step or
296  shutdowns.
297 
298  Each step is controlled by timer (\see schedule_operation_timeout_callback())
299 
300  In case of errors connection closes itself.
301 */
302 template < typename Traits >
303 class connection_t final
304  : public connection_base_t
305  , public executor_wrapper_t< typename Traits::strand_t >
306 {
308 
309  public:
310  using timer_manager_t = typename Traits::timer_manager_t;
311  using timer_guard_t = typename timer_manager_t::timer_guard_t;
312  using request_handler_t = typename Traits::request_handler_t;
313  using logger_t = typename Traits::logger_t;
314  using strand_t = typename Traits::strand_t;
315  using stream_socket_t = typename Traits::stream_socket_t;
318 
321  connection_id_t conn_id,
323  stream_socket_t && socket,
327  endpoint_t remote_endpoint,
329  lifetime_monitor_t lifetime_monitor )
330  : connection_base_t{ conn_id }
331  , executor_wrapper_base_t{ socket.get_executor() }
332  , m_socket{ std::move( socket ) }
333  , m_settings{ std::move( settings ) }
334  , m_remote_endpoint{ std::move( remote_endpoint ) }
335  , m_input{
336  m_settings->m_buffer_size,
337  m_settings->m_incoming_http_msg_limits
338  }
339  , m_response_coordinator{ m_settings->m_max_pipelined_requests }
340  , m_timer_guard{ m_settings->create_timer_guard() }
341  , m_request_handler{ *( m_settings->m_request_handler ) }
342  , m_logger{ *( m_settings->m_logger ) }
343  , m_lifetime_monitor{ std::move(lifetime_monitor) }
344  {
345  // Notify of a new connection instance.
346  m_logger.trace( [&]{
347  return fmt::format(
348  "[connection:{}] start connection with {}",
349  connection_id(),
351  } );
352  }
353 
354  // Disable copy/move.
355  connection_t( const connection_t & ) = delete;
356  connection_t( connection_t && ) = delete;
357  connection_t & operator = ( const connection_t & ) = delete;
359 
360  ~connection_t() override
361  {
363  [&]{
364  return fmt::format(
365  "[connection:{}] destructor called",
366  connection_id() );
367  } );
368  }
369 
370  void
372  {
374  m_socket,
375  *this,
376  [ & ]{
377  // Inform state listener if it used.
378  m_settings->call_state_listener( [this]() noexcept {
380  this->connection_id(),
381  this->m_remote_endpoint,
384  m_socket )
385  }
386  };
387  } );
388 
389  // Start timeout checking.
390  m_prepared_weak_ctx = shared_from_this();
392 
393  // Start reading request.
395  },
396  [ & ]( const asio_ns::error_code & ec ){
398  return fmt::format(
399  "[connection:{}] prepare connection error: {}",
400  connection_id(),
401  ec.message() );
402  } );
403  } );
404  }
405 
407  void
409  {
410  m_logger.trace( [&]{
411  return fmt::format(
412  "[connection:{}] start waiting for request",
413  connection_id() );
414  } );
415 
416  // Prepare parser for consuming new request message.
418 
419  // Guard total time for a request to be read.
420  // guarding here makes the total read process
421  // to run in read_next_http_message_timelimit.
423 
424  if( 0 != m_input.m_buf.length() )
425  {
426  // If a pipeline requests were sent by client
427  // then the biginning (or even entire request) of it
428  // is in the buffer obtained from socket in previous
429  // read operation.
431  }
432  else
433  {
434  // Next request (if any) must be obtained from socket.
435  consume_message();
436  }
437  }
438 
441  {
443  upgrade_internals_t && ) = default;
444 
447  stream_socket_t socket,
448  lifetime_monitor_t lifetime_monitor )
449  : m_settings{ std::move(settings) }
450  , m_socket{ std::move( socket ) }
451  , m_lifetime_monitor{ std::move(lifetime_monitor) }
452  {}
453 
457  };
458 
462  {
463  return upgrade_internals_t{
464  m_settings,
467  };
468  }
469 
470  private:
472  inline void
474  {
476  {
477  m_logger.trace( [&]{
478  return fmt::format(
479  "[connection:{}] continue reading request",
480  connection_id() );
481  } );
482 
483 
485  m_socket.async_read_some(
487  asio_ns::bind_executor(
488  this->get_executor(),
489  [this, ctx = shared_from_this()]
490  // NOTE: this lambda is noexcept since v.0.6.0.
491  ( const asio_ns::error_code & ec,
492  std::size_t length ) noexcept {
494  RESTINIO_ENSURE_NOEXCEPT_CALL( after_read( ec, length ) );
495  } ) );
496  }
497  else
498  {
499  m_logger.trace( [&]{
500  return fmt::format(
501  "[connection:{}] skip read operation: already running",
502  connection_id() );
503  } );
504  }
505  }
506 
508  inline void
509  after_read( const asio_ns::error_code & ec, std::size_t length ) noexcept
510  {
511  if( !ec )
512  {
513  // Exceptions shouldn't go out of `after_read`.
514  // So intercept them and close the connection in the case
515  // of an exception.
516  try
517  {
518  m_logger.trace( [&]{
519  return fmt::format(
520  "[connection:{}] received {} bytes",
521  this->connection_id(),
522  length );
523  } );
524 
525  m_input.m_buf.obtained_bytes( length );
526 
527  consume_data( m_input.m_buf.bytes(), length );
528  }
529  catch( const std::exception & x )
530  {
532  return fmt::format(
533  "[connection:{}] unexpected exception during the "
534  "handling of incoming data: {}",
535  connection_id(),
536  x.what() );
537  } );
538  }
539  }
540  else
541  {
542  // Well, if it is actually an error
543  // then close connection.
544  if( !error_is_operation_aborted( ec ) )
545  {
546  if ( !error_is_eof( ec ) || 0 != m_input.m_parser.nread )
548  return fmt::format(
549  "[connection:{}] read socket error: {}; "
550  "parsed bytes: {}",
551  connection_id(),
552  ec.message(),
553  m_input.m_parser.nread );
554  } );
555  else
556  {
557  // A case that is not such an error:
558  // on a connection (most probably keeped alive
559  // after previous request, but a new also applied)
560  // no bytes were consumed and remote peer closes connection.
562  [&]{
563  return fmt::format(
564  "[connection:{}] EOF and no request, "
565  "close connection",
566  connection_id() );
567  } );
568 
570  }
571  }
572  // else: read operation was cancelled.
573  }
574  }
575 
577  void
578  consume_data( const char * data, std::size_t length )
579  {
580  auto & parser = m_input.m_parser;
581 
582  const auto nparsed =
583  http_parser_execute(
584  &parser,
585  &( m_settings->m_parser_settings ),
586  data,
587  length );
588 
589  // If entire http-message was obtained,
590  // parser is stopped and the might be a part of consecutive request
591  // left in buffer, so we mark how many bytes were obtained.
592  // and next message read (if any) will be started from already existing
593  // data left in buffer.
594  m_input.m_buf.consumed_bytes( nparsed );
595 
596  if( HPE_OK != parser.http_errno &&
597  HPE_PAUSED != parser.http_errno )
598  {
599  // PARSE ERROR:
600  auto err = HTTP_PARSER_ERRNO( &parser );
601 
602  // TODO: handle case when there are some request in process.
604  return fmt::format(
605  "[connection:{}] parser error {}: {}",
606  connection_id(),
607  http_errno_name( err ),
608  http_errno_description( err ) );
609  } );
610 
611  // nothing to do.
612  return;
613  }
614 
616  {
618  }
619  else
620  consume_message();
621  }
622 
624  void
626  {
627  try
628  {
629  auto & parser = m_input.m_parser;
630  auto & parser_ctx = m_input.m_parser_ctx;
631 
632  if( m_input.m_parser.upgrade )
633  {
634  // Start upgrade connection operation.
635 
636  // The first thing is to make sure
637  // that upgrade request will be handled in
638  // a non pipelined fashion.
640  connection_upgrade_stage_t::pending_upgrade_handling;
641  }
642 
645  {
646  // Run ordinary HTTP logic.
647  const auto request_id = m_response_coordinator.register_new_request();
648 
649  m_logger.trace( [&]{
650  return fmt::format(
651  "[connection:{}] request received (#{}): {} {}",
652  connection_id(),
653  request_id,
654  http_method_str(
655  static_cast<http_method>( parser.method ) ),
656  parser_ctx.m_header.request_target() );
657  } );
658 
659  // TODO: mb there is a way to
660  // track if response was emmited immediately in handler
661  // or it was delegated
662  // so it is possible to omit this timer scheduling.
664 
665  if( request_rejected() ==
667  std::make_shared< request_t >(
668  request_id,
669  std::move( parser_ctx.m_header ),
670  std::move( parser_ctx.m_body ),
671  parser_ctx.make_chunked_input_info_if_necessary(),
672  shared_from_concrete< connection_base_t >(),
673  m_remote_endpoint ) ) )
674  {
675  // If handler refused request, say not implemented.
677  request_id,
682  }
684  {
685  // Request was accepted,
686  // didn't create immediate response that closes connection after,
687  // and it is possible to receive more requests
688  // then start consuming yet another request.
690  }
691  }
692  else
693  {
694  m_logger.trace( [&]{
695  const std::string default_value{};
696 
697  return fmt::format(
698  "[connection:{}] upgrade request received: {} {}; "
699  "Upgrade: '{}';",
700  connection_id(),
701  http_method_str(
702  static_cast<http_method>( parser.method ) ),
703  parser_ctx.m_header.request_target(),
704  parser_ctx.m_header.get_field_or(
705  http_field::upgrade, default_value ) );
706  } );
707 
709  {
710  // There are no requests in handling
711  // So the current request with upgrade
712  // is the only one and can be handled directly.
713  // It is safe to call a handler for it.
715  }
716  else
717  {
718  // There are pipelined request
719  m_logger.trace( [&]{
720  return fmt::format(
721  "[connection:{}] upgrade request happened to be a pipelined one, "
722  "and will be handled after previous requests are handled",
723  connection_id() );
724  } );
725  }
726 
727  // No further actions (like continue reading) in both cases are needed.
728  }
729 
730  }
731  catch( const std::exception & ex )
732  {
734  return fmt::format(
735  "[connection:{}] error while handling request: {}",
736  this->connection_id(),
737  ex.what() );
738  } );
739  }
740  }
741 
743 
746  void
748  {
749  auto & parser = m_input.m_parser;
750  auto & parser_ctx = m_input.m_parser_ctx;
751 
752  // If user responses with error
753  // then connection must be able to send
754  // (hence to receive) response.
755 
756  const auto request_id = m_response_coordinator.register_new_request();
757 
758  m_logger.info( [&]{
759  return fmt::format(
760  "[connection:{}] handle upgrade request (#{}): {} {}",
761  connection_id(),
762  request_id,
763  http_method_str(
764  static_cast<http_method>( parser.method ) ),
765  parser_ctx.m_header.request_target() );
766  } );
767 
768  // Do not guard upgrade request.
770 
771  // After calling handler we expect the results or
772  // no further operations with connection
775 
776  if( request_rejected() ==
778  std::make_shared< request_t >(
779  request_id,
780  std::move( parser_ctx.m_header ),
781  std::move( parser_ctx.m_body ),
782  parser_ctx.make_chunked_input_info_if_necessary(),
783  shared_from_concrete< connection_base_t >(),
784  m_remote_endpoint) ) )
785  {
786  if( m_socket.is_open() )
787  {
788  // Request is rejected, so our socket
789  // must not be moved out to websocket connection.
790 
791  // If handler refused request, say not implemented.
793  request_id,
798  }
799  else
800  {
801  // Request is rejected, but the socket
802  // was moved out to somewhere else???
803 
804  m_logger.error( [&]{
805  return fmt::format(
806  "[connection:{}] upgrade request handler rejects "
807  "request, but socket was moved out from connection",
808  connection_id() );
809  } );
810  }
811  }
812 
813  // Else 2 cases:
814  // 1. request is handled asynchronously, so
815  // what happens next depends on handling.
816  // 2. handling was immediate, so further destiny
817  // of a connection was already determined.
818  //
819  // In both cases: here do nothing.
820  // We can't even do read-only access because
821  // upgrade handling might take place
822  // in distinct execution context.
823  // So no even a log messages here.
824  }
825 
827  virtual void
830  request_id_t request_id,
832  response_output_flags_t response_output_flags,
834  write_group_t wg ) override
835  {
837  asio_ns::dispatch(
838  this->get_executor(),
839  [ this,
840  request_id,
841  response_output_flags,
842  actual_wg = std::move( wg ),
843  ctx = shared_from_this() ]
844  // NOTE that this lambda is noexcept since v.0.6.0.
845  () mutable noexcept
846  {
847  try
848  {
850  request_id,
851  response_output_flags,
852  std::move( actual_wg ) );
853  }
854  catch( const std::exception & ex )
855  {
857  return fmt::format(
858  "[connection:{}] unable to handle response: {}",
859  connection_id(),
860  ex.what() );
861  } );
862  }
863  } );
864  }
865 
867  void
870  request_id_t request_id,
872  response_output_flags_t response_output_flags,
874  write_group_t wg )
875  {
876  auto invoke_after_write_cb_with_error = [&]{
877  try
878  {
881  asio_convertible_error_t::write_was_not_executed ) );
882  }
883  catch( const std::exception & ex )
884  {
885  m_logger.error( [&]{
886  return fmt::format(
887  "[connection:{}] notificator error: {}",
888  connection_id(),
889  ex.what() );
890  } );
891  }
892  };
893 
894  if( m_socket.is_open() )
895  {
899  {
900  // It is response for a connection-upgrade request.
901  // If we receive it here then it is constructed via
902  // message builder and so connection was not transformed
903  // to websocket connection.
904  // So it is necessary to resume pipeline logic that was stopped
905  // for upgrade-request to be handled as the only request
906  // on the connection for that moment.
908  {
910  }
911  }
912 
914  {
915  m_logger.trace( [&]{
916  return fmt::format(
917  "[connection:{}] append response (#{}), "
918  "flags: {}, write group size: {}",
919  connection_id(),
920  request_id,
921  response_output_flags,
922  wg.items_count() );
923  } );
924 
926  request_id,
927  response_output_flags,
928  std::move( wg ) );
929 
931  }
932  else
933  {
934  m_logger.warn( [&]{
935  return fmt::format(
936  "[connection:{}] receive response parts for "
937  "request (#{}), but response with connection-close "
938  "attribute happened before",
939  connection_id(),
940  request_id );
941  } );
942  invoke_after_write_cb_with_error();
943  }
944  }
945  else
946  {
947  m_logger.warn( [&]{
948  return fmt::format(
949  "[connection:{}] try to write response, "
950  "while socket is closed",
951  connection_id() );
952  } );
953  invoke_after_write_cb_with_error();
954  }
955  }
956 
957  // Check if there is something to write,
958  // and if so starts write operation.
959  void
961  {
962  assert( !m_response_coordinator.closed() );
963 
965  {
966  init_write();
967  }
968  }
969 
971  void
973  {
974  // Here: not writing anything to socket, so
975  // write operation can be initiated.
976 
977  // Remember if all response cells were busy.
978  const bool response_coordinator_full_before =
980 
981  auto next_write_group = m_response_coordinator.pop_ready_buffers();
982 
983  if( next_write_group )
984  {
985  m_logger.trace( [&]{
986  return fmt::format(
987  "[connection:{}] start next write group for response (#{}), "
988  "size: {}",
989  this->connection_id(),
990  next_write_group->second,
991  next_write_group->first.items_count() );
992  } );
993 
994  // Check if all response cells busy:
995  const bool response_coordinator_full_after =
997 
998  // Whether we need to resume read after this group is written?
1000  response_coordinator_full_before &&
1001  !response_coordinator_full_after;
1002 
1003  if( 0 < next_write_group->first.status_line_size() )
1004  {
1005  // We need to extract status line out of the first buffer
1006  assert(
1007  writable_item_type_t::trivial_write_operation ==
1008  next_write_group->first.items().front().write_type() );
1009 
1010  m_logger.trace( [&]{
1011  // Get status line:
1012  const string_view_t
1013  status_line{
1014  asio_ns::buffer_cast< const char * >(
1015  next_write_group->first.items().front().buf() ),
1016  next_write_group->first.status_line_size() };
1017 
1018  return
1019  fmt::format(
1020  "[connection:{}] start response (#{}): {}",
1021  this->connection_id(),
1022  next_write_group->second,
1023  status_line );
1024  } );
1025  }
1026 
1027  // Initialize write context with a new write group.
1029  std::move( next_write_group->first ) );
1030 
1031  // Start the loop of sending data from current write group.
1033  }
1034  else
1035  {
1037  }
1038  }
1039 
1040  // Use aliases for shorter names.
1044 
1046 
1057  void
1059  {
1060  try
1061  {
1063 
1064  if( holds_alternative< trivial_write_operation_t >( wo ) )
1065  {
1066  handle_trivial_write_operation( get< trivial_write_operation_t >( wo ) );
1067  }
1068  else if( holds_alternative< file_write_operation_t >( wo ) )
1069  {
1070  handle_file_write_operation( get< file_write_operation_t >( wo ) );
1071  }
1072  else
1073  {
1074  assert( holds_alternative< none_write_operation_t >( wo ) );
1076  }
1077  }
1078  catch( const std::exception & ex )
1079  {
1081  return fmt::format(
1082  "[connection:{}] handle_current_write_ctx failed: {}",
1083  connection_id(),
1084  ex.what() );
1085  } );
1086  }
1087  }
1088 
1090  void
1092  {
1093  // Asio buffers (param for async write):
1094  auto & bufs = op.get_trivial_bufs();
1095 
1097  {
1098  m_logger.trace( [&]{
1099  return fmt::format(
1100  "[connection:{}] sending resp data with "
1101  "connection-close attribute "
1102  "buf count: {}, "
1103  "total size: {}",
1104  connection_id(),
1105  bufs.size(),
1106  op.size() );
1107  } );
1108 
1109  // Reading new requests is useless.
1110  asio_ns::error_code ignored_ec;
1111  m_socket.cancel( ignored_ec );
1112  }
1113  else
1114  {
1115  m_logger.trace( [&]{
1116  return fmt::format(
1117  "[connection:{}] sending resp data, "
1118  "buf count: {}, "
1119  "total size: {}",
1120  connection_id(),
1121  bufs.size(),
1122  op.size() ); } );
1123  }
1124 
1125  // There is somethig to write.
1126  asio_ns::async_write(
1127  m_socket,
1128  bufs,
1129  asio_ns::bind_executor(
1130  this->get_executor(),
1131  [this, ctx = shared_from_this()]
1132  // NOTE: since v.0.6.0 this lambda is noexcept.
1133  ( const asio_ns::error_code & ec, std::size_t written ) noexcept
1134  {
1135  if( !ec )
1136  {
1138  [&]{
1139  return fmt::format(
1140  "[connection:{}] outgoing data was sent: {} bytes",
1141  connection_id(),
1142  written );
1143  } );
1144  }
1145 
1147  } ) );
1148 
1150  }
1151 
1153  void
1155  {
1157  {
1158  m_logger.trace( [&]{
1159  return fmt::format(
1160  "[connection:{}] sending resp file data with "
1161  "connection-close attribute, "
1162  "total size: {}",
1163  connection_id(),
1164  op.size() );
1165  } );
1166 
1167  // Reading new requests is useless.
1168  asio_ns::error_code ignored_ec;
1169  m_socket.cancel( ignored_ec );
1170  }
1171  else
1172  {
1173  m_logger.trace( [&]{
1174  return fmt::format(
1175  "[connection:{}] sending resp file data, total size: {}",
1176  connection_id(),
1177  op.size() );
1178  } );
1179  }
1180 
1182 
1183  auto op_ctx = op;
1184 
1185  op_ctx.start_sendfile_operation(
1186  this->get_executor(),
1187  m_socket,
1188  asio_ns::bind_executor(
1189  this->get_executor(),
1190  [this, ctx = shared_from_this(),
1191  // Store operation context till the end
1192  op_ctx ]
1193  // NOTE: since v.0.6.0 this lambda is noexcept
1194  (const asio_ns::error_code & ec, file_size_t written ) mutable noexcept
1195  {
1196  // NOTE: op_ctx should be reset just before return from
1197  // that lambda. We can't call reset() until the end of
1198  // the lambda because lambda object itself will be
1199  // destroyed.
1200  auto op_ctx_reseter = restinio::utils::at_scope_exit(
1201  [&op_ctx] {
1202  // Reset sendfile operation context.
1203  RESTINIO_ENSURE_NOEXCEPT_CALL( op_ctx.reset() );
1204  } );
1205 
1206  if( !ec )
1207  {
1209  [&]{
1210  return fmt::format(
1211  "[connection:{}] file data was sent: {} bytes",
1212  connection_id(),
1213  written );
1214  } );
1215  }
1216  else
1217  {
1219  [&]{
1220  return fmt::format(
1221  "[connection:{}] send file data error: {} ({}) bytes",
1222  connection_id(),
1223  ec.value(),
1224  ec.message() );
1225  } );
1226  }
1227 
1229  } ) );
1230  }
1231 
1233  void
1235  {
1236  // Finishing writing this group.
1237  m_logger.trace( [&]{
1238  return fmt::format(
1239  "[connection:{}] finishing current write group",
1240  this->connection_id() );
1241  } );
1242 
1243  // Group notificators are called from here (if exist):
1245 
1247  {
1248  m_logger.trace( [&]{
1249  return fmt::format(
1250  "[connection:{}] should keep alive",
1251  this->connection_id() );
1252  } );
1253 
1256  {
1257  // Run ordinary HTTP logic.
1259  {
1261  }
1262 
1263  // Start another write opertion
1264  // if there is something to send.
1266  }
1267  else
1268  {
1270  {
1271  // Here upgrade req is the only request
1272  // to by handled by this connection.
1273  // So it is safe to call a handler for it.
1275  }
1276  else
1277  {
1278  // Do not start reading in any case,
1279  // but if there is at least one request preceding
1280  // upgrade-req, logic must continue http interaction.
1282  }
1283  }
1284  }
1285  else
1286  {
1287  // No keep-alive, close connection.
1288  close();
1289  }
1290  }
1291 
1292  void
1294  {
1296  {
1297  // Bufs empty but there happened to
1298  // be a response context marked as complete
1299  // (final_parts) and having connection-close attr.
1300  // It is because `init_write_if_necessary()`
1301  // is called only under `!m_response_coordinator.closed()`
1302  // condition, so if no bufs were obtained
1303  // and response coordinator is closed means
1304  // that a first response stored by
1305  // response coordinator was marked as complete
1306  // without data.
1307 
1308  m_logger.trace( [&]{
1309  return fmt::format(
1310  "[connection:{}] last sent response was marked "
1311  "as complete",
1312  connection_id() ); } );
1313  close();
1314  }
1315  else
1316  {
1317  // Not writing anything, so need to deal with timouts.
1319  {
1320  // No requests in processing.
1321  // So set read next request timeout.
1323  }
1324  else
1325  {
1326  // Have requests in process.
1327  // So take control over request handling.
1329  }
1330  }
1331  }
1332 
1334 
1338  void
1339  after_write( const asio_ns::error_code & ec ) noexcept
1340  {
1341  if( !ec )
1342  {
1344  }
1345  else
1346  {
1347  if( !error_is_operation_aborted( ec ) )
1348  {
1350  return fmt::format(
1351  "[connection:{}] unable to write: {}",
1352  connection_id(),
1353  ec.message() );
1354  } );
1355  }
1356  // else: Operation aborted only in case of close was called.
1357 
1358  try
1359  {
1361  }
1362  catch( const std::exception & ex )
1363  {
1365  [&]{
1366  return fmt::format(
1367  "[connection:{}] notificator error: {}",
1368  connection_id(),
1369  ex.what() );
1370  } );
1371  }
1372  }
1373  }
1374 
1377 
1379  void
1380  close() noexcept
1381  {
1383  [&]{
1384  return fmt::format(
1385  "[connection:{}] close",
1386  connection_id() );
1387  } );
1388 
1389  // shutdown() and close() should be called regardless of
1390  // possible exceptions.
1392  m_logger,
1393  "connection.socket.shutdown",
1394  [this] {
1395  asio_ns::error_code ignored_ec;
1396  m_socket.shutdown(
1397  asio_ns::ip::tcp::socket::shutdown_both,
1398  ignored_ec );
1399  } );
1401  m_logger,
1402  "connection.socket.close",
1403  [this] {
1404  m_socket.close();
1405  } );
1406 
1408  [&]{
1409  return fmt::format(
1410  "[connection:{}] close: close socket",
1411  connection_id() );
1412  } );
1413 
1414  // Clear stuff.
1416 
1418  [&]{
1419  return fmt::format(
1420  "[connection:{}] close: timer canceled",
1421  connection_id() );
1422  } );
1423 
1425 
1427  [&]{
1428  return fmt::format(
1429  "[connection:{}] close: reset responses data",
1430  connection_id() );
1431  } );
1432 
1433  // Inform state listener if it used.
1434  m_settings->call_state_listener_suppressing_exceptions(
1435  [this]() noexcept {
1437  this->connection_id(),
1438  this->m_remote_endpoint,
1440  };
1441  } );
1442  }
1443 
1445 
1449  template< typename Message_Builder >
1450  void
1451  trigger_error_and_close( Message_Builder msg_builder ) noexcept
1452  {
1453  // An exception from logger/msg_builder shouldn't prevent
1454  // a call to close().
1456  m_logger, std::move(msg_builder) );
1457 
1459  }
1461 
1464 
1467 
1470 
1473 
1476 
1477  // Memo flag: whether we need to resume read after this group is written
1479 
1482 
1485 
1487  static connection_t &
1489  {
1490  return static_cast< connection_t & >( base );
1491  }
1492 
1495  virtual void
1497  {
1498  asio_ns::dispatch(
1499  this->get_executor(),
1500  [ ctx = std::move( self ) ]
1501  // NOTE: this lambda is noexcept since v.0.6.0.
1502  () noexcept {
1503  auto & conn_object = cast_to_self( *ctx );
1504  // If an exception will be thrown we can only
1505  // close the connection.
1506  try
1507  {
1508  conn_object.check_timeout_impl();
1509  }
1510  catch( const std::exception & x )
1511  {
1512  conn_object.trigger_error_and_close( [&] {
1513  return fmt::format( "[connection: {}] unexpected "
1514  "error during timeout handling: {}",
1515  conn_object.connection_id(),
1516  x.what() );
1517  } );
1518  }
1519  } );
1520  }
1521 
1523  using timout_cb_t = void (connection_t::* )( void );
1524 
1527 
1529  std::chrono::steady_clock::time_point m_current_timeout_after;
1534 
1536  void
1538  {
1539  if( std::chrono::steady_clock::now() > m_current_timeout_after )
1540  {
1541  if( m_current_timeout_cb )
1542  (this->*m_current_timeout_cb)();
1543  }
1544  else
1545  {
1547  }
1548  }
1549 
1551  void
1553  {
1554  m_timer_guard.schedule( m_prepared_weak_ctx );
1555  }
1556 
1558  void
1560  {
1561  m_current_timeout_cb = nullptr;
1563  }
1564 
1566  void
1568  std::chrono::steady_clock::time_point timeout_after,
1569  timout_cb_t timout_cb )
1570  {
1571  m_current_timeout_after = timeout_after;
1572  m_current_timeout_cb = timout_cb;
1573  }
1574 
1575  void
1577  std::chrono::steady_clock::duration timeout,
1578  timout_cb_t timout_cb )
1579  {
1581  std::chrono::steady_clock::now() + timeout,
1582  timout_cb );
1583  }
1584 
1585  void
1586  handle_xxx_timeout( const char * operation_name )
1587  {
1588  m_logger.trace( [&]{
1589  return fmt::format(
1590  "[connection:{}] {} timed out",
1591  connection_id(),
1592  operation_name );
1593  } );
1594 
1595  close();
1596  }
1597 
1598  void
1600  {
1601  handle_xxx_timeout( "wait for request" );
1602  }
1603 
1605  void
1607  {
1609  {
1611  m_settings->m_read_next_http_message_timelimit,
1613  }
1614  }
1615 
1616  void
1618  {
1619  handle_xxx_timeout( "handle request" );
1620  }
1621 
1623  void
1625  {
1627  {
1629  m_settings->m_handle_request_timeout,
1631  }
1632  }
1633 
1634  void
1636  {
1637  handle_xxx_timeout( "writing response" );
1638  }
1639 
1641  void
1643  {
1645  m_settings->m_write_http_response_timelimit,
1647  }
1648 
1649  void
1651  {
1652  handle_xxx_timeout( "writing response (sendfile)" );
1653  }
1654 
1655  void
1656  guard_sendfile_operation( std::chrono::steady_clock::duration timelimit )
1657  {
1658  if( std::chrono::steady_clock::duration::zero() == timelimit )
1659  timelimit = m_settings->m_write_http_response_timelimit;
1660 
1662  timelimit,
1664  }
1666 
1669 
1672 
1682 };
1683 
1684 //
1685 // connection_factory_t
1686 //
1687 
1689 template < typename Traits >
1691 {
1692  public:
1693  using logger_t = typename Traits::logger_t;
1694  using stream_socket_t = typename Traits::stream_socket_t;
1697 
1699  connection_settings_handle_t< Traits > connection_settings,
1700  std::unique_ptr< socket_options_setter_t > socket_options_setter )
1701  : m_connection_settings{ std::move( connection_settings ) }
1702  , m_socket_options_setter{ std::move( socket_options_setter ) }
1703  , m_logger{ *(m_connection_settings->m_logger ) }
1704  {}
1705 
1706  // NOTE: since v.0.6.3 it returns non-empty
1707  // shared_ptr<connection_t<Traits>> or an exception is thrown in
1708  // the case of an error.
1709  // NOTE: since v.0.6.12 it accepts yet another parameter: lifetime_monitor.
1710  auto
1712  stream_socket_t socket,
1713  endpoint_t remote_endpoint,
1714  lifetime_monitor_t lifetime_monitor )
1715  {
1716  using connection_type_t = connection_t< Traits >;
1717 
1718  {
1719  socket_options_t options{ socket.lowest_layer() };
1720  (*m_socket_options_setter)( options );
1721  }
1722 
1723  return std::make_shared< connection_type_t >(
1725  std::move( socket ),
1727  std::move( remote_endpoint ),
1728  std::move( lifetime_monitor ) );
1729  }
1730 
1731  private:
1733 
1735 
1736  std::unique_ptr< socket_options_setter_t > m_socket_options_setter;
1737 
1739 };
1740 
1741 } /* namespace impl */
1742 
1743 } /* namespace restinio */
restinio::response_parts_attr_t::not_final_parts
@ not_final_parts
Intermediate parts (more parts of response to follow).
restinio::impl::connection_t::init
void init()
Definition: connection.hpp:371
restinio::tcp_connection_ctx_base_t::connection_id
connection_id_t connection_id() const noexcept
Get connection id.
Definition: tcp_connection_ctx_base.hpp:38
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
restinio::impl::connection_t::handle_file_write_operation
void handle_file_write_operation(file_write_operation_t &op)
Run sendfile write operation.
Definition: connection.hpp:1154
restinio::impl::fixed_buffer_t::length
std::size_t length() const noexcept
How many unconsumed bytes are there in buffer.
Definition: fixed_buffer.hpp:63
restinio::impl::fixed_buffer_t
Helper class for reading bytes and feeding them to parser.
Definition: fixed_buffer.hpp:27
restinio::impl::http_parser_ctx_t::m_header
http_request_header_t m_header
Request data.
Definition: connection.hpp:52
RESTINIO_NODISCARD
#define RESTINIO_NODISCARD
Definition: compiler_features.hpp:33
restinio::impl::write_group_output_ctx_t::trivial_write_operation_t
Trivial write operaton.
Definition: write_group_output_ctx.hpp:106
restinio::impl::executor_wrapper_t< Traits::strand_t >::get_executor
Traits::strand_t & get_executor() noexcept
An executor for callbacks on async operations.
Definition: executor_wrapper.hpp:35
restinio::impl::connection_t::init_write
void init_write()
Initiate write operation.
Definition: connection.hpp:972
restinio::impl::connection_t::handle_xxx_timeout
void handle_xxx_timeout(const char *operation_name)
Definition: connection.hpp:1586
restinio::impl::response_coordinator_t::append_response
void append_response(request_id_t req_id, response_output_flags_t response_output_flags, write_group_t wg)
Add outgoing data for specified request.
Definition: response_coordinator.hpp:324
restinio::impl::connection_t::m_logger
logger_t & m_logger
Logger for operation.
Definition: connection.hpp:1671
restinio::impl::connection_t::request_handler_t
typename Traits::request_handler_t request_handler_t
Definition: connection.hpp:312
restinio::impl::prepare_connection_and_start_read
void prepare_connection_and_start_read(asio_ns::ip::tcp::socket &, Connection &, Start_Read_CB start_read_cb, Failed_CB)
Definition: connection.hpp:265
restinio::impl::connection_t::m_remote_endpoint
const endpoint_t m_remote_endpoint
Remote endpoint for this connection.
Definition: connection.hpp:1469
response_coordinator.hpp
restinio::impl::connection_t::schedule_operation_timeout_callback
void schedule_operation_timeout_callback(std::chrono::steady_clock::time_point timeout_after, timout_cb_t timout_cb)
Helper function to work with timer guard.
Definition: connection.hpp:1567
restinio::impl::connection_t::upgrade_internals_t::upgrade_internals_t
upgrade_internals_t(upgrade_internals_t &&)=default
restinio::impl::http_parser_ctx_t::m_total_field_count
std::size_t m_total_field_count
Total number of parsed HTTP-fields.
Definition: connection.hpp:84
restinio::impl::connection_factory_t
Factory for connections.
Definition: connection.hpp:1691
restinio::impl::connection_t::connection_t
connection_t(connection_t &&)=delete
restinio::impl::connection_factory_t::logger_t
typename Traits::logger_t logger_t
Definition: connection.hpp:1693
restinio::impl::connection_t::connection_t
connection_t(connection_id_t conn_id, stream_socket_t &&socket, connection_settings_handle_t< Traits > settings, endpoint_t remote_endpoint, lifetime_monitor_t lifetime_monitor)
Definition: connection.hpp:319
nonstd::optional_lite::std11::move
T & move(T &t)
Definition: optional.hpp:421
restinio::impl::connection_t::~connection_t
~connection_t() override
Definition: connection.hpp:360
restinio::impl::connection_t::upgrade_internals_t::m_socket
stream_socket_t m_socket
Definition: connection.hpp:455
restinio::impl::write_group_output_ctx_t::transmitting
bool transmitting() const noexcept
Check if data is trunsmitting now.
Definition: write_group_output_ctx.hpp:235
restinio::impl::connection_t::m_prepared_weak_ctx
tcp_connection_ctx_weak_handle_t m_prepared_weak_ctx
A prepared weak handle for passing it to timer guard.
Definition: connection.hpp:1533
restinio::impl::chunked_input_info_block_t
Bunch of data related to chunked input.
Definition: chunked_input_info.hpp:116
restinio::impl::connection_factory_t::create_new_connection
auto create_new_connection(stream_socket_t socket, endpoint_t remote_endpoint, lifetime_monitor_t lifetime_monitor)
Definition: connection.hpp:1711
restinio::endpoint_t
asio_ns::ip::tcp::endpoint endpoint_t
An alias for endpoint type from Asio.
Definition: common_types.hpp:158
request_handler.hpp
restinio::impl::write_group_output_ctx_t
Helper class for writting response data.
Definition: write_group_output_ctx.hpp:80
restinio::impl::write_group_output_ctx_t::extract_next_write_operation
solid_write_operation_variant_t extract_next_write_operation()
et an object with next write operation to perform.
Definition: write_group_output_ctx.hpp:253
restinio::file_size_t
std::uint64_t file_size_t
Definition: sendfile_defs_default.hpp:23
restinio::connection_count_limits::connection_lifetime_monitor_t
Helper type for controlling the lifetime of the connection.
Definition: connection_count_limiter.hpp:375
restinio::impl::http_parser_ctx_t::m_current_field_name
std::string m_current_field_name
Parser context temp values and flags.
Definition: connection.hpp:58
restinio::impl::connection_t::init_write_if_necessary
void init_write_if_necessary()
Definition: connection.hpp:960
restinio::impl::connection_t::wait_for_http_message
void wait_for_http_message()
Start reading next htttp-message.
Definition: connection.hpp:408
asio_include.hpp
restinio::impl::make_tls_socket_pointer_for_state_listener
tls_socket_t * make_tls_socket_pointer_for_state_listener(asio_ns::ip::tcp::socket &) noexcept
Definition: connection.hpp:277
restinio::impl::write_group_output_ctx_t::fail_write_group
void fail_write_group(const asio_ns::error_code &ec)
Handle current group write process failed.
Definition: write_group_output_ctx.hpp:283
restinio_chunk_header_cb
int restinio_chunk_header_cb(http_parser *parser)
Definition: parser_callbacks.ipp:186
restinio::impl::connection_t::check_timeout
virtual void check_timeout(tcp_connection_ctx_handle_t &self) override
Schedules real timedout operations check on the executer of a connection.
Definition: connection.hpp:1496
restinio::impl::http_parser_ctx_t::m_body
std::string m_body
Definition: connection.hpp:53
restinio::impl::connection_t::init_next_timeout_checking
void init_next_timeout_checking()
Schedule next timeout checking.
Definition: connection.hpp:1552
restinio::impl::http_parser_ctx_t::m_message_complete
bool m_message_complete
Flag: is http message parsed completely.
Definition: connection.hpp:74
restinio::impl::connection_t::cancel_timeout_checking
void cancel_timeout_checking() noexcept
Stop timout guarding.
Definition: connection.hpp:1559
restinio::impl::connection_input_t::connection_input_t
connection_input_t(std::size_t buffer_size, incoming_http_msg_limits_t limits)
Definition: connection.hpp:227
restinio::http_field_parsers::qvalue_details::zero
constexpr underlying_uint_t zero
The minimal allowed value for a qvalue.
Definition: basics.hpp:41
restinio::impl::executor_wrapper_t
Wrapper for an executor (strand) used by connections.
Definition: executor_wrapper.hpp:25
restinio::write_group_t::items_count
auto items_count() const noexcept
Get the count of stored items.
Definition: buffers.hpp:832
restinio::impl::connection_t::handle_upgrade_request
void handle_upgrade_request()
Calls handler for upgrade request.
Definition: connection.hpp:747
restinio::impl::connection_t::check_timeout_impl
void check_timeout_impl()
Check timed out operation.
Definition: connection.hpp:1537
restinio::impl::write_group_output_ctx_t::start_next_write_group
void start_next_write_group(optional_t< write_group_t > next_wg) noexcept
Start handlong next write group.
Definition: write_group_output_ctx.hpp:239
restinio::impl::connection_t::move_upgrade_internals
upgrade_internals_t move_upgrade_internals()
Move socket out of connection.
Definition: connection.hpp:461
restinio::response_connection_attr_t::connection_close
@ connection_close
This response says to close connection.
restinio::string_view_t
nonstd::string_view string_view_t
Definition: string_view.hpp:19
restinio::impl::connection_factory_t::connection_factory_t
connection_factory_t(connection_settings_handle_t< Traits > connection_settings, std::unique_ptr< socket_options_setter_t > socket_options_setter)
Definition: connection.hpp:1698
restinio::impl::response_coordinator_t::empty
bool empty() const noexcept
Definition: response_coordinator.hpp:302
restinio::impl::fixed_buffer_t::consumed_bytes
void consumed_bytes(std::size_t length) noexcept
Mark how many bytes were obtained.
Definition: fixed_buffer.hpp:56
restinio::utils::at_scope_exit
scope_exit_details::at_exit_t< L > at_scope_exit(L &&l)
Helper function for creation action to be performed at scope exit.
Definition: at_scope_exit.hpp:60
connection_base.hpp
restinio::connection_id_t
std::uint64_t connection_id_t
Type for ID of connection.
Definition: common_types.hpp:155
restinio::impl::connection_t::guard_request_handling_operation
void guard_request_handling_operation()
Start guard request handling operation if necessary.
Definition: connection.hpp:1624
restinio::impl::http_parser_ctx_t::make_chunked_input_info_if_necessary
RESTINIO_NODISCARD chunked_input_info_unique_ptr_t make_chunked_input_info_if_necessary()
Creates an instance of chunked_input_info if there is an info about chunks in the body.
Definition: connection.hpp:124
restinio_chunk_complete_cb
int restinio_chunk_complete_cb(http_parser *)
Definition: parser_callbacks.ipp:218
restinio::impl::response_coordinator_t
Coordinator for process of sending responses with respect to http pipeline technique and chunk transf...
Definition: response_coordinator.hpp:289
restinio::websocket::basic::upgrade
ws_handle_t upgrade(request_t &req, activation_t activation_flag, http_header_fields_t upgrade_response_header_fields, WS_Message_Handler ws_message_handler)
Upgrade http-connection of a current request to a websocket connection.
Definition: websocket.hpp:215
restinio_url_cb
int restinio_url_cb(http_parser *parser, const char *at, size_t length)
Definition: parser_callbacks.ipp:10
restinio::impl::connection_t::schedule_operation_timeout_callback
void schedule_operation_timeout_callback(std::chrono::steady_clock::duration timeout, timout_cb_t timout_cb)
Definition: connection.hpp:1576
restinio::incoming_http_msg_limits_t
A type of holder of limits related to an incoming HTTP message.
Definition: incoming_http_msg_limits.hpp:69
restinio::connection_state::accepted_t
Type of object that tells that new connection has been accepted.
Definition: connection_state_listener.hpp:36
restinio::impl::connection_input_t::m_parser
http_parser m_parser
HTTP-parser.
Definition: connection.hpp:236
RESTINIO_ENSURE_NOEXCEPT_CALL
#define RESTINIO_ENSURE_NOEXCEPT_CALL(expr)
A wrapper around static_assert for checking that an expression is noexcept and execution of that expr...
Definition: compiler_features.hpp:60
restinio_headers_complete_cb
int restinio_headers_complete_cb(http_parser *parser)
Definition: parser_callbacks.ipp:124
restinio::impl::connection_t::finish_handling_current_write_ctx
void finish_handling_current_write_ctx()
Do post write actions for current write group.
Definition: connection.hpp:1234
restinio::impl::connection_t::upgrade_internals_t::m_lifetime_monitor
lifetime_monitor_t m_lifetime_monitor
Definition: connection.hpp:456
connection_settings.hpp
connection_count_limiter.hpp
Stuff related to limits of active parallel connections.
restinio::impl::fixed_buffer_t::obtained_bytes
void obtained_bytes(std::size_t length) noexcept
Mark how many bytes were obtained.
Definition: fixed_buffer.hpp:48
restinio::impl::connection_t::logger_t
typename Traits::logger_t logger_t
Definition: connection.hpp:313
restinio::utils::log_error_noexcept
void log_error_noexcept(Logger &&logger, Message_Builder &&builder) noexcept
Definition: suppress_exceptions.hpp:71
restinio::impl::response_coordinator_t::register_new_request
request_id_t register_new_request()
Create a new request and reserve context for its response.
Definition: response_coordinator.hpp:315
restinio::impl::http_parser_ctx_t::m_chunked_info_block
chunked_input_info_block_t m_chunked_info_block
Definition: connection.hpp:70
restinio::impl::write_group_output_ctx_t::none_write_operation_t
None write operation.
Definition: write_group_output_ctx.hpp:232
restinio::impl::connection_upgrade_stage_t
connection_upgrade_stage_t
Enum for a flag specifying that connection is going to upgrade or not.
Definition: connection.hpp:206
restinio::impl::connection_t::consume_data
void consume_data(const char *data, std::size_t length)
Parse some data.
Definition: connection.hpp:578
restinio::impl::connection_factory_t::m_socket_options_setter
std::unique_ptr< socket_options_setter_t > m_socket_options_setter
Definition: connection.hpp:1736
restinio::write_group_t::invoke_after_write_notificator_if_exists
void invoke_after_write_notificator_if_exists(const asio_ns::error_code &ec)
Get after write notificator.
Definition: buffers.hpp:815
restinio::impl::connection_t::handle_nothing_to_write
void handle_nothing_to_write()
Definition: connection.hpp:1293
restinio::impl::chunked_input_info_block_t::m_chunks
std::vector< chunk_info_t > m_chunks
All non-empty chunks from the input.
Definition: chunked_input_info.hpp:118
restinio::impl::connection_t::on_request_message_complete
void on_request_message_complete()
Handle a given request message.
Definition: connection.hpp:625
restinio::impl::connection_t::cast_to_self
static connection_t & cast_to_self(tcp_connection_ctx_base_t &base)
Timer to controll operations.
Definition: connection.hpp:1488
restinio::impl::connection_settings_handle_t
std::shared_ptr< connection_settings_t< Traits > > connection_settings_handle_t
Definition: connection_settings.hpp:199
restinio::impl::http_parser_ctx_t::reset
void reset()
Prepare context to handle new request.
Definition: connection.hpp:105
restinio::impl::tls_socket_t
Socket adapter for asio::ssl::stream< asio::ip::tcp::socket >.
Definition: tls_socket.hpp:37
restinio::impl::http_parser_ctx_t::m_last_was_value
bool m_last_was_value
Definition: connection.hpp:60
restinio::impl::connection_input_t::m_connection_upgrade_stage
connection_upgrade_stage_t m_connection_upgrade_stage
Connection upgrade request stage.
Definition: connection.hpp:244
restinio::impl::http_parser_ctx_t::m_leading_headers_completed
bool m_leading_headers_completed
Definition: connection.hpp:65
restinio::impl::connection_t::stream_socket_t
typename Traits::stream_socket_t stream_socket_t
Definition: connection.hpp:315
restinio::socket_options_t
An adapter for setting acceptor options before running server.
Definition: settings.hpp:249
restinio::impl::fixed_buffer_t::make_asio_buffer
auto make_asio_buffer() noexcept
Make asio buffer for reading bytes from socket.
Definition: fixed_buffer.hpp:41
executor_wrapper.hpp
restinio::impl::connection_t::handle_sendfile_timeout
void handle_sendfile_timeout()
Definition: connection.hpp:1650
restinio::impl::chunked_input_info_block_t::m_trailing_fields
http_header_fields_t m_trailing_fields
Trailing fields found in the input.
Definition: chunked_input_info.hpp:125
restinio::impl::connection_input_t
Data associated with connection read routine.
Definition: connection.hpp:226
restinio::impl::write_group_output_ctx_t::file_write_operation_t::size
auto size() const noexcept
Get the size of sendfile operation.
Definition: write_group_output_ctx.hpp:212
restinio::utils::log_trace_noexcept
void log_trace_noexcept(Logger &&logger, Message_Builder &&builder) noexcept
Definition: suppress_exceptions.hpp:32
restinio::impl::connection_t::handle_request_handling_timeout
void handle_request_handling_timeout()
Definition: connection.hpp:1617
restinio::impl::connection_t::write_response_parts_impl
void write_response_parts_impl(request_id_t request_id, response_output_flags_t response_output_flags, write_group_t wg)
Write parts for specified request.
Definition: connection.hpp:868
restinio::impl::connection_t::m_socket
stream_socket_t m_socket
Connection.
Definition: connection.hpp:1463
write_group_output_ctx.hpp
restinio::impl::connection_t::upgrade_internals_t::m_settings
connection_settings_handle_t< Traits > m_settings
Definition: connection.hpp:454
restinio::impl::connection_t::m_timer_guard
timer_guard_t m_timer_guard
Timer guard.
Definition: connection.hpp:1531
restinio::utils::suppress_exceptions
void suppress_exceptions(Logger &&logger, const char *block_description, Lambda &&lambda) noexcept
Helper function for execution a block of code with suppression of any exceptions raised inside that b...
Definition: suppress_exceptions.hpp:94
include_fmtlib.hpp
A special wrapper around fmtlib include files.
restinio::impl::connection_t::m_input
connection_input_t m_input
Input routine.
Definition: connection.hpp:1472
restinio::impl::connection_t::trigger_error_and_close
void trigger_error_and_close(Message_Builder msg_builder) noexcept
Trigger an error.
Definition: connection.hpp:1451
restinio::tcp_connection_ctx_base_t
TCP connection base.
Definition: tcp_connection_ctx_base.hpp:29
restinio::impl::connection_t::timer_manager_t
typename Traits::timer_manager_t timer_manager_t
Definition: connection.hpp:310
restinio::impl::connection_factory_t::m_logger
logger_t & m_logger
Definition: connection.hpp:1738
restinio_body_cb
int restinio_body_cb(http_parser *parser, const char *at, size_t length)
Definition: parser_callbacks.ipp:159
restinio::impl::connection_input_t::m_parser_ctx
http_parser_ctx_t m_parser_ctx
Definition: connection.hpp:237
restinio_header_field_cb
int restinio_header_field_cb(http_parser *parser, const char *at, size_t length)
Definition: parser_callbacks.ipp:35
restinio::impl::http_parser_ctx_t::http_parser_ctx_t
http_parser_ctx_t(incoming_http_msg_limits_t limits)
The main constructor.
Definition: connection.hpp:98
restinio::impl::connection_input_t::reset_parser
void reset_parser()
Prepare parser for reading new http-message.
Definition: connection.hpp:252
restinio::impl::http_parser_ctx_t::m_last_value_total_size
std::size_t m_last_value_total_size
Definition: connection.hpp:59
restinio::impl::connection_base_t
HTTP connection base.
Definition: connection_base.hpp:29
restinio::impl::write_group_output_ctx_t::file_write_operation_t::timelimit
auto timelimit() const noexcept
Get the timelimit on this sendfile operation.
Definition: write_group_output_ctx.hpp:193
restinio::connection_state::notice_t
An object with info about connection to be passed to state listener.
Definition: connection_state_listener.hpp:225
restinio::write_group_t
Group of writable items transported to the context of underlying connection as one solid piece.
Definition: buffers.hpp:692
restinio::impl::connection_t::operator=
connection_t & operator=(const connection_t &)=delete
restinio::impl::connection_t::timout_cb_t
void(connection_t::*)(void) timout_cb_t
Callback type for timedout operations.
Definition: connection.hpp:1523
restinio::error_is_eof
bool error_is_eof(const asio_ns::error_code &ec) noexcept
Definition: asio_include.hpp:33
restinio::impl::write_group_output_ctx_t::file_write_operation_t::start_sendfile_operation
void start_sendfile_operation(default_asio_executor executor, Socket &socket, After_Write_CB after_sendfile_cb)
Start a sendfile operation.
Definition: write_group_output_ctx.hpp:167
restinio
Definition: asio_include.hpp:21
restinio::response_output_flags_t
Response output flags for buffers commited to response-coordinator.
Definition: common_types.hpp:104
fixed_buffer.hpp
sendfile_operation.hpp
restinio::impl::write_group_output_ctx_t::finish_write_group
void finish_write_group()
Finish writing group normally.
Definition: write_group_output_ctx.hpp:294
restinio::impl::connection_factory_t::stream_socket_t
typename Traits::stream_socket_t stream_socket_t
Definition: connection.hpp:1694
restinio::impl::write_group_output_ctx_t::trivial_write_operation_t::get_trivial_bufs
const std::vector< asio_ns::const_buffer > & get_trivial_bufs() const noexcept
Get buffer "iovec" for performing gather write.
Definition: write_group_output_ctx.hpp:127
header_helpers.hpp
restinio::impl::connection_t::m_response_coordinator
response_coordinator_t m_response_coordinator
Response coordinator.
Definition: connection.hpp:1481
at_scope_exit.hpp
A simple implementation of at_scope_exit concept.
restinio::impl::connection_t::handle_read_timeout
void handle_read_timeout()
Definition: connection.hpp:1599
restinio::impl::connection_factory_t::lifetime_monitor_t
typename connection_count_limit_types< Traits >::lifetime_monitor_t lifetime_monitor_t
Definition: connection.hpp:1696
exception.hpp
restinio::impl::write_group_output_ctx_t::trivial_write_operation_t::size
auto size() const noexcept
The size of data within this operation.
Definition: write_group_output_ctx.hpp:133
restinio::impl::connection_factory_t::m_connection_settings
connection_settings_handle_t< Traits > m_connection_settings
Definition: connection.hpp:1734
restinio::impl::connection_t::guard_read_operation
void guard_read_operation()
Statr guard read operation if necessary.
Definition: connection.hpp:1606
restinio::connection_state::closed_t
Type of object that tells that the connection has been closed.
Definition: connection_state_listener.hpp:183
restinio::impl::response_coordinator_t::pop_ready_buffers
optional_t< std::pair< write_group_t, request_id_t > > pop_ready_buffers()
Extract a portion of data available for write.
Definition: response_coordinator.hpp:371
restinio::impl::connection_t::m_settings
connection_settings_handle_t< Traits > m_settings
Common paramaters of a connection.
Definition: connection.hpp:1466
restinio::impl::connection_t::handle_trivial_write_operation
void handle_trivial_write_operation(const trivial_write_operation_t &op)
Run trivial buffers write operation.
Definition: connection.hpp:1091
restinio::impl::connection_t::m_init_read_after_this_write
bool m_init_read_after_this_write
Definition: connection.hpp:1478
restinio::impl::connection_t::handle_write_response_timeout
void handle_write_response_timeout()
Definition: connection.hpp:1635
restinio::tcp_connection_ctx_handle_t
std::shared_ptr< tcp_connection_ctx_base_t > tcp_connection_ctx_handle_t
Alias for http connection handle.
Definition: tcp_connection_ctx_base.hpp:62
restinio::impl::connection_input_t::m_buf
fixed_buffer_t m_buf
Input buffer.
Definition: connection.hpp:241
restinio::impl::connection_t::executor_wrapper_base_t
executor_wrapper_t< typename Traits::strand_t > executor_wrapper_base_t
Definition: connection.hpp:307
restinio::impl::connection_input_t::m_read_operation_is_running
bool m_read_operation_is_running
Flag to track whether read operation is performed now.
Definition: connection.hpp:248
restinio::request_id_t
unsigned int request_id_t
Request id in scope of single connection.
Definition: common_types.hpp:51
restinio::impl::connection_t::after_read
void after_read(const asio_ns::error_code &ec, std::size_t length) noexcept
Handle read operation result.
Definition: connection.hpp:509
restinio::impl::http_parser_ctx_t
Parsing result context for using in parser callbacks.
Definition: connection.hpp:49
restinio::impl::connection_t::upgrade_internals_t
Internals that are necessary for upgrade.
Definition: connection.hpp:441
restinio::tcp_connection_ctx_weak_handle_t
std::weak_ptr< tcp_connection_ctx_base_t > tcp_connection_ctx_weak_handle_t
Alias for http connection weak handle.
Definition: tcp_connection_ctx_base.hpp:65
restinio::impl::connection_t::close
void close() noexcept
Close connection functions.
Definition: connection.hpp:1380
restinio::impl::connection_upgrade_stage_t::none
@ none
No connection request in progress.
restinio::impl::response_coordinator_t::is_able_to_get_more_messages
bool is_able_to_get_more_messages() const noexcept
Check if it is possible to accept more requests.
Definition: response_coordinator.hpp:308
restinio::http_header_fields_t::fields_count
auto fields_count() const noexcept
Definition: http_headers.hpp:1493
restinio::impl::fixed_buffer_t::bytes
const char * bytes() const noexcept
Get pointer to unconsumed bytes.
Definition: fixed_buffer.hpp:69
restinio::impl::connection_t::m_lifetime_monitor
lifetime_monitor_t m_lifetime_monitor
Monitor of the connection lifetime.
Definition: connection.hpp:1681
restinio::impl::connection_t::consume_message
void consume_message()
Start (continue) a chain of read-parse-read-... operations.
Definition: connection.hpp:473
restinio::error_is_operation_aborted
bool error_is_operation_aborted(const asio_ns::error_code &ec) noexcept
Definition: asio_include.hpp:27
restinio::impl::connection_t::m_current_timeout_after
std::chrono::steady_clock::time_point m_current_timeout_after
Timeout point of a current guarded operation.
Definition: connection.hpp:1529
restinio_header_value_cb
int restinio_header_value_cb(http_parser *parser, const char *at, size_t length)
Definition: parser_callbacks.ipp:80
safe_uint_truncate.hpp
Helpers for safe truncation of unsigned integers.
restinio::impl::response_coordinator_t::reset
void reset() noexcept
Remove all contexts.
Definition: response_coordinator.hpp:416
restinio::chunked_input_info_unique_ptr_t
std::unique_ptr< chunked_input_info_t > chunked_input_info_unique_ptr_t
Alias of unique_ptr for chunked_input_info.
Definition: chunked_input_info.hpp:230
restinio::http_request_header_t
Req header.
Definition: http_headers.hpp:1859
restinio::request_rejected
constexpr request_handling_status_t request_rejected() noexcept
Definition: common_types.hpp:44
restinio::impl::connection_t::handle_current_write_ctx
void handle_current_write_ctx() noexcept
Start/continue/continue handling output data of current write group.
Definition: connection.hpp:1058
restinio::impl::http_parser_ctx_t::m_limits
const incoming_http_msg_limits_t m_limits
Limits for the incoming message.
Definition: connection.hpp:91
restinio::impl::connection_t::timer_guard_t
typename timer_manager_t::timer_guard_t timer_guard_t
Definition: connection.hpp:311
restinio::impl::connection_t::upgrade_internals_t::upgrade_internals_t
upgrade_internals_t(connection_settings_handle_t< Traits > settings, stream_socket_t socket, lifetime_monitor_t lifetime_monitor)
Definition: connection.hpp:445
restinio::impl::response_coordinator_t::closed
bool closed() const noexcept
Definition: response_coordinator.hpp:301
restinio::impl::connection_factory_t::m_connection_id_counter
connection_id_t m_connection_id_counter
Definition: connection.hpp:1732
restinio::impl::response_coordinator_t::is_full
bool is_full() const noexcept
Definition: response_coordinator.hpp:303
restinio::impl::connection_t::connection_t
connection_t(const connection_t &)=delete
restinio::impl::create_not_implemented_resp
auto create_not_implemented_resp()
Definition: header_helpers.hpp:156
restinio::impl::connection_t::m_write_output_ctx
write_group_output_ctx_t m_write_output_ctx
Write to socket operation context.
Definition: connection.hpp:1475
restinio::impl::connection_t::after_write
void after_write(const asio_ns::error_code &ec) noexcept
Handle write response finished.
Definition: connection.hpp:1339
restinio::impl::connection_t::strand_t
typename Traits::strand_t strand_t
Definition: connection.hpp:314
http_headers.hpp
restinio::impl::connection_t::m_request_handler
request_handler_t & m_request_handler
Request handler.
Definition: connection.hpp:1668
restinio::impl::connection_t::guard_sendfile_operation
void guard_sendfile_operation(std::chrono::steady_clock::duration timelimit)
Definition: connection.hpp:1656
restinio::impl::connection_t
Context for handling http connections.
Definition: connection.hpp:306
parser_callbacks.ipp
restinio::impl::connection_t::m_current_timeout_cb
timout_cb_t m_current_timeout_cb
Callback to all if timeout happened.
Definition: connection.hpp:1526
restinio::impl::connection_t::lifetime_monitor_t
typename connection_count_limit_types< Traits >::lifetime_monitor_t lifetime_monitor_t
Definition: connection.hpp:317
restinio::impl::connection_t::write_response_parts
virtual void write_response_parts(request_id_t request_id, response_output_flags_t response_output_flags, write_group_t wg) override
Write parts for specified request.
Definition: connection.hpp:828
restinio::impl::write_group_output_ctx_t::file_write_operation_t
Write operaton using sendfile.
Definition: write_group_output_ctx.hpp:142
restinio::impl::create_parser_settings
http_parser_settings create_parser_settings() noexcept
Include parser callbacks.
Definition: connection.hpp:152
restinio::impl::connection_t::guard_write_operation
void guard_write_operation()
Start guard write operation if necessary.
Definition: connection.hpp:1642