aboutsummaryrefslogtreecommitdiffhomepage
path: root/tdnet/td/net/HttpConnectionBase.cpp
diff options
context:
space:
mode:
authorArseny Smirnov <arseny30@gmail.com>2018-12-31 22:04:05 +0300
committerArseny Smirnov <arseny30@gmail.com>2017-12-31 23:08:40 +0300
commit71d03f39c364367a8a7c51f783a41099297de826 (patch)
tree4c0c57f9ddb87f46d58192e1ebfd2c40f6d2c315 /tdnet/td/net/HttpConnectionBase.cpp
Project import generated by Copybara.
GitOrigin-RevId: 318483224ad6164d9966f731d60cde37039bb2d4
Diffstat (limited to 'tdnet/td/net/HttpConnectionBase.cpp')
-rw-r--r--tdnet/td/net/HttpConnectionBase.cpp153
1 files changed, 153 insertions, 0 deletions
diff --git a/tdnet/td/net/HttpConnectionBase.cpp b/tdnet/td/net/HttpConnectionBase.cpp
new file mode 100644
index 000000000..a0d437258
--- /dev/null
+++ b/tdnet/td/net/HttpConnectionBase.cpp
@@ -0,0 +1,153 @@
+//
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2017
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include "td/net/HttpConnectionBase.h"
+
+#include "td/actor/actor.h"
+
+#include "td/net/HttpHeaderCreator.h"
+
+#include "td/utils/logging.h"
+#include "td/utils/misc.h"
+
+namespace td {
+namespace detail {
+
+HttpConnectionBase::HttpConnectionBase(State state, FdProxy fd, size_t max_post_size, size_t max_files,
+ int32 idle_timeout)
+ : state_(state)
+ , stream_connection_(std::move(fd))
+ , max_post_size_(max_post_size)
+ , max_files_(max_files)
+ , idle_timeout_(idle_timeout) {
+ CHECK(state_ != State::Close);
+}
+
+void HttpConnectionBase::live_event() {
+ if (idle_timeout_ != 0) {
+ set_timeout_in(idle_timeout_);
+ }
+}
+
+void HttpConnectionBase::start_up() {
+ stream_connection_.get_fd().set_observer(this);
+ subscribe(stream_connection_.get_fd());
+ reader_.init(&stream_connection_.input_buffer(), max_post_size_, max_files_);
+ if (state_ == State::Read) {
+ current_query_ = make_unique<HttpQuery>();
+ }
+ live_event();
+ yield();
+}
+void HttpConnectionBase::tear_down() {
+ unsubscribe_before_close(stream_connection_.get_fd());
+ stream_connection_.close();
+}
+
+void HttpConnectionBase::write_next(BufferSlice buffer) {
+ CHECK(state_ == State::Write);
+ stream_connection_.output_buffer().append(std::move(buffer));
+ loop();
+}
+
+void HttpConnectionBase::write_ok() {
+ CHECK(state_ == State::Write);
+ current_query_ = make_unique<HttpQuery>();
+ state_ = State::Read;
+ live_event();
+ loop();
+}
+
+void HttpConnectionBase::write_error(Status error) {
+ CHECK(state_ == State::Write);
+ LOG(WARNING) << "Close http connection: " << error;
+ state_ = State::Close;
+ loop();
+}
+
+void HttpConnectionBase::timeout_expired() {
+ LOG(INFO) << "Idle timeout expired";
+
+ if (stream_connection_.need_flush_write()) {
+ on_error(Status::Error("Write timeout expired"));
+ } else if (state_ == State::Read) {
+ on_error(Status::Error("Read timeout expired"));
+ }
+
+ stop();
+}
+void HttpConnectionBase::loop() {
+ if (can_read(stream_connection_)) {
+ LOG(DEBUG) << "Can read from the connection";
+ auto r = stream_connection_.flush_read();
+ if (r.is_error()) {
+ if (!begins_with(r.error().message(), "SSL error {336134278")) { // if error is not yet outputed
+ LOG(INFO) << "flush_read error: " << r.error();
+ }
+ on_error(Status::Error(r.error().public_message()));
+ return stop();
+ }
+ }
+
+ // TODO: read_next even when state_ == State::Write
+
+ bool want_read = false;
+ if (state_ == State::Read) {
+ auto res = reader_.read_next(current_query_.get());
+ if (res.is_error()) {
+ live_event();
+ state_ = State::Write;
+ LOG(INFO) << res.error();
+ HttpHeaderCreator hc;
+ hc.init_status_line(res.error().code());
+ hc.set_content_size(0);
+ stream_connection_.output_buffer().append(hc.finish().ok());
+ close_after_write_ = true;
+ on_error(Status::Error(res.error().public_message()));
+ } else if (res.ok() == 0) {
+ state_ = State::Write;
+ LOG(INFO) << "Send query to handler";
+ live_event();
+ on_query(std::move(current_query_));
+ } else {
+ want_read = true;
+ }
+ }
+
+ if (can_write(stream_connection_)) {
+ LOG(DEBUG) << "Can write to the connection";
+ auto r = stream_connection_.flush_write();
+ if (r.is_error()) {
+ LOG(INFO) << "flush_write error: " << r.error();
+ on_error(Status::Error(r.error().public_message()));
+ }
+ if (close_after_write_ && !stream_connection_.need_flush_write()) {
+ return stop();
+ }
+ }
+
+ if (stream_connection_.get_fd().has_pending_error()) {
+ auto pending_error = stream_connection_.get_pending_error();
+ LOG(INFO) << pending_error;
+ if (!close_after_write_) {
+ on_error(Status::Error(pending_error.public_message()));
+ }
+ state_ = State::Close;
+ }
+ if (can_close(stream_connection_)) {
+ LOG(INFO) << "Can close the connection";
+ state_ = State::Close;
+ }
+ if (state_ == State::Close) {
+ LOG_IF(INFO, stream_connection_.need_flush_write()) << "Close nonempty connection";
+ LOG_IF(INFO, want_read &&
+ (stream_connection_.input_buffer().size() > 0 || current_query_->type_ != HttpQuery::Type::EMPTY))
+ << "Close connection while reading request/response";
+ return stop();
+ }
+}
+} // namespace detail
+} // namespace td