asio: server: Move push member function to response object

This commit is contained in:
Tatsuhiro Tsujikawa 2015-03-04 23:28:32 +09:00
parent ff0eaf8399
commit 726e6c087d
4 changed files with 69 additions and 45 deletions

View File

@ -100,8 +100,8 @@ int main(int argc, char *argv[]) {
std::cerr << "push response header was received" << std::endl; std::cerr << "push response header was received" << std::endl;
res.on_data([](const uint8_t *data, std::size_t len) { res.on_data([](const uint8_t *data, std::size_t len) {
// std::cerr.write(reinterpret_cast<const char *>(data), len); std::cerr.write(reinterpret_cast<const char *>(data), len);
// std::cerr << std::endl; std::cerr << std::endl;
}); });
}); });
}); });

View File

@ -47,12 +47,6 @@ const std::string &request::method() const { return impl_->method(); }
const uri_ref &request::uri() const { return impl_->uri(); } 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 { void request::on_data(data_cb cb) const {
return impl_->on_data(std::move(cb)); 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)); } 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(); } void response::resume() const { impl_->resume(); }
unsigned int response::status_code() const { return impl_->status_code(); } 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_; } 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_; } 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); } 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::on_data(data_cb cb) { on_data_cb_ = std::move(cb); }
void request_impl::stream(http2_stream *s) { stream_ = s; } 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() 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_; } 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); read_cb_ = std::move(cb);
started_ = true; started_ = true;
start_response();
}
void response_impl::start_response() {
if (!started_ || (pushed_ && !push_promise_sent_)) {
return;
}
auto handler = stream_->handler(); auto handler = stream_->handler();
if (handler->start_response(*stream_) != 0) { 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() { void response_impl::resume() {
auto handler = stream_->handler(); auto handler = stream_->handler();
handler->resume(*stream_); handler->resume(*stream_);
@ -163,6 +168,10 @@ void response_impl::resume() {
bool response_impl::started() const { return started_; } 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_; } const header_map &response_impl::header() const { return header_; }
void response_impl::stream(http2_stream *s) { stream_ = s; } 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; return 0;
} }
handler->call_on_request(*stream); auto &res = stream->response().impl();
res.push_promise_sent(true);
res.start_response();
return 0; return 0;
} }
@ -508,10 +519,14 @@ void http2_handler::resume(http2_stream &stream) {
nghttp2_session_resume_data(session_, stream.get_stream_id()); nghttp2_session_resume_data(session_, stream.get_stream_id());
} }
int http2_handler::push_promise(http2_stream &stream, std::string method, response *http2_handler::push_promise(boost::system::error_code &ec,
std::string raw_path_query, header_map h) { http2_stream &stream, std::string method,
std::string raw_path_query,
header_map h) {
int rv; int rv;
ec.clear();
auto &req = stream.request().impl(); auto &req = stream.request().impl();
auto nva = std::vector<nghttp2_nv>(); auto nva = std::vector<nghttp2_nv>();
@ -531,20 +546,24 @@ int http2_handler::push_promise(http2_stream &stream, std::string method,
nva.size(), nullptr); nva.size(), nullptr);
if (rv < 0) { if (rv < 0) {
return -1; ec = make_error_code(static_cast<nghttp2_error>(rv));
return nullptr;
} }
auto promised_stream = create_stream(rv); auto promised_stream = create_stream(rv);
auto &promised_req = promised_stream->request().impl(); auto &promised_req = promised_stream->request().impl();
promised_req.pushed(true);
promised_req.header(std::move(h)); promised_req.header(std::move(h));
promised_req.method(std::move(method)); promised_req.method(std::move(method));
auto &uref = promised_req.uri(); auto &uref = promised_req.uri();
uref.scheme = req.uri().scheme; uref.scheme = req.uri().scheme;
uref.host = req.uri().host; uref.host = req.uri().host;
split_path(uref, std::begin(raw_path_query), std::end(raw_path_query)); 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_; } boost::asio::io_service &http2_handler::io_service() { return io_service_; }

View File

@ -57,13 +57,8 @@ public:
const uri_ref &uri() const; const uri_ref &uri() const;
uri_ref &uri(); 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 on_data(data_cb cb);
void pushed(bool f);
void stream(http2_stream *s); void stream(http2_stream *s);
void call_on_data(const uint8_t *data, std::size_t len); void call_on_data(const uint8_t *data, std::size_t len);
@ -73,7 +68,6 @@ private:
std::string method_; std::string method_;
uri_ref uri_; uri_ref uri_;
data_cb on_data_cb_; data_cb on_data_cb_;
bool pushed_;
}; };
class response_impl { class response_impl {
@ -84,9 +78,16 @@ public:
void end(read_cb cb); void end(read_cb cb);
void resume(); 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; unsigned int status_code() const;
const header_map &header() const; const header_map &header() const;
bool started() const; bool started() const;
void pushed(bool f);
void push_promise_sent(bool f);
void stream(http2_stream *s); void stream(http2_stream *s);
read_cb::result_type call_read(uint8_t *data, std::size_t len, read_cb::result_type call_read(uint8_t *data, std::size_t len,
uint32_t *data_flags); uint32_t *data_flags);
@ -96,7 +97,13 @@ private:
header_map header_; header_map header_;
read_cb read_cb_; read_cb read_cb_;
unsigned int status_code_; unsigned int status_code_;
// true if response started (end() is called)
bool started_; 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 { class http2_stream {
@ -153,8 +160,9 @@ public:
void resume(http2_stream &stream); void resume(http2_stream &stream);
int push_promise(http2_stream &stream, std::string method, response *push_promise(boost::system::error_code &ec, http2_stream &stream,
std::string raw_path_query, header_map h); std::string method, std::string raw_path_query,
header_map h);
boost::asio::io_service &io_service(); boost::asio::io_service &io_service();

View File

@ -54,16 +54,6 @@ public:
// Sets callback when chunk of request body is received. // Sets callback when chunk of request body is received.
void on_data(data_cb cb) const; 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. // Application must not call this directly.
request_impl &impl() const; request_impl &impl() const;
@ -91,6 +81,13 @@ public:
// Resumes deferred response. // Resumes deferred response.
void resume() const; 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. // Returns status code.
unsigned int status_code() const; unsigned int status_code() const;