summaryrefslogtreecommitdiff
path: root/src/transport_base.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport_base.hh')
-rw-r--r--src/transport_base.hh113
1 files changed, 113 insertions, 0 deletions
diff --git a/src/transport_base.hh b/src/transport_base.hh
new file mode 100644
index 0000000..61d7601
--- /dev/null
+++ b/src/transport_base.hh
@@ -0,0 +1,113 @@
+#ifndef TRANSPORT_BASE_HH
+#define TRANSPORT_BASE_HH
+
+#include "buffer.hh"
+#include "transport.hh"
+
+#include <chrono>
+#include <deque>
+
+class FileOpener;
+
+class TransportBase : public Transport {
+public:
+ ~TransportBase() override;
+
+ std::unique_ptr<Response> create_data(
+ uint16_t code, std::string data) override;
+
+ std::unique_ptr<Response> create_file(
+ uint16_t code, std::filesystem::path data) override;
+
+ std::unique_ptr<Response> create_exif_thumbnail(
+ uint16_t code, std::filesystem::path data) override;
+
+ void add_client(unique_fd&& fd) override;
+
+ virtual bool setup(Logger* logger, Config const* config);
+
+protected:
+ struct ClientResponse {
+ std::unique_ptr<Response> response_;
+ std::unique_ptr<Input> content_;
+
+ ClientResponse() = default;
+ explicit ClientResponse(std::unique_ptr<Response> response)
+ : response_(std::move(response)) {}
+ };
+
+ struct Client {
+ size_t const index_;
+ unique_fd fd_;
+ std::unique_ptr<Buffer> in_;
+ std::unique_ptr<Buffer> out_;
+ std::unordered_map<uint32_t, ClientResponse> responses_;
+
+ bool in_closed_{false};
+ size_t expect_in_{1};
+ uint32_t timeout_{0};
+ std::chrono::steady_clock::time_point last_event_;
+
+ explicit Client(size_t index)
+ : index_(index) {}
+ };
+
+ class UrlRequest : public Request {
+ public:
+ std::string_view path() const override;
+ std::string_view query(std::string_view name) const override;
+
+ protected:
+ virtual std::string_view url() const = 0;
+
+ private:
+ void split_url_if_needed() const;
+
+ std::string mutable path_;
+ std::unordered_map<std::string, std::string> mutable query_;
+ };
+
+ TransportBase(std::shared_ptr<Logger> logger, std::shared_ptr<Looper> looper,
+ std::shared_ptr<TaskRunner> runner, Handler* handler);
+
+ virtual uint64_t default_client_input_buffer_size() const;
+ virtual uint64_t default_client_output_buffer_size() const;
+
+ virtual void client_new(Client* client);
+ virtual void client_event(Client* client, uint8_t event);
+ virtual void client_abort(Client* client);
+ virtual bool client_flush(Client* client);
+ virtual bool client_handle(Client* client) = 0;
+ virtual void client_timeout(Client* client, uint32_t id);
+ virtual bool client_response(Client* client, uint32_t id,
+ std::unique_ptr<Response> response);
+ virtual bool client_response_header(Client* client, uint32_t id);
+ virtual bool client_response_content(Client* client, uint32_t id);
+ virtual bool client_response_footer(Client* client, uint32_t id);
+ virtual bool client_response_end(Client* client, uint32_t id);
+ void client_update_event(Client* client);
+ bool client_request(Client* client, uint32_t id,
+ std::unique_ptr<Request> request);
+ bool client_response_content(Client* client, uint32_t id, Buffer* out);
+
+ size_t clients() const { return client_.size(); }
+
+ std::shared_ptr<Logger> logger_;
+ std::shared_ptr<Looper> looper_;
+ std::shared_ptr<TaskRunner> runner_;
+ Handler* const handler_;
+ std::shared_ptr<FileOpener> file_opener_;
+
+private:
+ void client_response_content_wait(Client* client, uint32_t response_id);
+ void client_response_open(Client* client, uint32_t response_id,
+ std::unique_ptr<Input> input);
+
+ std::vector<Client> client_;
+ bool client_full_{false};
+ size_t next_avail_client_{0};
+ std::vector<unique_fd> client_wait_;
+ double client_timeout_;
+};
+
+#endif // TRANSPORT_BASE_HH