diff options
Diffstat (limited to 'src/fcgi_protocol.hh')
| -rw-r--r-- | src/fcgi_protocol.hh | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/src/fcgi_protocol.hh b/src/fcgi_protocol.hh new file mode 100644 index 0000000..f41c4a8 --- /dev/null +++ b/src/fcgi_protocol.hh @@ -0,0 +1,191 @@ +#ifndef FCGI_PROTOCOL_HH +#define FCGI_PROTOCOL_HH + +#include <memory> +#include <stdint.h> +#include <string> + +class Buffer; +class RoBuffer; + +namespace fcgi { + +enum RecordType { + BeginRequest = 1, + AbortRequest = 2, + EndRequest = 3, + Params = 4, + Stdin = 5, + Stdout = 6, + Stderr = 7, + Data = 8, + GetValues = 9, + GetValuesResult = 10, + UnknownType = 11, +}; + +enum Role { + Responder = 1, + Authorizer = 2, + Filter = 3, +}; + +enum Flags { + KeepConn = 1, +}; + +enum ProtocolStatus { + RequestComplete = 0, + CantMpxConn = 1, + Overloaded = 2, + UnknownRole = 3, +}; + +class Record { +public: + virtual ~Record() = default; + + virtual bool good() const = 0; + + virtual uint8_t type() const = 0; + virtual uint16_t request_id() const = 0; + virtual uint16_t content_length() const = 0; + virtual uint8_t padding_length() const = 0; + + static std::unique_ptr<Record> parse(RoBuffer* buffer); + +protected: + Record() = default; + Record(Record const&) = delete; + Record& operator=(Record const&) = delete; +}; + +class BeginRequestBody { +public: + virtual ~BeginRequestBody() = default; + + virtual bool good() const = 0; + + virtual uint16_t role() const = 0; + virtual uint8_t flags() const = 0; + + static std::unique_ptr<BeginRequestBody> parse(Record const* record, + RoBuffer* buffer); + +protected: + BeginRequestBody() = default; + BeginRequestBody(BeginRequestBody const&) = delete; + BeginRequestBody& operator=(BeginRequestBody const&) = delete; +}; + +class RecordStream { +public: + virtual ~RecordStream() = default; + + // True if all data has been read from stream. + virtual bool end_of_stream() const = 0; + // True if all data from last added record has been read. + virtual bool end_of_record() const = 0; + // True if no more data is coming, ie. what rbuf() returned last is all + // there will ever be. + virtual bool all_available() = 0; + + virtual char const* rbuf(RoBuffer* buf, size_t want, size_t& avail) = 0; + virtual void rcommit(RoBuffer* buf, size_t bytes) = 0; + + // Call when next package for stream arrives. + virtual void add(Record const* record) = 0; + + // Create stream with record as the first package in stream. + static std::unique_ptr<RecordStream> create_stream(Record const* record); + + // Create stream with record as the only package in stream. + static std::unique_ptr<RecordStream> create_single(Record const* record); + +protected: + RecordStream() = default; + RecordStream(RecordStream const&) = delete; + RecordStream& operator=(RecordStream const&) = delete; +}; + +class Pair { +public: + virtual ~Pair() = default; + + // Returns false if bad encoding or an invalid stream was found. + // Calling next() will NOT change a false value back to true. + virtual bool good() const = 0; + virtual std::string const& name() const = 0; + virtual std::string const& value() const = 0; + + // Returns nullptr if stream and buf needs more data. + static std::unique_ptr<Pair> start( + RecordStream* stream, RoBuffer* buf); + + // Returns false if stream and buf needs more data. In that case Pair + // is not modified. + virtual bool next(RecordStream* stream, RoBuffer* buf) = 0; + +protected: + Pair() = default; + Pair(Pair const&) = delete; + Pair& operator=(Pair const&) = delete; +}; + +class RecordBuilder { +public: + virtual ~RecordBuilder() = default; + + virtual bool build(Buffer* dst) const = 0; + virtual bool build(char* dst, size_t avail) const = 0; + virtual bool padding(Buffer* dst) const = 0; + virtual bool padding(char* dst, size_t avail) const = 0; + virtual size_t size() const = 0; + + static std::unique_ptr<RecordBuilder> create( + RecordType type, + uint16_t request_id, + uint16_t content_length, + int16_t padding_length = -1); + + static std::unique_ptr<RecordBuilder> create( + RecordType type, + uint16_t request_id, + std::string body); + + static std::unique_ptr<RecordBuilder> create_unknown_type( + uint8_t unknown_type); + + static std::unique_ptr<RecordBuilder> create_begin_request( + uint16_t request_id, Role role, uint8_t flags); + + static std::unique_ptr<RecordBuilder> create_end_request( + uint16_t request_id, uint32_t app_status, ProtocolStatus protocol_status); + +protected: + RecordBuilder() = default; + RecordBuilder(RecordBuilder const&) = delete; + RecordBuilder& operator=(RecordBuilder const&) = delete; +}; + +class PairBuilder { +public: + virtual ~PairBuilder() = default; + + virtual void add(std::string name, std::string value) = 0; + + virtual size_t size() const = 0; + + virtual bool build(Buffer* buf) const = 0; + + static std::unique_ptr<PairBuilder> create(); + +protected: + PairBuilder() = default; + PairBuilder(PairBuilder const&) = delete; + PairBuilder& operator=(PairBuilder const&) = delete; +}; + +} // namespace fcgi + +#endif // FCGI_PROTOCOL_HH |
