From 726e6c087d863a1b330bce351e1a6f3f86ae4e8f Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 4 Mar 2015 23:28:32 +0900 Subject: [PATCH] asio: server: Move push member function to response object --- examples/asio-cl.cc | 4 +- src/asio_http2_handler.cc | 69 +++++++++++++++--------- src/asio_http2_handler.h | 24 ++++++--- src/includes/nghttp2/asio_http2_server.h | 17 +++--- 4 files changed, 69 insertions(+), 45 deletions(-) diff --git a/examples/asio-cl.cc b/examples/asio-cl.cc index 7cfef6a2..8bc069ad 100644 --- a/examples/asio-cl.cc +++ b/examples/asio-cl.cc @@ -100,8 +100,8 @@ int main(int argc, char *argv[]) { std::cerr << "push response header was received" << std::endl; res.on_data([](const uint8_t *data, std::size_t len) { - // std::cerr.write(reinterpret_cast(data), len); - // std::cerr << std::endl; + std::cerr.write(reinterpret_cast(data), len); + std::cerr << std::endl; }); }); }); diff --git a/src/asio_http2_handler.cc b/src/asio_http2_handler.cc index 966295ab..df5bae17 100644 --- a/src/asio_http2_handler.cc +++ b/src/asio_http2_handler.cc @@ -47,12 +47,6 @@ const std::string &request::method() const { return impl_->method(); } const uri_ref &request::uri() const { return impl_->uri(); } -bool request::push(std::string method, std::string path, header_map h) const { - return impl_->push(std::move(method), std::move(path), std::move(h)); -} - -bool request::pushed() const { return impl_->pushed(); } - void request::on_data(data_cb cb) const { return impl_->on_data(std::move(cb)); } @@ -69,6 +63,12 @@ void response::end(std::string data) const { impl_->end(std::move(data)); } void response::end(read_cb cb) const { impl_->end(std::move(cb)); } +const response *response::push(boost::system::error_code &ec, + std::string method, std::string path, + header_map h) const { + return impl_->push(ec, std::move(method), std::move(path), std::move(h)); +} + void response::resume() const { impl_->resume(); } unsigned int response::status_code() const { return impl_->status_code(); } @@ -77,7 +77,7 @@ bool response::started() const { return impl_->started(); } response_impl &response::impl() const { return *impl_; } -request_impl::request_impl() : stream_(nullptr), pushed_(false) {} +request_impl::request_impl() : stream_(nullptr) {} const header_map &request_impl::header() const { return header_; } @@ -93,17 +93,6 @@ header_map &request_impl::header() { return header_; } void request_impl::method(std::string arg) { method_ = std::move(arg); } -bool request_impl::push(std::string method, std::string path, header_map h) { - auto handler = stream_->handler(); - auto rv = handler->push_promise(*stream_, std::move(method), std::move(path), - std::move(h)); - return rv == 0; -} - -bool request_impl::pushed() const { return pushed_; } - -void request_impl::pushed(bool f) { pushed_ = f; } - void request_impl::on_data(data_cb cb) { on_data_cb_ = std::move(cb); } void request_impl::stream(http2_stream *s) { stream_ = s; } @@ -115,7 +104,8 @@ void request_impl::call_on_data(const uint8_t *data, std::size_t len) { } response_impl::response_impl() - : stream_(nullptr), status_code_(200), started_(false) {} + : stream_(nullptr), status_code_(200), started_(false), pushed_(false), + push_promise_sent_(false) {} unsigned int response_impl::status_code() const { return status_code_; } @@ -140,6 +130,14 @@ void response_impl::end(read_cb cb) { read_cb_ = std::move(cb); started_ = true; + start_response(); +} + +void response_impl::start_response() { + if (!started_ || (pushed_ && !push_promise_sent_)) { + return; + } + auto handler = stream_->handler(); if (handler->start_response(*stream_) != 0) { @@ -152,6 +150,13 @@ void response_impl::end(read_cb cb) { } } +response *response_impl::push(boost::system::error_code &ec, std::string method, + std::string raw_path_query, header_map h) const { + auto handler = stream_->handler(); + return handler->push_promise(ec, *stream_, std::move(method), + std::move(raw_path_query), std::move(h)); +} + void response_impl::resume() { auto handler = stream_->handler(); handler->resume(*stream_); @@ -163,6 +168,10 @@ void response_impl::resume() { bool response_impl::started() const { return started_; } +void response_impl::pushed(bool f) { pushed_ = f; } + +void response_impl::push_promise_sent(bool f) { push_promise_sent_ = f; } + const header_map &response_impl::header() const { return header_; } void response_impl::stream(http2_stream *s) { stream_ = s; } @@ -345,7 +354,9 @@ int on_frame_send_callback(nghttp2_session *session, const nghttp2_frame *frame, return 0; } - handler->call_on_request(*stream); + auto &res = stream->response().impl(); + res.push_promise_sent(true); + res.start_response(); return 0; } @@ -508,10 +519,14 @@ void http2_handler::resume(http2_stream &stream) { nghttp2_session_resume_data(session_, stream.get_stream_id()); } -int http2_handler::push_promise(http2_stream &stream, std::string method, - std::string raw_path_query, header_map h) { +response *http2_handler::push_promise(boost::system::error_code &ec, + http2_stream &stream, std::string method, + std::string raw_path_query, + header_map h) { int rv; + ec.clear(); + auto &req = stream.request().impl(); auto nva = std::vector(); @@ -531,20 +546,24 @@ int http2_handler::push_promise(http2_stream &stream, std::string method, nva.size(), nullptr); if (rv < 0) { - return -1; + ec = make_error_code(static_cast(rv)); + return nullptr; } auto promised_stream = create_stream(rv); auto &promised_req = promised_stream->request().impl(); - promised_req.pushed(true); promised_req.header(std::move(h)); promised_req.method(std::move(method)); + auto &uref = promised_req.uri(); uref.scheme = req.uri().scheme; uref.host = req.uri().host; split_path(uref, std::begin(raw_path_query), std::end(raw_path_query)); - return 0; + auto &promised_res = promised_stream->response().impl(); + promised_res.pushed(true); + + return &promised_stream->response(); } boost::asio::io_service &http2_handler::io_service() { return io_service_; } diff --git a/src/asio_http2_handler.h b/src/asio_http2_handler.h index 8364767c..38b44e5c 100644 --- a/src/asio_http2_handler.h +++ b/src/asio_http2_handler.h @@ -57,13 +57,8 @@ public: const uri_ref &uri() const; uri_ref &uri(); - bool push(std::string method, std::string raw_path_query, header_map h = {}); - - bool pushed() const; - void on_data(data_cb cb); - void pushed(bool f); void stream(http2_stream *s); void call_on_data(const uint8_t *data, std::size_t len); @@ -73,7 +68,6 @@ private: std::string method_; uri_ref uri_; data_cb on_data_cb_; - bool pushed_; }; class response_impl { @@ -84,9 +78,16 @@ public: void end(read_cb cb); void resume(); + response *push(boost::system::error_code &ec, std::string method, + std::string raw_path_query, header_map h = {}) const; + + void start_response(); + unsigned int status_code() const; const header_map &header() const; bool started() const; + void pushed(bool f); + void push_promise_sent(bool f); void stream(http2_stream *s); read_cb::result_type call_read(uint8_t *data, std::size_t len, uint32_t *data_flags); @@ -96,7 +97,13 @@ private: header_map header_; read_cb read_cb_; unsigned int status_code_; + // true if response started (end() is called) bool started_; + // true if this is pushed stream's response + bool pushed_; + // true if PUSH_PROMISE is sent if this is response of a pushed + // stream + bool push_promise_sent_; }; class http2_stream { @@ -153,8 +160,9 @@ public: void resume(http2_stream &stream); - int push_promise(http2_stream &stream, std::string method, - std::string raw_path_query, header_map h); + response *push_promise(boost::system::error_code &ec, http2_stream &stream, + std::string method, std::string raw_path_query, + header_map h); boost::asio::io_service &io_service(); diff --git a/src/includes/nghttp2/asio_http2_server.h b/src/includes/nghttp2/asio_http2_server.h index 16366ac2..c7bdad17 100644 --- a/src/includes/nghttp2/asio_http2_server.h +++ b/src/includes/nghttp2/asio_http2_server.h @@ -54,16 +54,6 @@ public: // Sets callback when chunk of request body is received. void on_data(data_cb cb) const; - // Pushes resource denoted by |path| using |method|. The additional - // headers can be given in |h|. request_cb will be called for - // pushed resource later on. This function returns true if it - // succeeds, or false. - bool push(std::string method, std::string raw_path_query, - header_map h = {}) const; - - // Returns true if this is pushed request. - bool pushed() const; - // Application must not call this directly. request_impl &impl() const; @@ -91,6 +81,13 @@ public: // Resumes deferred response. void resume() const; + // Pushes resource denoted by |raw_path_query| using |method|. The + // additional headers can be given in |h|. This function returns + // pointer to response object for promised stream, otherwise nullptr + // and error code is filled in |ec|. + const response *push(boost::system::error_code &ec, std::string method, + std::string raw_path_query, header_map h = {}) const; + // Returns status code. unsigned int status_code() const;