From 04c1324c57692dfd22fab211a7443aaf484f07ce Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 27 Apr 2015 13:52:25 +0200 Subject: Implement module configuration, cleanup the code --- web/apache/stream | 87 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 39 deletions(-) (limited to 'web/apache/stream') 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 -#include // streamsize -#include // min(), max() -#include // memmove() -#include // unique_ptr - #include #include +#include // streamsize +#include // unique_ptr +#include // memmove() +#include +#include // min(), max() + #include 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 buf_; - bool error_ {false}; }; } -- cgit v1.1