44 using AutoUnlinkOption = boost::intrusive::link_mode<boost::intrusive::auto_unlink>;
46 static constexpr auto IdleTimeout = 5
s;
59 , sock_{std::move(
sock)}
64 schedule_timeout(now);
65 app.on_http_connect(now, ep_);
78 boost::intrusive::list_member_hook<AutoUnlinkOption>
list_hook;
83 app_.on_http_disconnect(now, ep_);
95 bool on_http_message_begin(
CyclTime )
noexcept
101 bool on_http_url(
CyclTime now, std::string_view
sv)
noexcept
107 }
catch (
const std::exception& e) {
108 app_.on_http_error(now, ep_, e, os_);
113 bool on_http_status(CyclTime , std::string_view )
noexcept
118 bool on_http_header_field(CyclTime now, std::string_view
sv,
First first)
noexcept
122 req_.append_header_field(
sv, first);
124 }
catch (
const std::exception& e) {
125 app_.on_http_error(now, ep_, e, os_);
130 bool on_http_header_value(CyclTime now, std::string_view
sv,
First first)
noexcept
134 req_.append_header_value(
sv, first);
136 }
catch (
const std::exception& e) {
137 app_.on_http_error(now, ep_, e, os_);
142 bool on_http_headers_end(CyclTime )
noexcept
144 req_.set_method(
method());
147 bool on_http_body(CyclTime now, std::string_view
sv)
noexcept
151 req_.append_body(
sv);
153 }
catch (
const std::exception& e) {
154 app_.on_http_error(now, ep_, e, os_);
159 bool on_http_message_end(CyclTime now)
noexcept
163 in_progress_ =
false;
165 app_.on_http_message(now, ep_, req_, os_);
167 }
catch (
const std::exception& e) {
168 app_.on_http_error(now, ep_, e, os_);
173 bool on_http_chunk_header(CyclTime , std::size_t )
noexcept {
return true; }
174 bool on_http_chunk_end(CyclTime )
noexcept {
return true; }
175 void on_timeout_timer(CyclTime now, Timer& )
177 auto lock = this->lock_this(now);
178 app_.on_http_timeout(now, ep_);
181 void on_io_event(CyclTime now,
int fd,
unsigned events)
183 auto lock = this->lock_this(now);
186 if (!drain_input(now, fd)) {
193 if (out_.
empty() || (write_blocked_ && !(events &
EpollOut))) {
197 }
catch (
const Exception&) {
200 }
catch (
const std::exception& e) {
201 app_.on_http_error(now, ep_, e, os_);
205 bool drain_input(CyclTime now,
int fd)
208 for (
int i{0};
i < 4; ++
i) {
214 if (
ec == std::errc::operation_would_block) {
217 throw std::system_error{
ec,
"read"};
229 if (
static_cast<size_t>(
size) < buffer_size(
buf)) {
235 schedule_timeout(now);
239 void flush_output(CyclTime now)
248 if (write_blocked_) {
251 write_blocked_ =
false;
253 }
else if (!write_blocked_) {
256 write_blocked_ =
true;
259 void schedule_timeout(CyclTime now)
261 const auto timeout = std::chrono::ceil<Seconds>(now.mono_time() + IdleTimeout);
269 Reactor::Handle sub_;
274 bool in_progress_{
false}, write_blocked_{
false};