#ifndef TRANSPORT_HH #define TRANSPORT_HH #include "unique_fd.hh" #include #include #include #include #include #include #include class Buffer; class Config; class Logger; class Looper; class TaskRunner; class Transport { public: class Request { public: virtual ~Request() = default; virtual std::string_view method() const = 0; virtual std::string_view path() const = 0; virtual std::string_view query(std::string_view name) const = 0; virtual std::optional header_one( std::string_view name) const = 0; virtual std::vector header_all( std::string_view name) const = 0; }; class Input { public: virtual ~Input() = default; enum class Return { OK, // At least one byte was added to buffer. FULL, // Zero bytes added to buffer as it is full. END, // Zero or more bytes added to buffer but there are no more bytes // available because input has ended. ERR, // No bytes added to buffer and there was an fatal error reading // any more bytes. WAIT, // Zero or more bytes added to buffer but wait before calling // fill again (see wait_once). }; virtual Return fill(Buffer* buffer, size_t buf_request_size = 1) = 0; // Setup callback to be called when Input is ready to be read again using // looper. Callback will only be called once. Callback might be called // before wait returns if Input is already ready. If Input is destroyed // before getting ready the callback will never be called. virtual void wait_once(std::shared_ptr looper, std::function callback) = 0; protected: Input() = default; }; class Response { public: virtual ~Response() = default; virtual uint16_t code() const = 0; virtual std::vector> const& headers() const = 0; // Only call this once. If it returns null, call open_content_async instead. virtual std::unique_ptr open_content() = 0; // Only call this once and only if open_content() first returned nullptr. // If response is destroyed before callback is posted the callback will // never be posted. But if callback is already posted then it will run, // and the input will still be valid. virtual void open_content_async( std::shared_ptr runner, std::function)> callback); virtual void add_header(std::string name, std::string value) = 0; protected: Response() = default; }; std::unique_ptr create_ok_data(std::string data); std::unique_ptr create_ok_file(std::filesystem::path path); std::unique_ptr create_ok_exif_thumbnail( std::filesystem::path path); std::unique_ptr create_not_found(); std::unique_ptr create_redirect(std::string target, bool temporary = true); virtual std::unique_ptr create_data( uint16_t code, std::string data) = 0; virtual std::unique_ptr create_file( uint16_t code, std::filesystem::path data) = 0; virtual std::unique_ptr create_exif_thumbnail( uint16_t code, std::filesystem::path data) = 0; class Handler { public: virtual ~Handler() = default; virtual std::unique_ptr request(Transport* transport, Request const* request) = 0; protected: Handler() = default; }; // Takes care of GET/HEAD, optional cache headers and general housekeeping. // Also removes // and similar from paths. static std::unique_ptr create_default_handler( std::shared_ptr logger, Handler* handler); class Factory { public: virtual ~Factory() = default; virtual std::unique_ptr create( std::shared_ptr logger, std::shared_ptr looper, std::shared_ptr runner, // config_logger is used to write any errors during create // when reading the config. No reference kept as with logger. Logger* config_logger, Config const* config, Handler* handler) = 0; protected: Factory() = default; Factory(Factory const&) = delete; Factory& operator=(Factory const&) = delete; }; virtual ~Transport() = default; virtual void add_client(unique_fd&& fd) = 0; protected: Transport() = default; Transport(Transport const&) = delete; Transport& operator=(Transport const&) = delete; }; #endif // TRANSPORT_HH