RESTinio

connection.hpp
Go to the documentation of this file.
1/*
2 restinio
3*/
4
9#pragma once
10
11#include <restinio/asio_include.hpp>
12
13#include <http_parser.h>
14
15#include <restinio/impl/include_fmtlib.hpp>
16
17#include <restinio/exception.hpp>
18#include <restinio/http_headers.hpp>
19#include <restinio/request_handler.hpp>
20#include <restinio/connection_count_limiter.hpp>
21#include <restinio/impl/connection_base.hpp>
22#include <restinio/impl/header_helpers.hpp>
23#include <restinio/impl/response_coordinator.hpp>
24#include <restinio/impl/connection_settings.hpp>
25#include <restinio/impl/fixed_buffer.hpp>
26#include <restinio/impl/write_group_output_ctx.hpp>
27#include <restinio/impl/executor_wrapper.hpp>
28#include <restinio/impl/sendfile_operation.hpp>
29
30#include <restinio/utils/impl/safe_uint_truncate.hpp>
31#include <restinio/utils/at_scope_exit.hpp>
32
33 namespace restinio
34{
35
36 namespace impl
37{
38
39//
40// http_parser_ctx_t
41//
42
44
48 struct http_parser_ctx_t
49{
52 http_request_header_t m_header;
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
65 bool m_leading_headers_completed{ false };
66
70 chunked_input_info_block_t m_chunked_info_block;
72
74 bool m_message_complete{ false };
75
84 std::size_t m_total_field_count{ 0u };
85
91 const incoming_http_msg_limits_t m_limits;
92
98 http_parser_ctx_t(
99 incoming_http_msg_limits_t limits )
100 : m_limits{ limits }
101 {}
102
104 void
105 reset()
106 {
107 m_header = http_request_header_t{};
108 m_body.clear();
109 m_current_field_name.clear();
110 m_last_value_total_size = 0u;
111 m_last_was_value = true;
112 m_leading_headers_completed = false;
113 m_message_complete = false;
114 m_total_field_count = 0u;
115 }
116
119
122 RESTINIO_NODISCARD
123 chunked_input_info_unique_ptr_t
124 make_chunked_input_info_if_necessary()
125 {
126 chunked_input_info_unique_ptr_t result;
127
128 if( !m_chunked_info_block.m_chunks.empty() ||
129 0u != m_chunked_info_block.m_trailing_fields.fields_count() )
130 {
131 result = std::make_unique< chunked_input_info_t >(
132 std::move( m_chunked_info_block ) );
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
152 create_parser_settings() noexcept
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,
217 wait_for_upgrade_handling_result_or_nothing
218};
219
220//
221// connection_input_t
222//
223
225 struct connection_input_t
226{
227 connection_input_t(
228 std::size_t buffer_size,
229 incoming_http_msg_limits_t limits )
230 : m_parser_ctx{ limits }
231 , m_buf{ buffer_size }
232 {}
233
236 http_parser m_parser;
237 http_parser_ctx_t m_parser_ctx;
239
241 fixed_buffer_t m_buf;
242
244 connection_upgrade_stage_t m_connection_upgrade_stage{
245 connection_upgrade_stage_t::none };
246
248 bool m_read_operation_is_running{ false };
249
251 void
252 reset_parser()
253 {
254 // Reinit parser.
255 http_parser_init( &m_parser, HTTP_REQUEST);
256
257 // Reset context and attach it to parser.
258 m_parser_ctx.reset();
259 m_parser.data = &m_parser_ctx;
260 }
261};
262
263 template < typename Connection, typename Start_Read_CB, typename Failed_CB >
264 void
265 prepare_connection_and_start_read(
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 *
277 make_tls_socket_pointer_for_state_listener(
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{
307 using executor_wrapper_base_t = executor_wrapper_t< typename Traits::strand_t >;
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 = request_handler_type_from_traits_t< Traits >;
313 using generic_request_t = generic_request_type_from_traits_t< Traits >;
314 using logger_t = typename Traits::logger_t;
315 using strand_t = typename Traits::strand_t;
316 using stream_socket_t = typename Traits::stream_socket_t;
317 using lifetime_monitor_t =
318 typename connection_count_limit_types<Traits>::lifetime_monitor_t;
319
320 connection_t(
322 connection_id_t conn_id,
324 stream_socket_t && socket,
326 connection_settings_handle_t< Traits > settings,
328 endpoint_t remote_endpoint,
330 lifetime_monitor_t lifetime_monitor )
331 : connection_base_t{ conn_id }
332 , executor_wrapper_base_t{ socket.get_executor() }
333 , m_socket{ std::move( socket ) }
334 , m_settings{ std::move( settings ) }
335 , m_remote_endpoint{ std::move( remote_endpoint ) }
336 , m_input{
337 m_settings->m_buffer_size,
338 m_settings->m_incoming_http_msg_limits
339 }
340 , m_response_coordinator{ m_settings->m_max_pipelined_requests }
341 , m_timer_guard{ m_settings->create_timer_guard() }
342 , m_request_handler{ *( m_settings->m_request_handler ) }
343 , m_logger{ *( m_settings->m_logger ) }
344 , m_lifetime_monitor{ std::move(lifetime_monitor) }
345 {
346 // Notify of a new connection instance.
347 m_logger.trace( [&]{
348 return fmt::format(
349 "[connection:{}] start connection with {}",
350 connection_id(),
351 m_remote_endpoint );
352 } );
353 }
354
355 // Disable copy/move.
356 connection_t( const connection_t & ) = delete;
357 connection_t( connection_t && ) = delete;
358 connection_t & operator = ( const connection_t & ) = delete;
359 connection_t & operator = ( connection_t && ) = delete;
360
361 ~connection_t() override
362 {
363 restinio::utils::log_trace_noexcept( m_logger,
364 [&]{
365 return fmt::format(
366 "[connection:{}] destructor called",
367 connection_id() );
368 } );
369 }
370
371 void
372 init()
373 {
374 prepare_connection_and_start_read(
375 m_socket,
376 *this,
377 [ & ]{
378 // Inform state listener if it used.
379 m_settings->call_state_listener( [this]() noexcept {
380 return connection_state::notice_t{
381 this->connection_id(),
382 this->m_remote_endpoint,
383 connection_state::accepted_t{
384 make_tls_socket_pointer_for_state_listener(
385 m_socket )
386 }
387 };
388 } );
389
390 // Start timeout checking.
391 m_prepared_weak_ctx = shared_from_this();
392 init_next_timeout_checking();
393
394 // Start reading request.
395 wait_for_http_message();
396 },
397 [ & ]( const asio_ns::error_code & ec ){
398 trigger_error_and_close( [&]{
399 return fmt::format(
400 "[connection:{}] prepare connection error: {}",
401 connection_id(),
402 ec.message() );
403 } );
404 } );
405 }
406
408 void
409 wait_for_http_message()
410 {
411 m_logger.trace( [&]{
412 return fmt::format(
413 "[connection:{}] start waiting for request",
414 connection_id() );
415 } );
416
417 // Prepare parser for consuming new request message.
418 m_input.reset_parser();
419
420 // Guard total time for a request to be read.
421 // guarding here makes the total read process
422 // to run in read_next_http_message_timelimit.
423 guard_read_operation();
424
425 if( 0 != m_input.m_buf.length() )
426 {
427 // If a pipeline requests were sent by client
428 // then the biginning (or even entire request) of it
429 // is in the buffer obtained from socket in previous
430 // read operation.
431 consume_data( m_input.m_buf.bytes(), m_input.m_buf.length() );
432 }
433 else
434 {
435 // Next request (if any) must be obtained from socket.
436 consume_message();
437 }
438 }
439
441 struct upgrade_internals_t
442 {
443 upgrade_internals_t(
444 upgrade_internals_t && ) = default;
445
446 upgrade_internals_t(
447 connection_settings_handle_t< Traits > settings,
448 stream_socket_t socket,
449 lifetime_monitor_t lifetime_monitor )
450 : m_settings{ std::move(settings) }
451 , m_socket{ std::move( socket ) }
452 , m_lifetime_monitor{ std::move(lifetime_monitor) }
453 {}
454
455 connection_settings_handle_t< Traits > m_settings;
456 stream_socket_t m_socket;
457 lifetime_monitor_t m_lifetime_monitor;
458 };
459
461 upgrade_internals_t
462 move_upgrade_internals()
463 {
464 return upgrade_internals_t{
465 m_settings,
466 std::move(m_socket),
467 std::move(m_lifetime_monitor)
468 };
469 }
470
471 private:
473 inline void
474 consume_message()
475 {
476 if( !m_input.m_read_operation_is_running )
477 {
478 m_logger.trace( [&]{
479 return fmt::format(
480 "[connection:{}] continue reading request",
481 connection_id() );
482 } );
483
484
485 m_input.m_read_operation_is_running = true;
486 m_socket.async_read_some(
487 m_input.m_buf.make_asio_buffer(),
488 asio_ns::bind_executor(
489 this->get_executor(),
490 [this, ctx = shared_from_this()]
491 // NOTE: this lambda is noexcept since v.0.6.0.
492 ( const asio_ns::error_code & ec,
493 std::size_t length ) noexcept {
494 m_input.m_read_operation_is_running = false;
495 RESTINIO_ENSURE_NOEXCEPT_CALL( after_read( ec, length ) );
496 } ) );
497 }
498 else
499 {
500 m_logger.trace( [&]{
501 return fmt::format(
502 "[connection:{}] skip read operation: already running",
503 connection_id() );
504 } );
505 }
506 }
507
509 inline void
510 after_read( const asio_ns::error_code & ec, std::size_t length ) noexcept
511 {
512 if( !ec )
513 {
514 // Exceptions shouldn't go out of `after_read`.
515 // So intercept them and close the connection in the case
516 // of an exception.
517 try
518 {
519 m_logger.trace( [&]{
520 return fmt::format(
521 "[connection:{}] received {} bytes",
522 this->connection_id(),
523 length );
524 } );
525
526 m_input.m_buf.obtained_bytes( length );
527
528 consume_data( m_input.m_buf.bytes(), length );
529 }
530 catch( const std::exception & x )
531 {
532 trigger_error_and_close( [&] {
533 return fmt::format(
534 "[connection:{}] unexpected exception during the "
535 "handling of incoming data: {}",
536 connection_id(),
537 x.what() );
538 } );
539 }
540 }
541 else
542 {
543 // Well, if it is actually an error
544 // then close connection.
545 if( !error_is_operation_aborted( ec ) )
546 {
547 if ( !error_is_eof( ec ) || 0 != m_input.m_parser.nread )
548 trigger_error_and_close( [&]{
549 return fmt::format(
550 "[connection:{}] read socket error: {}; "
551 "parsed bytes: {}",
552 connection_id(),
553 ec.message(),
554 m_input.m_parser.nread );
555 } );
556 else
557 {
558 // A case that is not such an error:
559 // on a connection (most probably keeped alive
560 // after previous request, but a new also applied)
561 // no bytes were consumed and remote peer closes connection.
562 restinio::utils::log_trace_noexcept( m_logger,
563 [&]{
564 return fmt::format(
565 "[connection:{}] EOF and no request, "
566 "close connection",
567 connection_id() );
568 } );
569
570 RESTINIO_ENSURE_NOEXCEPT_CALL( close() );
571 }
572 }
573 // else: read operation was cancelled.
574 }
575 }
576
578 void
579 consume_data( const char * data, std::size_t length )
580 {
581 auto & parser = m_input.m_parser;
582
583 const auto nparsed =
584 http_parser_execute(
585 &parser,
586 &( m_settings->m_parser_settings ),
587 data,
588 length );
589
590 // If entire http-message was obtained,
591 // parser is stopped and the might be a part of consecutive request
592 // left in buffer, so we mark how many bytes were obtained.
593 // and next message read (if any) will be started from already existing
594 // data left in buffer.
595 m_input.m_buf.consumed_bytes( nparsed );
596
597 if( HPE_OK != parser.http_errno &&
598 HPE_PAUSED != parser.http_errno )
599 {
600 // PARSE ERROR:
601 auto err = HTTP_PARSER_ERRNO( &parser );
602
603 // TODO: handle case when there are some request in process.
604 trigger_error_and_close( [&]{
605 return fmt::format(
606 "[connection:{}] parser error {}: {}",
607 connection_id(),
608 http_errno_name( err ),
609 http_errno_description( err ) );
610 } );
611
612 // nothing to do.
613 return;
614 }
615
616 if( m_input.m_parser_ctx.m_message_complete )
617 {
618 on_request_message_complete();
619 }
620 else
621 consume_message();
622 }
623
625 void
626 on_request_message_complete()
627 {
628 try
629 {
630 auto & parser = m_input.m_parser;
631 auto & parser_ctx = m_input.m_parser_ctx;
632
633 if( m_input.m_parser.upgrade )
634 {
635 // Start upgrade connection operation.
636
637 // The first thing is to make sure
638 // that upgrade request will be handled in
639 // a non pipelined fashion.
640 m_input.m_connection_upgrade_stage =
641 connection_upgrade_stage_t::pending_upgrade_handling;
642 }
643
644 if( connection_upgrade_stage_t::none ==
645 m_input.m_connection_upgrade_stage )
646 {
647 // Run ordinary HTTP logic.
648 const auto request_id = m_response_coordinator.register_new_request();
649
650 m_logger.trace( [&]{
651 return fmt::format(
652 "[connection:{}] request received (#{}): {} {}",
653 connection_id(),
654 request_id,
655 http_method_str(
656 static_cast<http_method>( parser.method ) ),
657 parser_ctx.m_header.request_target() );
658 } );
659
660 // TODO: mb there is a way to
661 // track if response was emmited immediately in handler
662 // or it was delegated
663 // so it is possible to omit this timer scheduling.
664 guard_request_handling_operation();
665
666 const auto handling_result =
667 m_request_handler(
668 std::make_shared< generic_request_t >(
669 request_id,
670 std::move( parser_ctx.m_header ),
671 std::move( parser_ctx.m_body ),
672 parser_ctx.make_chunked_input_info_if_necessary(),
673 shared_from_concrete< connection_base_t >(),
674 m_remote_endpoint,
675 m_settings->extra_data_factory() ) );
676
677 switch( handling_result )
678 {
679 case request_handling_status_t::not_handled:
680 case request_handling_status_t::rejected:
681 // If handler refused request, say not implemented.
682 write_response_parts_impl(
683 request_id,
684 response_output_flags_t{
685 response_parts_attr_t::final_parts,
686 response_connection_attr_t::connection_close },
687 write_group_t{ create_not_implemented_resp() } );
688 break;
689
690 case request_handling_status_t::accepted:
691 if( m_response_coordinator.is_able_to_get_more_messages() )
692 {
693 // Request was accepted,
694 // didn't create immediate response that closes connection after,
695 // and it is possible to receive more requests
696 // then start consuming yet another request.
697 wait_for_http_message();
698 }
699 break;
700 }
701 }
702 else
703 {
704 m_logger.trace( [&]{
705 const std::string default_value{};
706
707 return fmt::format(
708 "[connection:{}] upgrade request received: {} {}; "
709 "Upgrade: '{}';",
710 connection_id(),
711 http_method_str(
712 static_cast<http_method>( parser.method ) ),
713 parser_ctx.m_header.request_target(),
714 parser_ctx.m_header.get_field_or(
715 http_field::upgrade, default_value ) );
716 } );
717
718 if( m_response_coordinator.empty() )
719 {
720 // There are no requests in handling
721 // So the current request with upgrade
722 // is the only one and can be handled directly.
723 // It is safe to call a handler for it.
724 handle_upgrade_request();
725 }
726 else
727 {
728 // There are pipelined request
729 m_logger.trace( [&]{
730 return fmt::format(
731 "[connection:{}] upgrade request happened to be a pipelined one, "
732 "and will be handled after previous requests are handled",
733 connection_id() );
734 } );
735 }
736
737 // No further actions (like continue reading) in both cases are needed.
738 }
739
740 }
741 catch( const std::exception & ex )
742 {
743 trigger_error_and_close( [&]{
744 return fmt::format(
745 "[connection:{}] error while handling request: {}",
746 this->connection_id(),
747 ex.what() );
748 } );
749 }
750 }
751
753
756 void
757 handle_upgrade_request()
758 {
759 auto & parser = m_input.m_parser;
760 auto & parser_ctx = m_input.m_parser_ctx;
761
762 // If user responses with error
763 // then connection must be able to send
764 // (hence to receive) response.
765
766 const auto request_id = m_response_coordinator.register_new_request();
767
768 m_logger.info( [&]{
769 return fmt::format(
770 "[connection:{}] handle upgrade request (#{}): {} {}",
771 connection_id(),
772 request_id,
773 http_method_str(
774 static_cast<http_method>( parser.method ) ),
775 parser_ctx.m_header.request_target() );
776 } );
777
778 // Do not guard upgrade request.
779 cancel_timeout_checking();
780
781 // After calling handler we expect the results or
782 // no further operations with connection
783 m_input.m_connection_upgrade_stage =
784 connection_upgrade_stage_t::wait_for_upgrade_handling_result_or_nothing;
785
786 const auto handling_result = m_request_handler(
787 std::make_shared< generic_request_t >(
788 request_id,
789 std::move( parser_ctx.m_header ),
790 std::move( parser_ctx.m_body ),
791 parser_ctx.make_chunked_input_info_if_necessary(),
792 shared_from_concrete< connection_base_t >(),
793 m_remote_endpoint,
794 m_settings->extra_data_factory() ) );
795 switch( handling_result )
796 {
797 case request_handling_status_t::not_handled:
798 case request_handling_status_t::rejected:
799 if( m_socket.is_open() )
800 {
801 // Request is rejected, so our socket
802 // must not be moved out to websocket connection.
803
804 // If handler refused request, say not implemented.
805 write_response_parts_impl(
806 request_id,
807 response_output_flags_t{
808 response_parts_attr_t::final_parts,
809 response_connection_attr_t::connection_close },
810 write_group_t{ create_not_implemented_resp() } );
811 }
812 else
813 {
814 // Request is rejected, but the socket
815 // was moved out to somewhere else???
816
817 m_logger.error( [&]{
818 return fmt::format(
819 "[connection:{}] upgrade request handler rejects "
820 "request, but socket was moved out from connection",
821 connection_id() );
822 } );
823 }
824 break;
825
826 case request_handling_status_t::accepted:
827 /* nothing to do */
828 break;
829 }
830
831 // Else 2 cases:
832 // 1. request is handled asynchronously, so
833 // what happens next depends on handling.
834 // 2. handling was immediate, so further destiny
835 // of a connection was already determined.
836 //
837 // In both cases: here do nothing.
838 // We can't even do read-only access because
839 // upgrade handling might take place
840 // in distinct execution context.
841 // So no even a log messages here.
842 }
843
845 virtual void
846 write_response_parts(
848 request_id_t request_id,
850 response_output_flags_t response_output_flags,
852 write_group_t wg ) override
853 {
855 asio_ns::dispatch(
856 this->get_executor(),
857 [ this,
858 request_id,
859 response_output_flags,
860 actual_wg = std::move( wg ),
861 ctx = shared_from_this() ]
862 // NOTE that this lambda is noexcept since v.0.6.0.
863 () mutable noexcept
864 {
865 try
866 {
867 write_response_parts_impl(
868 request_id,
869 response_output_flags,
870 std::move( actual_wg ) );
871 }
872 catch( const std::exception & ex )
873 {
874 trigger_error_and_close( [&]{
875 return fmt::format(
876 "[connection:{}] unable to handle response: {}",
877 connection_id(),
878 ex.what() );
879 } );
880 }
881 } );
882 }
883
885 void
886 write_response_parts_impl(
888 request_id_t request_id,
890 response_output_flags_t response_output_flags,
892 write_group_t wg )
893 {
894 auto invoke_after_write_cb_with_error = [&]{
895 try
896 {
897 wg.invoke_after_write_notificator_if_exists(
898 make_asio_compaible_error(
899 asio_convertible_error_t::write_was_not_executed ) );
900 }
901 catch( const std::exception & ex )
902 {
903 m_logger.error( [&]{
904 return fmt::format(
905 "[connection:{}] notificator error: {}",
906 connection_id(),
907 ex.what() );
908 } );
909 }
910 };
911
912 if( m_socket.is_open() )
913 {
914 if( connection_upgrade_stage_t::
915 wait_for_upgrade_handling_result_or_nothing ==
916 m_input.m_connection_upgrade_stage )
917 {
918 // It is response for a connection-upgrade request.
919 // If we receive it here then it is constructed via
920 // message builder and so connection was not transformed
921 // to websocket connection.
922 // So it is necessary to resume pipeline logic that was stopped
923 // for upgrade-request to be handled as the only request
924 // on the connection for that moment.
925 if( !m_response_coordinator.is_full() )
926 {
927 wait_for_http_message();
928 }
929 }
930
931 if( !m_response_coordinator.closed() )
932 {
933 m_logger.trace( [&]{
934 return fmt::format(
935 "[connection:{}] append response (#{}), "
936 "flags: {}, write group size: {}",
937 connection_id(),
938 request_id,
939 response_output_flags,
940 wg.items_count() );
941 } );
942
943 m_response_coordinator.append_response(
944 request_id,
945 response_output_flags,
946 std::move( wg ) );
947
948 init_write_if_necessary();
949 }
950 else
951 {
952 m_logger.warn( [&]{
953 return fmt::format(
954 "[connection:{}] receive response parts for "
955 "request (#{}), but response with connection-close "
956 "attribute happened before",
957 connection_id(),
958 request_id );
959 } );
960 invoke_after_write_cb_with_error();
961 }
962 }
963 else
964 {
965 m_logger.warn( [&]{
966 return fmt::format(
967 "[connection:{}] try to write response, "
968 "while socket is closed",
969 connection_id() );
970 } );
971 invoke_after_write_cb_with_error();
972 }
973 }
974
975 // Check if there is something to write,
976 // and if so starts write operation.
977 void
978 init_write_if_necessary()
979 {
980 assert( !m_response_coordinator.closed() );
981
982 if( !m_write_output_ctx.transmitting() )
983 {
984 init_write();
985 }
986 }
987
989 void
990 init_write()
991 {
992 // Here: not writing anything to socket, so
993 // write operation can be initiated.
994
995 // Remember if all response cells were busy.
996 const bool response_coordinator_full_before =
997 m_response_coordinator.is_full();
998
999 auto next_write_group = m_response_coordinator.pop_ready_buffers();
1000
1001 if( next_write_group )
1002 {
1003 m_logger.trace( [&]{
1004 return fmt::format(
1005 "[connection:{}] start next write group for response (#{}), "
1006 "size: {}",
1007 this->connection_id(),
1008 next_write_group->second,
1009 next_write_group->first.items_count() );
1010 } );
1011
1012 // Check if all response cells busy:
1013 const bool response_coordinator_full_after =
1014 m_response_coordinator.is_full();
1015
1016 // Whether we need to resume read after this group is written?
1017 m_init_read_after_this_write =
1018 response_coordinator_full_before &&
1019 !response_coordinator_full_after;
1020
1021 if( 0 < next_write_group->first.status_line_size() )
1022 {
1023 // We need to extract status line out of the first buffer
1024 assert(
1025 writable_item_type_t::trivial_write_operation ==
1026 next_write_group->first.items().front().write_type() );
1027
1028 m_logger.trace( [&]{
1029 // Get status line:
1030 const string_view_t
1031 status_line{
1032 asio_ns::buffer_cast< const char * >(
1033 next_write_group->first.items().front().buf() ),
1034 next_write_group->first.status_line_size() };
1035
1036 return
1037 fmt::format(
1038 "[connection:{}] start response (#{}): {}",
1039 this->connection_id(),
1040 next_write_group->second,
1041 status_line );
1042 } );
1043 }
1044
1045 // Initialize write context with a new write group.
1046 m_write_output_ctx.start_next_write_group(
1047 std::move( next_write_group->first ) );
1048
1049 // Start the loop of sending data from current write group.
1050 handle_current_write_ctx();
1051 }
1052 else
1053 {
1054 handle_nothing_to_write();
1055 }
1056 }
1057
1058 // Use aliases for shorter names.
1059 using none_write_operation_t = write_group_output_ctx_t::none_write_operation_t;
1060 using trivial_write_operation_t = write_group_output_ctx_t::trivial_write_operation_t;
1061 using file_write_operation_t = write_group_output_ctx_t::file_write_operation_t;
1062
1064
1075 void
1076 handle_current_write_ctx() noexcept
1077 {
1078 try
1079 {
1080 auto wo = m_write_output_ctx.extract_next_write_operation();
1081
1082 if( holds_alternative< trivial_write_operation_t >( wo ) )
1083 {
1084 handle_trivial_write_operation( get< trivial_write_operation_t >( wo ) );
1085 }
1086 else if( holds_alternative< file_write_operation_t >( wo ) )
1087 {
1088 handle_file_write_operation( get< file_write_operation_t >( wo ) );
1089 }
1090 else
1091 {
1092 assert( holds_alternative< none_write_operation_t >( wo ) );
1093 finish_handling_current_write_ctx();
1094 }
1095 }
1096 catch( const std::exception & ex )
1097 {
1098 trigger_error_and_close( [&]{
1099 return fmt::format(
1100 "[connection:{}] handle_current_write_ctx failed: {}",
1101 connection_id(),
1102 ex.what() );
1103 } );
1104 }
1105 }
1106
1108 void
1109 handle_trivial_write_operation( const trivial_write_operation_t & op )
1110 {
1111 // Asio buffers (param for async write):
1112 auto & bufs = op.get_trivial_bufs();
1113
1114 if( m_response_coordinator.closed() )
1115 {
1116 m_logger.trace( [&]{
1117 return fmt::format(
1118 "[connection:{}] sending resp data with "
1119 "connection-close attribute "
1120 "buf count: {}, "
1121 "total size: {}",
1122 connection_id(),
1123 bufs.size(),
1124 op.size() );
1125 } );
1126
1127 // Reading new requests is useless.
1128 asio_ns::error_code ignored_ec;
1129 m_socket.cancel( ignored_ec );
1130 }
1131 else
1132 {
1133 m_logger.trace( [&]{
1134 return fmt::format(
1135 "[connection:{}] sending resp data, "
1136 "buf count: {}, "
1137 "total size: {}",
1138 connection_id(),
1139 bufs.size(),
1140 op.size() ); } );
1141 }
1142
1143 // There is somethig to write.
1144 asio_ns::async_write(
1145 m_socket,
1146 bufs,
1147 asio_ns::bind_executor(
1148 this->get_executor(),
1149 [this, ctx = shared_from_this()]
1150 // NOTE: since v.0.6.0 this lambda is noexcept.
1151 ( const asio_ns::error_code & ec, std::size_t written ) noexcept
1152 {
1153 if( !ec )
1154 {
1155 restinio::utils::log_trace_noexcept( m_logger,
1156 [&]{
1157 return fmt::format(
1158 "[connection:{}] outgoing data was sent: {} bytes",
1159 connection_id(),
1160 written );
1161 } );
1162 }
1163
1164 RESTINIO_ENSURE_NOEXCEPT_CALL( after_write( ec ) );
1165 } ) );
1166
1167 guard_write_operation();
1168 }
1169
1171 void
1172 handle_file_write_operation( file_write_operation_t & op )
1173 {
1174 if( m_response_coordinator.closed() )
1175 {
1176 m_logger.trace( [&]{
1177 return fmt::format(
1178 "[connection:{}] sending resp file data with "
1179 "connection-close attribute, "
1180 "total size: {}",
1181 connection_id(),
1182 op.size() );
1183 } );
1184
1185 // Reading new requests is useless.
1186 asio_ns::error_code ignored_ec;
1187 m_socket.cancel( ignored_ec );
1188 }
1189 else
1190 {
1191 m_logger.trace( [&]{
1192 return fmt::format(
1193 "[connection:{}] sending resp file data, total size: {}",
1194 connection_id(),
1195 op.size() );
1196 } );
1197 }
1198
1199 guard_sendfile_operation( op.timelimit() );
1200
1201 auto op_ctx = op;
1202
1203 op_ctx.start_sendfile_operation(
1204 this->get_executor(),
1205 m_socket,
1206 asio_ns::bind_executor(
1207 this->get_executor(),
1208 [this, ctx = shared_from_this(),
1209 // Store operation context till the end
1210 op_ctx ]
1211 // NOTE: since v.0.6.0 this lambda is noexcept
1212 (const asio_ns::error_code & ec, file_size_t written ) mutable noexcept
1213 {
1214 // NOTE: op_ctx should be reset just before return from
1215 // that lambda. We can't call reset() until the end of
1216 // the lambda because lambda object itself will be
1217 // destroyed.
1218 auto op_ctx_reseter = restinio::utils::at_scope_exit(
1219 [&op_ctx] {
1220 // Reset sendfile operation context.
1221 RESTINIO_ENSURE_NOEXCEPT_CALL( op_ctx.reset() );
1222 } );
1223
1224 if( !ec )
1225 {
1226 restinio::utils::log_trace_noexcept( m_logger,
1227 [&]{
1228 return fmt::format(
1229 "[connection:{}] file data was sent: {} bytes",
1230 connection_id(),
1231 written );
1232 } );
1233 }
1234 else
1235 {
1236 restinio::utils::log_error_noexcept( m_logger,
1237 [&]{
1238 return fmt::format(
1239 "[connection:{}] send file data error: {} ({}) bytes",
1240 connection_id(),
1241 ec.value(),
1242 ec.message() );
1243 } );
1244 }
1245
1246 RESTINIO_ENSURE_NOEXCEPT_CALL( after_write( ec ) );
1247 } ) );
1248 }
1249
1251 void
1252 finish_handling_current_write_ctx()
1253 {
1254 // Finishing writing this group.
1255 m_logger.trace( [&]{
1256 return fmt::format(
1257 "[connection:{}] finishing current write group",
1258 this->connection_id() );
1259 } );
1260
1261 // Group notificators are called from here (if exist):
1262 m_write_output_ctx.finish_write_group();
1263
1264 if( !m_response_coordinator.closed() )
1265 {
1266 m_logger.trace( [&]{
1267 return fmt::format(
1268 "[connection:{}] should keep alive",
1269 this->connection_id() );
1270 } );
1271
1272 if( connection_upgrade_stage_t::none ==
1273 m_input.m_connection_upgrade_stage )
1274 {
1275 // Run ordinary HTTP logic.
1276 if( m_init_read_after_this_write )
1277 {
1278 wait_for_http_message();
1279 }
1280
1281 // Start another write opertion
1282 // if there is something to send.
1283 init_write_if_necessary();
1284 }
1285 else
1286 {
1287 if( m_response_coordinator.empty() )
1288 {
1289 // Here upgrade req is the only request
1290 // to by handled by this connection.
1291 // So it is safe to call a handler for it.
1292 handle_upgrade_request();
1293 }
1294 else
1295 {
1296 // Do not start reading in any case,
1297 // but if there is at least one request preceding
1298 // upgrade-req, logic must continue http interaction.
1299 init_write_if_necessary();
1300 }
1301 }
1302 }
1303 else
1304 {
1305 // No keep-alive, close connection.
1306 close();
1307 }
1308 }
1309
1310 void
1311 handle_nothing_to_write()
1312 {
1313 if( m_response_coordinator.closed() )
1314 {
1315 // Bufs empty but there happened to
1316 // be a response context marked as complete
1317 // (final_parts) and having connection-close attr.
1318 // It is because `init_write_if_necessary()`
1319 // is called only under `!m_response_coordinator.closed()`
1320 // condition, so if no bufs were obtained
1321 // and response coordinator is closed means
1322 // that a first response stored by
1323 // response coordinator was marked as complete
1324 // without data.
1325
1326 m_logger.trace( [&]{
1327 return fmt::format(
1328 "[connection:{}] last sent response was marked "
1329 "as complete",
1330 connection_id() ); } );
1331 close();
1332 }
1333 else
1334 {
1335 // Not writing anything, so need to deal with timouts.
1336 if( m_response_coordinator.empty() )
1337 {
1338 // No requests in processing.
1339 // So set read next request timeout.
1340 guard_read_operation();
1341 }
1342 else
1343 {
1344 // Have requests in process.
1345 // So take control over request handling.
1346 guard_request_handling_operation();
1347 }
1348 }
1349 }
1350
1352
1356 void
1357 after_write( const asio_ns::error_code & ec ) noexcept
1358 {
1359 if( !ec )
1360 {
1361 RESTINIO_ENSURE_NOEXCEPT_CALL( handle_current_write_ctx() );
1362 }
1363 else
1364 {
1365 if( !error_is_operation_aborted( ec ) )
1366 {
1367 trigger_error_and_close( [&]{
1368 return fmt::format(
1369 "[connection:{}] unable to write: {}",
1370 connection_id(),
1371 ec.message() );
1372 } );
1373 }
1374 // else: Operation aborted only in case of close was called.
1375
1376 try
1377 {
1378 m_write_output_ctx.fail_write_group( ec );
1379 }
1380 catch( const std::exception & ex )
1381 {
1382 restinio::utils::log_error_noexcept( m_logger,
1383 [&]{
1384 return fmt::format(
1385 "[connection:{}] notificator error: {}",
1386 connection_id(),
1387 ex.what() );
1388 } );
1389 }
1390 }
1391 }
1392
1395
1397 void
1398 close() noexcept
1399 {
1400 restinio::utils::log_trace_noexcept( m_logger,
1401 [&]{
1402 return fmt::format(
1403 "[connection:{}] close",
1404 connection_id() );
1405 } );
1406
1407 // shutdown() and close() should be called regardless of
1408 // possible exceptions.
1409 restinio::utils::suppress_exceptions(
1410 m_logger,
1411 "connection.socket.shutdown",
1412 [this] {
1413 asio_ns::error_code ignored_ec;
1414 m_socket.shutdown(
1415 asio_ns::ip::tcp::socket::shutdown_both,
1416 ignored_ec );
1417 } );
1418 restinio::utils::suppress_exceptions(
1419 m_logger,
1420 "connection.socket.close",
1421 [this] {
1422 m_socket.close();
1423 } );
1424
1425 restinio::utils::log_trace_noexcept( m_logger,
1426 [&]{
1427 return fmt::format(
1428 "[connection:{}] close: close socket",
1429 connection_id() );
1430 } );
1431
1432 // Clear stuff.
1433 RESTINIO_ENSURE_NOEXCEPT_CALL( cancel_timeout_checking() );
1434
1435 restinio::utils::log_trace_noexcept( m_logger,
1436 [&]{
1437 return fmt::format(
1438 "[connection:{}] close: timer canceled",
1439 connection_id() );
1440 } );
1441
1442 RESTINIO_ENSURE_NOEXCEPT_CALL( m_response_coordinator.reset() );
1443
1444 restinio::utils::log_trace_noexcept( m_logger,
1445 [&]{
1446 return fmt::format(
1447 "[connection:{}] close: reset responses data",
1448 connection_id() );
1449 } );
1450
1451 // Inform state listener if it used.
1452 m_settings->call_state_listener_suppressing_exceptions(
1453 [this]() noexcept {
1454 return connection_state::notice_t{
1455 this->connection_id(),
1456 this->m_remote_endpoint,
1457 connection_state::closed_t{}
1458 };
1459 } );
1460 }
1461
1463
1467 template< typename Message_Builder >
1468 void
1469 trigger_error_and_close( Message_Builder msg_builder ) noexcept
1470 {
1471 // An exception from logger/msg_builder shouldn't prevent
1472 // a call to close().
1473 restinio::utils::log_error_noexcept(
1474 m_logger, std::move(msg_builder) );
1475
1476 RESTINIO_ENSURE_NOEXCEPT_CALL( close() );
1477 }
1479
1481 stream_socket_t m_socket;
1482
1484 connection_settings_handle_t< Traits > m_settings;
1485
1487 const endpoint_t m_remote_endpoint;
1488
1490 connection_input_t m_input;
1491
1493 write_group_output_ctx_t m_write_output_ctx;
1494
1495 // Memo flag: whether we need to resume read after this group is written
1496 bool m_init_read_after_this_write{ false };
1497
1499 response_coordinator_t m_response_coordinator;
1500
1503
1505 static connection_t &
1506 cast_to_self( tcp_connection_ctx_base_t & base )
1507 {
1508 return static_cast< connection_t & >( base );
1509 }
1510
1513 virtual void
1514 check_timeout( tcp_connection_ctx_handle_t & self ) override
1515 {
1516 asio_ns::dispatch(
1517 this->get_executor(),
1518 [ ctx = std::move( self ) ]
1519 // NOTE: this lambda is noexcept since v.0.6.0.
1520 () noexcept {
1521 auto & conn_object = cast_to_self( *ctx );
1522 // If an exception will be thrown we can only
1523 // close the connection.
1524 try
1525 {
1526 conn_object.check_timeout_impl();
1527 }
1528 catch( const std::exception & x )
1529 {
1530 conn_object.trigger_error_and_close( [&] {
1531 return fmt::format( "[connection: {}] unexpected "
1532 "error during timeout handling: {}",
1533 conn_object.connection_id(),
1534 x.what() );
1535 } );
1536 }
1537 } );
1538 }
1539
1541 using timout_cb_t = void (connection_t::* )( void );
1542
1544 timout_cb_t m_current_timeout_cb{ nullptr };
1545
1547 std::chrono::steady_clock::time_point m_current_timeout_after;
1549 timer_guard_t m_timer_guard;
1551 tcp_connection_ctx_weak_handle_t m_prepared_weak_ctx;
1552
1554 void
1555 check_timeout_impl()
1556 {
1557 if( std::chrono::steady_clock::now() > m_current_timeout_after )
1558 {
1559 if( m_current_timeout_cb )
1560 (this->*m_current_timeout_cb)();
1561 }
1562 else
1563 {
1564 init_next_timeout_checking();
1565 }
1566 }
1567
1569 void
1570 init_next_timeout_checking()
1571 {
1572 m_timer_guard.schedule( m_prepared_weak_ctx );
1573 }
1574
1576 void
1577 cancel_timeout_checking() noexcept
1578 {
1579 m_current_timeout_cb = nullptr;
1580 RESTINIO_ENSURE_NOEXCEPT_CALL( m_timer_guard.cancel() );
1581 }
1582
1584 void
1585 schedule_operation_timeout_callback(
1586 std::chrono::steady_clock::time_point timeout_after,
1587 timout_cb_t timout_cb )
1588 {
1589 m_current_timeout_after = timeout_after;
1590 m_current_timeout_cb = timout_cb;
1591 }
1592
1593 void
1594 schedule_operation_timeout_callback(
1595 std::chrono::steady_clock::duration timeout,
1596 timout_cb_t timout_cb )
1597 {
1598 schedule_operation_timeout_callback(
1599 std::chrono::steady_clock::now() + timeout,
1600 timout_cb );
1601 }
1602
1603 void
1604 handle_xxx_timeout( const char * operation_name )
1605 {
1606 m_logger.trace( [&]{
1607 return fmt::format(
1608 "[connection:{}] {} timed out",
1609 connection_id(),
1610 operation_name );
1611 } );
1612
1613 close();
1614 }
1615
1616 void
1617 handle_read_timeout()
1618 {
1619 handle_xxx_timeout( "wait for request" );
1620 }
1621
1623 void
1624 guard_read_operation()
1625 {
1626 if( m_response_coordinator.empty() )
1627 {
1628 schedule_operation_timeout_callback(
1629 m_settings->m_read_next_http_message_timelimit,
1630 &connection_t::handle_read_timeout );
1631 }
1632 }
1633
1634 void
1635 handle_request_handling_timeout()
1636 {
1637 handle_xxx_timeout( "handle request" );
1638 }
1639
1641 void
1642 guard_request_handling_operation()
1643 {
1644 if( !m_write_output_ctx.transmitting() )
1645 {
1646 schedule_operation_timeout_callback(
1647 m_settings->m_handle_request_timeout,
1648 &connection_t::handle_request_handling_timeout );
1649 }
1650 }
1651
1652 void
1653 handle_write_response_timeout()
1654 {
1655 handle_xxx_timeout( "writing response" );
1656 }
1657
1659 void
1660 guard_write_operation()
1661 {
1662 schedule_operation_timeout_callback(
1663 m_settings->m_write_http_response_timelimit,
1664 &connection_t::handle_write_response_timeout );
1665 }
1666
1667 void
1668 handle_sendfile_timeout()
1669 {
1670 handle_xxx_timeout( "writing response (sendfile)" );
1671 }
1672
1673 void
1674 guard_sendfile_operation( std::chrono::steady_clock::duration timelimit )
1675 {
1676 if( std::chrono::steady_clock::duration::zero() == timelimit )
1677 timelimit = m_settings->m_write_http_response_timelimit;
1678
1679 schedule_operation_timeout_callback(
1680 timelimit,
1681 &connection_t::handle_sendfile_timeout );
1682 }
1684
1686 request_handler_t & m_request_handler;
1687
1689 logger_t & m_logger;
1690
1699 lifetime_monitor_t m_lifetime_monitor;
1700};
1701
1702//
1703// connection_factory_t
1704//
1705
1707 template < typename Traits >
1708 class connection_factory_t
1709{
1710 public:
1711 using logger_t = typename Traits::logger_t;
1712 using stream_socket_t = typename Traits::stream_socket_t;
1713 using lifetime_monitor_t =
1714 typename connection_count_limit_types<Traits>::lifetime_monitor_t;
1715
1716 connection_factory_t(
1717 connection_settings_handle_t< Traits > connection_settings,
1718 std::unique_ptr< socket_options_setter_t > socket_options_setter )
1719 : m_connection_settings{ std::move( connection_settings ) }
1720 , m_socket_options_setter{ std::move( socket_options_setter ) }
1721 , m_logger{ *(m_connection_settings->m_logger ) }
1722 {}
1723
1724 // NOTE: since v.0.6.3 it returns non-empty
1725 // shared_ptr<connection_t<Traits>> or an exception is thrown in
1726 // the case of an error.
1727 // NOTE: since v.0.6.12 it accepts yet another parameter: lifetime_monitor.
1728 auto
1729 create_new_connection(
1730 stream_socket_t socket,
1731 endpoint_t remote_endpoint,
1732 lifetime_monitor_t lifetime_monitor )
1733 {
1734 using connection_type_t = connection_t< Traits >;
1735
1736 {
1737 socket_options_t options{ socket.lowest_layer() };
1738 (*m_socket_options_setter)( options );
1739 }
1740
1741 return std::make_shared< connection_type_t >(
1742 m_connection_id_counter++,
1743 std::move( socket ),
1744 m_connection_settings,
1745 std::move( remote_endpoint ),
1746 std::move( lifetime_monitor ) );
1747 }
1748
1749 private:
1750 connection_id_t m_connection_id_counter{ 1 };
1751
1752 connection_settings_handle_t< Traits > m_connection_settings;
1753
1754 std::unique_ptr< socket_options_setter_t > m_socket_options_setter;
1755
1756 logger_t & m_logger;
1757};
1758
1759} /* namespace impl */
1760
1761} /* namespace restinio */
asio_include.hpp
at_scope_exit.hpp
A simple implementation of at_scope_exit concept.
restinio::connection_count_limits::connection_lifetime_monitor_t
Helper type for controlling the lifetime of the connection.
Definition: connection_count_limiter.hpp:375
restinio::connection_state::accepted_t
Type of object that tells that new connection has been accepted.
Definition: connection_state_listener.hpp:36
restinio::connection_state::closed_t
Type of object that tells that the connection has been closed.
Definition: connection_state_listener.hpp:183
restinio::connection_state::notice_t
An object with info about connection to be passed to state listener.
Definition: connection_state_listener.hpp:225
restinio::generic_request_t
HTTP Request data.
Definition: request_handler.hpp:201
restinio::http_header_fields_t::fields_count
auto fields_count() const noexcept
Definition: http_headers.hpp:1493
restinio::impl::connection_base_t
HTTP connection base.
Definition: connection_base.hpp:29
restinio::impl::connection_factory_t
Factory for connections.
Definition: connection.hpp:1709
restinio::impl::connection_factory_t::m_socket_options_setter
std::unique_ptr< socket_options_setter_t > m_socket_options_setter
Definition: connection.hpp:1754
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:1716
restinio::impl::connection_factory_t::logger_t
typename Traits::logger_t logger_t
Definition: connection.hpp:1711
restinio::impl::connection_factory_t::m_logger
logger_t & m_logger
Definition: connection.hpp:1756
restinio::impl::connection_factory_t::m_connection_settings
connection_settings_handle_t< Traits > m_connection_settings
Definition: connection.hpp:1752
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:1729
restinio::impl::connection_factory_t::stream_socket_t
typename Traits::stream_socket_t stream_socket_t
Definition: connection.hpp:1712
restinio::impl::connection_factory_t::m_connection_id_counter
connection_id_t m_connection_id_counter
Definition: connection.hpp:1750
restinio::impl::connection_factory_t::lifetime_monitor_t
typename connection_count_limit_types< Traits >::lifetime_monitor_t lifetime_monitor_t
Definition: connection.hpp:1714
restinio::impl::connection_t
Context for handling http connections.
Definition: connection.hpp:306
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:1514
restinio::impl::connection_t::operator=
connection_t & operator=(const connection_t &)=delete
restinio::impl::connection_t::strand_t
typename Traits::strand_t strand_t
Definition: connection.hpp:315
restinio::impl::connection_t::handle_upgrade_request
void handle_upgrade_request()
Calls handler for upgrade request.
Definition: connection.hpp:757
restinio::impl::connection_t::init_write_if_necessary
void init_write_if_necessary()
Definition: connection.hpp:978
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:1551
restinio::impl::connection_t::on_request_message_complete
void on_request_message_complete()
Handle a given request message.
Definition: connection.hpp:626
restinio::impl::connection_t::handle_request_handling_timeout
void handle_request_handling_timeout()
Definition: connection.hpp:1635
restinio::impl::connection_t::lifetime_monitor_t
typename connection_count_limit_types< Traits >::lifetime_monitor_t lifetime_monitor_t
Definition: connection.hpp:318
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:846
restinio::impl::connection_t::handle_xxx_timeout
void handle_xxx_timeout(const char *operation_name)
Definition: connection.hpp:1604
restinio::impl::connection_t::guard_write_operation
void guard_write_operation()
Start guard write operation if necessary.
Definition: connection.hpp:1660
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:1252
restinio::impl::connection_t::m_remote_endpoint
const endpoint_t m_remote_endpoint
Remote endpoint for this connection.
Definition: connection.hpp:1487
restinio::impl::connection_t::m_lifetime_monitor
lifetime_monitor_t m_lifetime_monitor
Monitor of the connection lifetime.
Definition: connection.hpp:1699
restinio::impl::connection_t::m_socket
stream_socket_t m_socket
Connection.
Definition: connection.hpp:1481
restinio::impl::connection_t::m_input
connection_input_t m_input
Input routine.
Definition: connection.hpp:1490
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:1585
restinio::impl::connection_t::guard_sendfile_operation
void guard_sendfile_operation(std::chrono::steady_clock::duration timelimit)
Definition: connection.hpp:1674
restinio::impl::connection_t::m_request_handler
request_handler_t & m_request_handler
Request handler.
Definition: connection.hpp:1686
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:1109
restinio::impl::connection_t::handle_nothing_to_write
void handle_nothing_to_write()
Definition: connection.hpp:1311
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:1172
restinio::impl::connection_t::m_current_timeout_cb
timout_cb_t m_current_timeout_cb
Callback to all if timeout happened.
Definition: connection.hpp:1544
restinio::impl::connection_t::~connection_t
~connection_t() override
Definition: connection.hpp:361
restinio::impl::connection_t::wait_for_http_message
void wait_for_http_message()
Start reading next htttp-message.
Definition: connection.hpp:409
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:510
restinio::impl::connection_t::m_logger
logger_t & m_logger
Logger for operation.
Definition: connection.hpp:1689
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:1547
restinio::impl::connection_t::init_write
void init_write()
Initiate write operation.
Definition: connection.hpp:990
restinio::impl::connection_t::timer_manager_t
typename Traits::timer_manager_t timer_manager_t
Definition: connection.hpp:310
restinio::impl::connection_t::move_upgrade_internals
upgrade_internals_t move_upgrade_internals()
Move socket out of connection.
Definition: connection.hpp:462
restinio::impl::connection_t::cancel_timeout_checking
void cancel_timeout_checking() noexcept
Stop timout guarding.
Definition: connection.hpp:1577
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:1506
restinio::impl::connection_t::connection_t
connection_t(const connection_t &)=delete
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:1076
restinio::impl::connection_t::timout_cb_t
void(connection_t::*)(void) timout_cb_t
Callback type for timedout operations.
Definition: connection.hpp:1541
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:320
restinio::impl::connection_t::close
void close() noexcept
Close connection functions.
Definition: connection.hpp:1398
restinio::impl::connection_t::handle_write_response_timeout
void handle_write_response_timeout()
Definition: connection.hpp:1653
restinio::impl::connection_t::logger_t
typename Traits::logger_t logger_t
Definition: connection.hpp:314
restinio::impl::connection_t::after_write
void after_write(const asio_ns::error_code &ec) noexcept
Handle write response finished.
Definition: connection.hpp:1357
restinio::impl::connection_t::trigger_error_and_close
void trigger_error_and_close(Message_Builder msg_builder) noexcept
Trigger an error.
Definition: connection.hpp:1469
restinio::impl::connection_t::m_response_coordinator
response_coordinator_t m_response_coordinator
Response coordinator.
Definition: connection.hpp:1499
restinio::impl::connection_t::guard_request_handling_operation
void guard_request_handling_operation()
Start guard request handling operation if necessary.
Definition: connection.hpp:1642
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::request_handler_t
request_handler_type_from_traits_t< Traits > request_handler_t
Definition: connection.hpp:312
restinio::impl::connection_t::init_next_timeout_checking
void init_next_timeout_checking()
Schedule next timeout checking.
Definition: connection.hpp:1570
restinio::impl::connection_t::consume_data
void consume_data(const char *data, std::size_t length)
Parse some data.
Definition: connection.hpp:579
restinio::impl::connection_t::consume_message
void consume_message()
Start (continue) a chain of read-parse-read-... operations.
Definition: connection.hpp:474
restinio::impl::connection_t::m_timer_guard
timer_guard_t m_timer_guard
Timer guard.
Definition: connection.hpp:1549
restinio::impl::connection_t::init
void init()
Definition: connection.hpp:372
restinio::impl::connection_t::stream_socket_t
typename Traits::stream_socket_t stream_socket_t
Definition: connection.hpp:316
restinio::impl::connection_t::check_timeout_impl
void check_timeout_impl()
Check timed out operation.
Definition: connection.hpp:1555
restinio::impl::connection_t::m_settings
connection_settings_handle_t< Traits > m_settings
Common paramaters of a connection.
Definition: connection.hpp:1484
restinio::impl::connection_t::handle_sendfile_timeout
void handle_sendfile_timeout()
Definition: connection.hpp:1668
restinio::impl::connection_t::guard_read_operation
void guard_read_operation()
Statr guard read operation if necessary.
Definition: connection.hpp:1624
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:886
restinio::impl::connection_t::connection_t
connection_t(connection_t &&)=delete
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:1594
restinio::impl::connection_t::m_init_read_after_this_write
bool m_init_read_after_this_write
Definition: connection.hpp:1496
restinio::impl::connection_t::handle_read_timeout
void handle_read_timeout()
Definition: connection.hpp:1617
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:1493
restinio::impl::executor_wrapper_t
Wrapper for an executor (strand) used by connections.
Definition: executor_wrapper.hpp:25
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::fixed_buffer_t
Helper class for reading bytes and feeding them to parser.
Definition: fixed_buffer.hpp:27
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::consumed_bytes
void consumed_bytes(std::size_t length) noexcept
Mark how many bytes were obtained.
Definition: fixed_buffer.hpp:56
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::fixed_buffer_t::make_asio_buffer
auto make_asio_buffer() noexcept
Make asio buffer for reading bytes from socket.
Definition: fixed_buffer.hpp:41
restinio::impl::fixed_buffer_t::bytes
const char * bytes() const noexcept
Get pointer to unconsumed bytes.
Definition: fixed_buffer.hpp:69
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::impl::response_coordinator_t::reset
void reset() noexcept
Remove all contexts.
Definition: response_coordinator.hpp:416
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::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::impl::response_coordinator_t::is_full
bool is_full() const noexcept
Definition: response_coordinator.hpp:303
restinio::impl::response_coordinator_t::empty
bool empty() const noexcept
Definition: response_coordinator.hpp:302
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::response_coordinator_t::closed
bool closed() const noexcept
Definition: response_coordinator.hpp:301
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::tls_socket_t
Socket adapter for asio::ssl::stream< asio::ip::tcp::socket >.
Definition: tls_socket.hpp:37
restinio::impl::write_group_output_ctx_t::file_write_operation_t
Write operaton using sendfile.
Definition: write_group_output_ctx.hpp:142
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::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::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::impl::write_group_output_ctx_t::trivial_write_operation_t
Trivial write operaton.
Definition: write_group_output_ctx.hpp:106
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::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
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::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::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::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::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::write_group_output_ctx_t::transmitting
bool transmitting() const noexcept
Check if data is trunsmitting now.
Definition: write_group_output_ctx.hpp:235
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::socket_options_t
An adapter for setting acceptor options before running server.
Definition: settings.hpp:249
restinio::tcp_connection_ctx_base_t
TCP connection base.
Definition: tcp_connection_ctx_base.hpp:29
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::write_group_t
Group of writable items transported to the context of underlying connection as one solid piece.
Definition: buffers.hpp:692
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::write_group_t::items_count
auto items_count() const noexcept
Get the count of stored items.
Definition: buffers.hpp:832
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_NODISCARD
#define RESTINIO_NODISCARD
Definition: compiler_features.hpp:33
connection_base.hpp
connection_count_limiter.hpp
Stuff related to limits of active parallel connections.
connection_settings.hpp
exception.hpp
executor_wrapper.hpp
fixed_buffer.hpp
header_helpers.hpp
http_headers.hpp
include_fmtlib.hpp
A special wrapper around fmtlib include files.
nonstd::optional_lite::std11::move
T & move(T &t)
Definition: optional.hpp:465
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::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::connection_settings_handle_t
std::shared_ptr< connection_settings_t< Traits > > connection_settings_handle_t
Definition: connection_settings.hpp:235
restinio::impl::create_parser_settings
http_parser_settings create_parser_settings() noexcept
Include parser callbacks.
Definition: connection.hpp:152
restinio::impl::create_not_implemented_resp
auto create_not_implemented_resp()
Definition: header_helpers.hpp:156
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_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_upgrade_stage_t::wait_for_upgrade_handling_result_or_nothing
@ wait_for_upgrade_handling_result_or_nothing
Handler for request with connection-upgrade header was called so any response data comming is for tha...
restinio::impl::connection_upgrade_stage_t::none
@ none
No connection request in progress.
restinio::impl::connection_upgrade_stage_t::pending_upgrade_handling
@ pending_upgrade_handling
Request with connection-upgrade header came and waits for request handler to be called in non pipelin...
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
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
restinio::utils::log_error_noexcept
void log_error_noexcept(Logger &&logger, Message_Builder &&builder) noexcept
Definition: suppress_exceptions.hpp:71
restinio::utils::log_trace_noexcept
void log_trace_noexcept(Logger &&logger, Message_Builder &&builder) noexcept
Definition: suppress_exceptions.hpp:32
restinio::websocket::basic::upgrade
ws_handle_t upgrade(generic_request_type_from_traits_t< Traits > &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
Definition: asio_include.hpp:21
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::file_size_t
std::uint64_t file_size_t
Definition: sendfile_defs_default.hpp:23
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::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::string_view_t
nonstd::string_view string_view_t
Definition: string_view.hpp:19
restinio::request_id_t
unsigned int request_id_t
Request id in scope of single connection.
Definition: common_types.hpp:70
restinio::writable_item_type_t::trivial_write_operation
@ trivial_write_operation
Item is a buffer and must be written trivially.
restinio::error_is_operation_aborted
bool error_is_operation_aborted(const asio_ns::error_code &ec) noexcept
Definition: asio_include.hpp:27
restinio::request_handling_status_t::accepted
@ accepted
Request accepted for handling.
restinio::request_handling_status_t::not_handled
@ not_handled
The request wasn't handled. If there is another handler to be tried it should be tried....
restinio::request_handling_status_t::rejected
@ rejected
Request wasn't accepted for handling.
restinio::request_handler_type_from_traits_t
typename details::actual_request_handler_type_detector< typename Traits::request_handler_t, typename Traits::extra_data_factory_t >::request_handler_t request_handler_type_from_traits_t
A metafunction for extraction a request-handler type from server's traits.
Definition: traits.hpp:379
restinio::asio_convertible_error_t::write_was_not_executed
@ write_was_not_executed
After write notificator error: data was not sent, connection closed (or aborted) before a given piece...
restinio::error_is_eof
bool error_is_eof(const asio_ns::error_code &ec) noexcept
Definition: asio_include.hpp:33
restinio::endpoint_t
asio_ns::ip::tcp::endpoint endpoint_t
An alias for endpoint type from Asio.
Definition: common_types.hpp:177
restinio::response_connection_attr_t::connection_close
@ connection_close
This response says to close connection.
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::response_parts_attr_t::final_parts
@ final_parts
Final parts (response ands with these parts).
restinio::connection_id_t
std::uint64_t connection_id_t
Type for ID of connection.
Definition: common_types.hpp:174
std
STL namespace.
parser_callbacks.ipp
restinio_url_cb
int restinio_url_cb(http_parser *parser, const char *at, size_t length)
Definition: parser_callbacks.ipp:10
restinio_header_value_cb
int restinio_header_value_cb(http_parser *parser, const char *at, size_t length)
Definition: parser_callbacks.ipp:80
restinio_body_cb
int restinio_body_cb(http_parser *parser, const char *at, size_t length)
Definition: parser_callbacks.ipp:159
restinio_chunk_complete_cb
int restinio_chunk_complete_cb(http_parser *)
Definition: parser_callbacks.ipp:218
restinio_headers_complete_cb
int restinio_headers_complete_cb(http_parser *parser)
Definition: parser_callbacks.ipp:124
restinio_header_field_cb
int restinio_header_field_cb(http_parser *parser, const char *at, size_t length)
Definition: parser_callbacks.ipp:35
restinio_chunk_header_cb
int restinio_chunk_header_cb(http_parser *parser)
Definition: parser_callbacks.ipp:186
request_handler.hpp
response_coordinator.hpp
safe_uint_truncate.hpp
Helpers for safe truncation of unsigned integers.
sendfile_operation.hpp
restinio::http_request_header_t
Req header.
Definition: http_headers.hpp:1859
restinio::impl::chunked_input_info_block_t
Bunch of data related to chunked input.
Definition: chunked_input_info.hpp:116
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::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::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::impl::connection_input_t::m_parser_ctx
http_parser_ctx_t m_parser_ctx
Definition: connection.hpp:237
restinio::impl::connection_input_t::m_buf
fixed_buffer_t m_buf
Input buffer.
Definition: connection.hpp:241
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::impl::connection_input_t::reset_parser
void reset_parser()
Prepare parser for reading new http-message.
Definition: connection.hpp:252
restinio::impl::connection_input_t::m_parser
http_parser m_parser
HTTP-parser.
Definition: connection.hpp:236
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::connection_t::upgrade_internals_t
Internals that are necessary for upgrade.
Definition: connection.hpp:442
restinio::impl::connection_t::upgrade_internals_t::m_socket
stream_socket_t m_socket
Definition: connection.hpp:456
restinio::impl::connection_t::upgrade_internals_t::m_lifetime_monitor
lifetime_monitor_t m_lifetime_monitor
Definition: connection.hpp:457
restinio::impl::connection_t::upgrade_internals_t::m_settings
connection_settings_handle_t< Traits > m_settings
Definition: connection.hpp:455
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:446
restinio::impl::connection_t::upgrade_internals_t::upgrade_internals_t
upgrade_internals_t(upgrade_internals_t &&)=default
restinio::impl::http_parser_ctx_t
Parsing result context for using in parser callbacks.
Definition: connection.hpp:49
restinio::impl::http_parser_ctx_t::reset
void reset()
Prepare context to handle new request.
Definition: connection.hpp:105
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::impl::http_parser_ctx_t::m_leading_headers_completed
bool m_leading_headers_completed
Definition: connection.hpp:65
restinio::impl::http_parser_ctx_t::m_header
http_request_header_t m_header
Request data.
Definition: connection.hpp:52
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::http_parser_ctx_t::m_body
std::string m_body
Definition: connection.hpp:53
restinio::impl::http_parser_ctx_t::m_last_was_value
bool m_last_was_value
Definition: connection.hpp:60
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::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::http_parser_ctx_t::m_chunked_info_block
chunked_input_info_block_t m_chunked_info_block
Definition: connection.hpp:70
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::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::http_parser_ctx_t::m_last_value_total_size
std::size_t m_last_value_total_size
Definition: connection.hpp:59
restinio::impl::write_group_output_ctx_t::none_write_operation_t
None write operation.
Definition: write_group_output_ctx.hpp:232
restinio::response_output_flags_t
Response output flags for buffers commited to response-coordinator.
Definition: common_types.hpp:123
write_group_output_ctx.hpp