tdlight/tdnet/td/net/HttpConnectionBase.h

165 lines
4.0 KiB
C
Raw Normal View History

//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
//
// 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)
//
#pragma once
#include "td/actor/actor.h"
#include "td/net/HttpQuery.h"
#include "td/net/HttpReader.h"
#include "td/utils/buffer.h"
#include "td/utils/BufferedFd.h"
#include "td/utils/port/Fd.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
namespace td {
class FdInterface {
public:
FdInterface() = default;
FdInterface(const FdInterface &) = delete;
FdInterface &operator=(const FdInterface &) = delete;
FdInterface(FdInterface &&) = default;
FdInterface &operator=(FdInterface &&) = default;
virtual ~FdInterface() = default;
virtual const Fd &get_fd() const = 0;
virtual Fd &get_fd() = 0;
virtual int32 get_flags() const = 0;
virtual Status get_pending_error() TD_WARN_UNUSED_RESULT = 0;
virtual Result<size_t> write(Slice slice) TD_WARN_UNUSED_RESULT = 0;
virtual Result<size_t> read(MutableSlice slice) TD_WARN_UNUSED_RESULT = 0;
virtual void close() = 0;
virtual bool empty() const = 0;
};
template <class FdT>
class FdToInterface : public FdInterface {
public:
FdToInterface() = default;
explicit FdToInterface(FdT fd) : fd_(std::move(fd)) {
}
const Fd &get_fd() const final {
return fd_.get_fd();
}
Fd &get_fd() final {
return fd_.get_fd();
}
int32 get_flags() const final {
return fd_.get_flags();
}
Status get_pending_error() final TD_WARN_UNUSED_RESULT {
return fd_.get_pending_error();
}
Result<size_t> write(Slice slice) final TD_WARN_UNUSED_RESULT {
return fd_.write(slice);
}
Result<size_t> read(MutableSlice slice) final TD_WARN_UNUSED_RESULT {
return fd_.read(slice);
}
void close() final {
fd_.close();
}
bool empty() const final {
return fd_.empty();
}
private:
FdT fd_;
};
template <class FdT>
std::unique_ptr<FdInterface> make_fd_interface(FdT fd) {
return make_unique<FdToInterface<FdT>>(std::move(fd));
}
class FdProxy {
public:
FdProxy() = default;
explicit FdProxy(std::unique_ptr<FdInterface> fd) : fd_(std::move(fd)) {
}
const Fd &get_fd() const {
return fd_->get_fd();
}
Fd &get_fd() {
return fd_->get_fd();
}
int32 get_flags() const {
return fd_->get_flags();
}
Status get_pending_error() TD_WARN_UNUSED_RESULT {
return fd_->get_pending_error();
}
Result<size_t> write(Slice slice) TD_WARN_UNUSED_RESULT {
return fd_->write(slice);
}
Result<size_t> read(MutableSlice slice) TD_WARN_UNUSED_RESULT {
return fd_->read(slice);
}
void close() {
fd_->close();
}
bool empty() const {
return fd_->empty();
}
private:
std::unique_ptr<FdInterface> fd_;
};
template <class FdT>
FdProxy make_fd_proxy(FdT fd) {
return FdProxy(make_fd_interface(std::move(fd)));
}
namespace detail {
class HttpConnectionBase : public Actor {
public:
void write_next(BufferSlice buffer);
void write_ok();
void write_error(Status error);
protected:
enum class State { Read, Write, Close };
template <class FdT>
HttpConnectionBase(State state, FdT fd, size_t max_post_size, size_t max_files, int32 idle_timeout)
: HttpConnectionBase(state, make_fd_proxy(std::move(fd)), max_post_size, max_files, idle_timeout) {
}
HttpConnectionBase(State state, FdProxy fd, size_t max_post_size, size_t max_files, int32 idle_timeout);
private:
using StreamConnection = BufferedFd<FdProxy>;
State state_;
StreamConnection stream_connection_;
size_t max_post_size_;
size_t max_files_;
int32 idle_timeout_;
HttpReader reader_;
HttpQueryPtr current_query_;
bool close_after_write_ = false;
void live_event();
void start_up() override;
void tear_down() override;
void timeout_expired() override;
void loop() override;
virtual void on_query(HttpQueryPtr) = 0;
virtual void on_error(Status error) = 0;
};
} // namespace detail
} // namespace td