45 using AutoUnlinkOption = boost::intrusive::link_mode<boost::intrusive::auto_unlink>;
47 static constexpr auto IdleTimeout = 5
s;
60 , sock_{std::move(
sock)}
65 schedule_timeout(now);
66 app.on_http_connect(now, ep_);
79 boost::intrusive::list_member_hook<AutoUnlinkOption>
list_hook;
84 app_.on_http_disconnect(now, ep_);
96 bool on_http_message_begin(
CyclTime )
noexcept
102 bool on_http_url(
CyclTime now, std::string_view
sv)
noexcept
108 }
catch (
const std::exception& e) {
109 app_.on_http_error(now, ep_, e, os_);
114 bool on_http_status(CyclTime , std::string_view )
noexcept
119 bool on_http_header_field(CyclTime now, std::string_view
sv,
First first)
noexcept
123 req_.append_header_field(
sv, first);
125 }
catch (
const std::exception& e) {
126 app_.on_http_error(now, ep_, e, os_);
131 bool on_http_header_value(CyclTime now, std::string_view
sv,
First first)
noexcept
135 req_.append_header_value(
sv, first);
137 }
catch (
const std::exception& e) {
138 app_.on_http_error(now, ep_, e, os_);
143 bool on_http_headers_end(CyclTime )
noexcept
145 req_.set_method(
method());
148 bool on_http_body(CyclTime now, std::string_view
sv)
noexcept
152 req_.append_body(
sv);
154 }
catch (
const std::exception& e) {
155 app_.on_http_error(now, ep_, e, os_);
160 bool on_http_message_end(CyclTime now)
noexcept
164 in_progress_ =
false;
166 app_.on_http_message(now, ep_, req_, os_);
168 }
catch (
const std::exception& e) {
169 app_.on_http_error(now, ep_, e, os_);
174 bool on_http_chunk_header(CyclTime , std::size_t )
noexcept {
return true; }
175 bool on_http_chunk_end(CyclTime )
noexcept {
return true; }
176 void on_timeout_timer(CyclTime now, Timer& )
178 auto lock = this->lock_this(now);
179 app_.on_http_timeout(now, ep_);
182 void on_io_event(CyclTime now,
int fd,
unsigned events)
184 auto lock = this->lock_this(now);
187 if (!drain_input(now, fd)) {
194 if (out_.
empty() || (write_blocked_ && !(events &
EpollOut))) {
198 }
catch (
const Exception&) {
201 }
catch (
const std::exception& e) {
202 app_.on_http_error(now, ep_, e, os_);
206 bool drain_input(CyclTime now,
int fd)
209 for (
int i{0};
i < 4; ++
i) {
215 if (
ec == std::errc::operation_would_block) {
218 throw std::system_error{
ec,
"read"};
230 if (
static_cast<size_t>(
size) < buffer_size(
buf)) {
236 schedule_timeout(now);
240 void flush_output(CyclTime now)
249 if (write_blocked_) {
252 write_blocked_ =
false;
254 }
else if (!write_blocked_) {
257 write_blocked_ =
true;
260 void schedule_timeout(CyclTime now)
262 const auto timeout = std::chrono::ceil<Seconds>(now.mono_time() + IdleTimeout);
270 Reactor::Handle sub_;
275 bool in_progress_{
false}, write_blocked_{
false};