#ifndef TRANSPORT_BASE_HH #define TRANSPORT_BASE_HH #include "buffer.hh" #include "transport.hh" #include #include class FileOpener; class TransportBase : public Transport { public: ~TransportBase() override; std::unique_ptr create_data( uint16_t code, std::string data) override; std::unique_ptr create_file( uint16_t code, std::filesystem::path data) override; std::unique_ptr 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_; std::unique_ptr content_; ClientResponse() = default; explicit ClientResponse(std::unique_ptr response) : response_(std::move(response)) {} }; struct Client { size_t const index_; unique_fd fd_; std::unique_ptr in_; std::unique_ptr out_; std::unordered_map 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 mutable query_; }; TransportBase(std::shared_ptr logger, std::shared_ptr looper, std::shared_ptr 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); 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); bool client_response_content(Client* client, uint32_t id, Buffer* out); size_t clients() const { return client_.size(); } std::shared_ptr logger_; std::shared_ptr looper_; std::shared_ptr runner_; Handler* const handler_; std::shared_ptr 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); std::vector client_; bool client_full_{false}; size_t next_avail_client_{0}; std::vector client_wait_; double client_timeout_; }; #endif // TRANSPORT_BASE_HH