diff options
Diffstat (limited to 'web/apache/stream')
-rw-r--r-- | web/apache/stream | 87 |
1 files changed, 48 insertions, 39 deletions
diff --git a/web/apache/stream b/web/apache/stream index eb62b85..5f76347 100644 --- a/web/apache/stream +++ b/web/apache/stream @@ -5,28 +5,44 @@ #ifndef WEB_APACHE_STREAM #define WEB_APACHE_STREAM -#include <streambuf> -#include <ios> // streamsize -#include <algorithm> // min(), max() -#include <cstring> // memmove() -#include <memory> // unique_ptr - #include <httpd/httpd.h> #include <httpd/http_protocol.h> +#include <ios> // streamsize +#include <memory> // unique_ptr +#include <cstring> // memmove() +#include <streambuf> +#include <algorithm> // min(), max() + #include <web/module> namespace web { namespace apache { - class ostreambuf : public std::streambuf + // Object of a class implementing this interface is intended for + // keeping the state of writing response to the client. + // + struct write_state { - public: - ostreambuf (request_rec* rec) : rec_ (rec) {} + // Called by ostreambuf methods when some content to be written to the + // client. + // + virtual void + set_write_state () = 0; + + // Called to check if any data have already been written to the client. + // Such checks required for some operations which are impossible to + // execute after response is partially written. + // + virtual bool + get_write_state () const noexcept = 0; + }; - bool - write_flag () const noexcept {return write_;} + class ostreambuf: public std::streambuf + { + public: + ostreambuf (request_rec* rec, write_state& ws): rec_ (rec), ws_ (ws) {} private: virtual int_type @@ -34,7 +50,7 @@ namespace web { if (c != traits_type::eof ()) { - flag_write (); + ws_.set_write_state (); char chr = c; @@ -51,7 +67,7 @@ namespace web virtual std::streamsize xsputn (const char* s, std::streamsize num) { - flag_write (); + ws_.set_write_state (); if (ap_rwrite (s, num, rec_) < 0) { @@ -64,7 +80,7 @@ namespace web virtual int sync () { - if(ap_rflush (rec_) < 0) + if (ap_rflush (rec_) < 0) { throw invalid_request (HTTP_REQUEST_TIME_OUT); } @@ -72,40 +88,30 @@ namespace web return 0; } - void - flag_write () noexcept - { - if (!write_) - { - // Preparing to write a response read and discard request - // body if any. - // - int r = ap_discard_request_body (rec_); - - if (r != OK) - { - throw invalid_request (r); - } - - write_ = true; - } - } - private: request_rec* rec_; - bool write_ {false}; + write_state& ws_; }; - class istreambuf : public std::streambuf + class istreambuf: public std::streambuf { public: - istreambuf (request_rec* rec, size_t bufsize = 1024, size_t putback = 1) + istreambuf (request_rec* rec, + write_state& ws, + size_t bufsize = 1024, + size_t putback = 1) : rec_ (rec), + ws_ (ws), bufsize_ (std::max (bufsize, (size_t)1)), putback_ (std::min (putback, bufsize_ - 1)), buf_ (new char[bufsize_]) { + if (ws_.get_write_state ()) + { + throw sequence_error ("::web::apache::istreambuf::istreambuf"); + } + char* p = buf_.get () + putback_; setg (p, p, p); @@ -121,6 +127,11 @@ namespace web virtual int_type underflow () { + if (ws_.get_write_state ()) + { + throw sequence_error ("::web::apache::istreambuf::underflow"); + } + if (gptr () < egptr ()) return traits_type::to_int_type (*gptr ()); @@ -144,15 +155,13 @@ namespace web return traits_type::to_int_type (*gptr ()); } - bool error () const noexcept {return error_;} - private: request_rec* rec_; + write_state& ws_; size_t bufsize_; size_t putback_; std::unique_ptr<char[]> buf_; - bool error_ {false}; }; } |