diff --git a/src/Makefile.am b/src/Makefile.am index 254abf48..bdda06d8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -173,14 +173,19 @@ DISTCLEANFILES = $(pkgconfig_DATA) lib_LTLIBRARIES = libnghttp2_asio.la libnghttp2_asio_la_SOURCES = \ - asio_connection.h \ - asio_server.cc asio_server.h \ - asio_io_service_pool.cc asio_io_service_pool.h \ - asio_http2_handler.cc asio_http2_handler.h \ - asio_http2_impl.cc asio_http2_impl.h \ util.cc util.h http2.cc http2.h \ ssl.cc ssl.h \ asio_common.cc asio_common.h \ + asio_io_service_pool.cc asio_io_service_pool.h \ + asio_server_http2_impl.cc asio_server_http2_impl.h \ + asio_server.cc asio_server.h \ + asio_server_http2_handler.cc asio_server_http2_handler.h \ + asio_server_connection.h \ + asio_server_request.cc \ + asio_server_request_impl.cc asio_server_request_impl.h \ + asio_server_response.cc \ + asio_server_response_impl.cc asio_server_response_impl.h \ + asio_server_stream.cc asio_server_stream.h \ asio_server_serve_mux.cc asio_server_serve_mux.h \ asio_client_session.cc \ asio_client_session_impl.cc asio_client_session_impl.h \ diff --git a/src/asio_common.cc b/src/asio_common.cc index 2f7548dd..ec0df2b3 100644 --- a/src/asio_common.cc +++ b/src/asio_common.cc @@ -27,6 +27,7 @@ #include #include "util.h" +#include "template.h" namespace nghttp2 { namespace asio_http2 { @@ -62,5 +63,49 @@ read_cb string_reader(std::string data) { }; } +template +std::shared_ptr> defer_shared(F &&f, T &&... t) { + return std::make_shared>(std::forward(f), + std::forward(t)...); +} + +read_cb file_reader(const std::string &path) { + auto fd = open(path.c_str(), O_RDONLY); + if (fd == -1) { + return read_cb(); + } + + return file_reader_from_fd(fd); +} + +read_cb file_reader_from_fd(int fd) { + auto d = defer_shared(close, fd); + + return [fd, d](uint8_t *buf, size_t len, uint32_t *data_flags) + -> read_cb::result_type { + ssize_t n; + while ((n = read(fd, buf, len)) == -1 && errno == EINTR) + ; + + if (n == -1) { + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + + if (n == 0) { + *data_flags |= NGHTTP2_DATA_FLAG_EOF; + } + + return n; + }; +} + +bool check_path(const std::string &path) { return util::check_path(path); } + +std::string percent_decode(const std::string &s) { + return util::percentDecode(std::begin(s), std::end(s)); +} + +std::string http_date(int64_t t) { return util::http_date(t); } + } // namespace asio_http2 } // namespace nghttp2 diff --git a/src/asio_io_service_pool.cc b/src/asio_io_service_pool.cc index 90241b79..c6936d08 100644 --- a/src/asio_io_service_pool.cc +++ b/src/asio_io_service_pool.cc @@ -33,19 +33,14 @@ // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // +#include "asio_io_service_pool.h" -#include "asio_server.h" -#include #include -#include -#include namespace nghttp2 { namespace asio_http2 { -namespace server { - io_service_pool::io_service_pool(std::size_t pool_size) : next_io_service_(0) { if (pool_size == 0) { throw std::runtime_error("io_service_pool size is 0"); @@ -95,8 +90,6 @@ boost::asio::io_service &io_service_pool::get_io_service() { return io_service; } -} // namespace server - } // namespace asio_http2 } // namespace nghttp2 diff --git a/src/asio_io_service_pool.h b/src/asio_io_service_pool.h index bbbae2a9..7ebd883c 100644 --- a/src/asio_io_service_pool.h +++ b/src/asio_io_service_pool.h @@ -34,8 +34,8 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef HTTP_SERVER2_IO_SERVICE_POOL_HPP -#define HTTP_SERVER2_IO_SERVICE_POOL_HPP +#ifndef ASIO_IO_SERVICE_POOL_H +#define ASIO_IO_SERVICE_POOL_H #include "nghttp2_config.h" @@ -45,14 +45,12 @@ #include #include -#include +#include namespace nghttp2 { namespace asio_http2 { -namespace server { - /// A pool of io_service objects. class io_service_pool : private boost::noncopyable { public: @@ -79,10 +77,8 @@ private: std::size_t next_io_service_; }; -} // namespace server - } // namespace asio_http2 } // namespace nghttp2 -#endif // HTTP_SERVER2_IO_SERVICE_POOL_HPP +#endif // ASIO_IO_SERVICE_POOL_H diff --git a/src/asio_server.cc b/src/asio_server.cc index 5b774ca0..e19435d2 100644 --- a/src/asio_server.cc +++ b/src/asio_server.cc @@ -38,6 +38,9 @@ #include +#include "asio_server_connection.h" +#include "util.h" + namespace nghttp2 { namespace asio_http2 { namespace server { diff --git a/src/asio_server.h b/src/asio_server.h index 36c4cb3a..533ce2da 100644 --- a/src/asio_server.h +++ b/src/asio_server.h @@ -34,8 +34,8 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef HTTP_SERVER2_SERVER_HPP -#define HTTP_SERVER2_SERVER_HPP +#ifndef ASIO_SERVER_H +#define ASIO_SERVER_H #include "nghttp2_config.h" @@ -47,7 +47,6 @@ #include -#include "asio_connection.h" #include "asio_io_service_pool.h" namespace nghttp2 { @@ -99,4 +98,4 @@ private: } // namespace nghttp2 -#endif // HTTP_SERVER2_SERVER_HPP +#endif // ASIO_SERVER_H diff --git a/src/asio_connection.h b/src/asio_server_connection.h similarity index 97% rename from src/asio_connection.h rename to src/asio_server_connection.h index b1f267c1..5ce48d92 100644 --- a/src/asio_connection.h +++ b/src/asio_server_connection.h @@ -34,8 +34,8 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef HTTP_SERVER2_CONNECTION_HPP -#define HTTP_SERVER2_CONNECTION_HPP +#ifndef ASIO_SERVER_CONNECTION_H +#define ASIO_SERVER_CONNECTION_H #include "nghttp2_config.h" @@ -46,7 +46,7 @@ #include -#include "asio_http2_handler.h" +#include "asio_server_http2_handler.h" #include "asio_server_serve_mux.h" #include "util.h" @@ -166,4 +166,4 @@ private: } // namespace nghttp2 -#endif // HTTP_SERVER2_CONNECTION_HPP +#endif // ASIO_SERVER_CONNECTION_H diff --git a/src/asio_http2_handler.cc b/src/asio_server_http2_handler.cc similarity index 70% rename from src/asio_http2_handler.cc rename to src/asio_server_http2_handler.cc index a07fcb5d..cd53c0f2 100644 --- a/src/asio_http2_handler.cc +++ b/src/asio_server_http2_handler.cc @@ -22,12 +22,15 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "asio_http2_handler.h" +#include "asio_server_http2_handler.h" #include #include "asio_common.h" #include "asio_server_serve_mux.h" +#include "asio_server_stream.h" +#include "asio_server_request_impl.h" +#include "asio_server_response_impl.h" #include "http2.h" #include "util.h" #include "template.h" @@ -40,198 +43,6 @@ namespace server { extern std::shared_ptr cached_date; -request::request() : impl_(make_unique()) {} - -const header_map &request::header() const { return impl_->header(); } - -const std::string &request::method() const { return impl_->method(); } - -const uri_ref &request::uri() const { return impl_->uri(); } - -void request::on_data(data_cb cb) const { - return impl_->on_data(std::move(cb)); -} - -request_impl &request::impl() const { return *impl_; } - -response::response() : impl_(make_unique()) {} - -void response::write_head(unsigned int status_code, header_map h) const { - impl_->write_head(status_code, std::move(h)); -} - -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::on_close(close_cb cb) const { impl_->on_close(std::move(cb)); } - -void response::cancel(uint32_t error_code) const { impl_->cancel(error_code); } - -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(); } - -boost::asio::io_service &response::io_service() const { - return impl_->io_service(); -} - -bool response::started() const { return impl_->started(); } - -response_impl &response::impl() const { return *impl_; } - -request_impl::request_impl() : strm_(nullptr) {} - -const header_map &request_impl::header() const { return header_; } - -const std::string &request_impl::method() const { return method_; } - -const uri_ref &request_impl::uri() const { return uri_; } - -uri_ref &request_impl::uri() { return uri_; } - -void request_impl::header(header_map h) { header_ = std::move(h); } - -header_map &request_impl::header() { return header_; } - -void request_impl::method(std::string arg) { method_ = std::move(arg); } - -void request_impl::on_data(data_cb cb) { on_data_cb_ = std::move(cb); } - -void request_impl::stream(class stream *s) { strm_ = s; } - -void request_impl::call_on_data(const uint8_t *data, std::size_t len) { - if (on_data_cb_) { - on_data_cb_(data, len); - } -} - -response_impl::response_impl() - : strm_(nullptr), status_code_(200), started_(false), pushed_(false), - push_promise_sent_(false) {} - -unsigned int response_impl::status_code() const { return status_code_; } - -void response_impl::write_head(unsigned int status_code, header_map h) { - status_code_ = status_code; - header_ = std::move(h); -} - -void response_impl::end(std::string data) { - if (started_) { - return; - } - - end(string_reader(std::move(data))); -} - -void response_impl::end(read_cb cb) { - if (started_) { - return; - } - - read_cb_ = std::move(cb); - started_ = true; - - start_response(); -} - -void response_impl::on_close(close_cb cb) { close_cb_ = std::move(cb); } - -void response_impl::call_on_close(uint32_t error_code) { - if (close_cb_) { - close_cb_(error_code); - } -} - -void response_impl::cancel(uint32_t error_code) { - auto handler = strm_->handler(); - - handler->stream_error(strm_->get_stream_id(), error_code); - - if (!handler->inside_callback()) { - handler->initiate_write(); - } -} - -void response_impl::start_response() { - if (!started_ || (pushed_ && !push_promise_sent_)) { - return; - } - - auto handler = strm_->handler(); - - if (handler->start_response(*strm_) != 0) { - handler->stream_error(strm_->get_stream_id(), NGHTTP2_INTERNAL_ERROR); - return; - } - - if (!handler->inside_callback()) { - handler->initiate_write(); - } -} - -response *response_impl::push(boost::system::error_code &ec, std::string method, - std::string raw_path_query, header_map h) const { - auto handler = strm_->handler(); - return handler->push_promise(ec, *strm_, std::move(method), - std::move(raw_path_query), std::move(h)); -} - -void response_impl::resume() { - auto handler = strm_->handler(); - handler->resume(*strm_); - - if (!handler->inside_callback()) { - handler->initiate_write(); - } -} - -boost::asio::io_service &response_impl::io_service() { - return strm_->handler()->io_service(); -} - -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(class stream *s) { strm_ = s; } - -read_cb::result_type response_impl::call_read(uint8_t *data, std::size_t len, - uint32_t *data_flags) { - if (read_cb_) { - return read_cb_(data, len, data_flags); - } - - *data_flags |= NGHTTP2_DATA_FLAG_EOF; - - return 0; -} - -stream::stream(http2_handler *h, int32_t stream_id) - : handler_(h), stream_id_(stream_id) { - request_.impl().stream(this); - response_.impl().stream(this); -} - -int32_t stream::get_stream_id() const { return stream_id_; } - -request &stream::request() { return request_; } - -response &stream::response() { return response_; } - -http2_handler *stream::handler() const { return handler_; } - namespace { int stream_error(nghttp2_session *session, int32_t stream_id, uint32_t error_code) { diff --git a/src/asio_http2_handler.h b/src/asio_server_http2_handler.h similarity index 63% rename from src/asio_http2_handler.h rename to src/asio_server_http2_handler.h index 3ebc47aa..bc8f5507 100644 --- a/src/asio_http2_handler.h +++ b/src/asio_server_http2_handler.h @@ -22,13 +22,12 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef HTTP2_HANDLER_H -#define HTTP2_HANDLER_H +#ifndef ASIO_SERVER_HTTP2_HANDLER_H +#define ASIO_SERVER_HTTP2_HANDLER_H #include "nghttp2_config.h" #include -#include #include #include @@ -44,100 +43,13 @@ class http2_handler; class stream; class serve_mux; -class request_impl { -public: - request_impl(); - - void header(header_map h); - const header_map &header() const; - header_map &header(); - - void method(std::string method); - const std::string &method() const; - - const uri_ref &uri() const; - uri_ref &uri(); - - void on_data(data_cb cb); - - void stream(class stream *s); - void call_on_data(const uint8_t *data, std::size_t len); - -private: - class stream *strm_; - header_map header_; - std::string method_; - uri_ref uri_; - data_cb on_data_cb_; -}; - -class response_impl { -public: - response_impl(); - void write_head(unsigned int status_code, header_map h = {}); - void end(std::string data = ""); - void end(read_cb cb); - void on_close(close_cb cb); - void resume(); - - void cancel(uint32_t error_code); - - response *push(boost::system::error_code &ec, std::string method, - std::string raw_path_query, header_map h = {}) const; - - boost::asio::io_service &io_service(); - - 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(class stream *s); - read_cb::result_type call_read(uint8_t *data, std::size_t len, - uint32_t *data_flags); - void call_on_close(uint32_t error_code); - -private: - class stream *strm_; - header_map header_; - read_cb read_cb_; - close_cb close_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 stream { -public: - stream(http2_handler *h, int32_t stream_id); - - int32_t get_stream_id() const; - request &request(); - response &response(); - - http2_handler *handler() const; - -private: - http2_handler *handler_; - class request request_; - class response response_; - int32_t stream_id_; -}; - struct callback_guard { callback_guard(http2_handler &h); ~callback_guard(); http2_handler &handler; }; -typedef std::function connection_write; +using connection_write = std::function; class http2_handler : public std::enable_shared_from_this { public: @@ -245,4 +157,4 @@ private: } // namespace asio_http2 } // namespace nghttp -#endif // HTTP2_HANDLER_H +#endif // ASIO_SERVER_HTTP2_HANDLER_H diff --git a/src/asio_http2_impl.cc b/src/asio_server_http2_impl.cc similarity index 79% rename from src/asio_http2_impl.cc rename to src/asio_server_http2_impl.cc index dfb8e36c..6e00b507 100644 --- a/src/asio_http2_impl.cc +++ b/src/asio_server_http2_impl.cc @@ -22,7 +22,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "asio_http2_impl.h" +#include "asio_server_http2_impl.h" #include @@ -127,50 +127,6 @@ bool http2_impl::handle(std::string pattern, request_cb cb) { } // namespace server -template -std::shared_ptr> defer_shared(F &&f, T &&... t) { - return std::make_shared>(std::forward(f), - std::forward(t)...); -} - -read_cb file_reader(const std::string &path) { - auto fd = open(path.c_str(), O_RDONLY); - if (fd == -1) { - return read_cb(); - } - - return file_reader_from_fd(fd); -} - -read_cb file_reader_from_fd(int fd) { - auto d = defer_shared(close, fd); - - return [fd, d](uint8_t *buf, size_t len, uint32_t *data_flags) - -> read_cb::result_type { - ssize_t n; - while ((n = read(fd, buf, len)) == -1 && errno == EINTR) - ; - - if (n == -1) { - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; - } - - if (n == 0) { - *data_flags |= NGHTTP2_DATA_FLAG_EOF; - } - - return n; - }; -} - -bool check_path(const std::string &path) { return util::check_path(path); } - -std::string percent_decode(const std::string &s) { - return util::percentDecode(std::begin(s), std::end(s)); -} - -std::string http_date(int64_t t) { return util::http_date(t); } - } // namespace asio_http2 } // namespace nghttp2 diff --git a/src/asio_http2_impl.h b/src/asio_server_http2_impl.h similarity index 94% rename from src/asio_http2_impl.h rename to src/asio_server_http2_impl.h index 975b883e..5c5494a5 100644 --- a/src/asio_http2_impl.h +++ b/src/asio_server_http2_impl.h @@ -22,8 +22,8 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef ASIO_HTTP2_IMPL_H -#define ASIO_HTTP2_IMPL_H +#ifndef ASIO_SERVER_HTTP2_IMPL_H +#define ASIO_SERVER_HTTP2_IMPL_H #include "nghttp2_config.h" @@ -63,4 +63,4 @@ private: } // namespace nghttp2 -#endif // ASIO_HTTP2_IMPL_H +#endif // ASIO_SERVER_HTTP2_IMPL_H diff --git a/src/asio_server_request.cc b/src/asio_server_request.cc new file mode 100644 index 00000000..1dfc8bac --- /dev/null +++ b/src/asio_server_request.cc @@ -0,0 +1,53 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2015 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "nghttp2_config.h" + +#include + +#include "asio_server_request_impl.h" + +#include "template.h" + +namespace nghttp2 { +namespace asio_http2 { +namespace server { + +request::request() : impl_(make_unique()) {} + +const header_map &request::header() const { return impl_->header(); } + +const std::string &request::method() const { return impl_->method(); } + +const uri_ref &request::uri() const { return impl_->uri(); } + +void request::on_data(data_cb cb) const { + return impl_->on_data(std::move(cb)); +} + +request_impl &request::impl() const { return *impl_; } + +} // namespace server +} // namespace asio_http2 +} // namespace nghttp2 diff --git a/src/asio_server_request_impl.cc b/src/asio_server_request_impl.cc new file mode 100644 index 00000000..3a78208f --- /dev/null +++ b/src/asio_server_request_impl.cc @@ -0,0 +1,59 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2015 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "asio_server_request_impl.h" + +namespace nghttp2 { +namespace asio_http2 { +namespace server { + +request_impl::request_impl() : strm_(nullptr) {} + +const header_map &request_impl::header() const { return header_; } + +const std::string &request_impl::method() const { return method_; } + +const uri_ref &request_impl::uri() const { return uri_; } + +uri_ref &request_impl::uri() { return uri_; } + +void request_impl::header(header_map h) { header_ = std::move(h); } + +header_map &request_impl::header() { return header_; } + +void request_impl::method(std::string arg) { method_ = std::move(arg); } + +void request_impl::on_data(data_cb cb) { on_data_cb_ = std::move(cb); } + +void request_impl::stream(class stream *s) { strm_ = s; } + +void request_impl::call_on_data(const uint8_t *data, std::size_t len) { + if (on_data_cb_) { + on_data_cb_(data, len); + } +} + +} // namespace server +} // namespace asio_http2 +} // namespace nghttp2 diff --git a/src/asio_server_request_impl.h b/src/asio_server_request_impl.h new file mode 100644 index 00000000..8d4b0149 --- /dev/null +++ b/src/asio_server_request_impl.h @@ -0,0 +1,69 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2015 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef ASIO_SERVER_REQUEST_IMPL_H +#define ASIO_SERVER_REQUEST_IMPL_H + +#include "nghttp2_config.h" + +#include + +namespace nghttp2 { +namespace asio_http2 { +namespace server { + +class stream; + +class request_impl { +public: + request_impl(); + + void header(header_map h); + const header_map &header() const; + header_map &header(); + + void method(std::string method); + const std::string &method() const; + + const uri_ref &uri() const; + uri_ref &uri(); + + void on_data(data_cb cb); + + void stream(class stream *s); + void call_on_data(const uint8_t *data, std::size_t len); + +private: + class stream *strm_; + header_map header_; + std::string method_; + uri_ref uri_; + data_cb on_data_cb_; +}; + +} // namespace server +} // namespace asio_http2 +} // namespace nghttp2 + +#endif // ASIO_SERVER_REQUEST_IMPL_H diff --git a/src/asio_server_response.cc b/src/asio_server_response.cc new file mode 100644 index 00000000..59895ef9 --- /dev/null +++ b/src/asio_server_response.cc @@ -0,0 +1,71 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2015 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "nghttp2_config.h" + +#include + +#include "asio_server_response_impl.h" + +#include "template.h" + +namespace nghttp2 { +namespace asio_http2 { +namespace server { + +response::response() : impl_(make_unique()) {} + +void response::write_head(unsigned int status_code, header_map h) const { + impl_->write_head(status_code, std::move(h)); +} + +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::on_close(close_cb cb) const { impl_->on_close(std::move(cb)); } + +void response::cancel(uint32_t error_code) const { impl_->cancel(error_code); } + +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(); } + +boost::asio::io_service &response::io_service() const { + return impl_->io_service(); +} + +bool response::started() const { return impl_->started(); } + +response_impl &response::impl() const { return *impl_; } + +} // namespace server +} // namespace asio_http2 +} // namespace nghttp2 diff --git a/src/asio_server_response_impl.cc b/src/asio_server_response_impl.cc new file mode 100644 index 00000000..a535aba3 --- /dev/null +++ b/src/asio_server_response_impl.cc @@ -0,0 +1,143 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2015 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "asio_server_response_impl.h" + +#include "asio_server_stream.h" +#include "asio_server_http2_handler.h" +#include "asio_common.h" + +namespace nghttp2 { +namespace asio_http2 { +namespace server { + +response_impl::response_impl() + : strm_(nullptr), status_code_(200), started_(false), pushed_(false), + push_promise_sent_(false) {} + +unsigned int response_impl::status_code() const { return status_code_; } + +void response_impl::write_head(unsigned int status_code, header_map h) { + status_code_ = status_code; + header_ = std::move(h); +} + +void response_impl::end(std::string data) { + if (started_) { + return; + } + + end(string_reader(std::move(data))); +} + +void response_impl::end(read_cb cb) { + if (started_) { + return; + } + + read_cb_ = std::move(cb); + started_ = true; + + start_response(); +} + +void response_impl::on_close(close_cb cb) { close_cb_ = std::move(cb); } + +void response_impl::call_on_close(uint32_t error_code) { + if (close_cb_) { + close_cb_(error_code); + } +} + +void response_impl::cancel(uint32_t error_code) { + auto handler = strm_->handler(); + + handler->stream_error(strm_->get_stream_id(), error_code); + + if (!handler->inside_callback()) { + handler->initiate_write(); + } +} + +void response_impl::start_response() { + if (!started_ || (pushed_ && !push_promise_sent_)) { + return; + } + + auto handler = strm_->handler(); + + if (handler->start_response(*strm_) != 0) { + handler->stream_error(strm_->get_stream_id(), NGHTTP2_INTERNAL_ERROR); + return; + } + + if (!handler->inside_callback()) { + handler->initiate_write(); + } +} + +response *response_impl::push(boost::system::error_code &ec, std::string method, + std::string raw_path_query, header_map h) const { + auto handler = strm_->handler(); + return handler->push_promise(ec, *strm_, std::move(method), + std::move(raw_path_query), std::move(h)); +} + +void response_impl::resume() { + auto handler = strm_->handler(); + handler->resume(*strm_); + + if (!handler->inside_callback()) { + handler->initiate_write(); + } +} + +boost::asio::io_service &response_impl::io_service() { + return strm_->handler()->io_service(); +} + +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(class stream *s) { strm_ = s; } + +read_cb::result_type response_impl::call_read(uint8_t *data, std::size_t len, + uint32_t *data_flags) { + if (read_cb_) { + return read_cb_(data, len, data_flags); + } + + *data_flags |= NGHTTP2_DATA_FLAG_EOF; + + return 0; +} + +} // namespace server +} // namespace asio_http2 +} // namespace nghttp2 diff --git a/src/asio_server_response_impl.h b/src/asio_server_response_impl.h new file mode 100644 index 00000000..5e1246ff --- /dev/null +++ b/src/asio_server_response_impl.h @@ -0,0 +1,85 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2015 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef ASIO_SERVER_RESPONSE_IMPL_H +#define ASIO_SERVER_RESPONSE_IMPL_H + +#include "nghttp2_config.h" + +#include + +namespace nghttp2 { +namespace asio_http2 { +namespace server { + +class stream; + +class response_impl { +public: + response_impl(); + void write_head(unsigned int status_code, header_map h = {}); + void end(std::string data = ""); + void end(read_cb cb); + void on_close(close_cb cb); + void resume(); + + void cancel(uint32_t error_code); + + response *push(boost::system::error_code &ec, std::string method, + std::string raw_path_query, header_map h = {}) const; + + boost::asio::io_service &io_service(); + + 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(class stream *s); + read_cb::result_type call_read(uint8_t *data, std::size_t len, + uint32_t *data_flags); + void call_on_close(uint32_t error_code); + +private: + class stream *strm_; + header_map header_; + read_cb read_cb_; + close_cb close_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_; +}; + +} // namespace server +} // namespace asio_http2 +} // namespace nghttp2 + +#endif // ASIO_SERVER_RESPONSE_IMPL_H diff --git a/src/asio_server_serve_mux.cc b/src/asio_server_serve_mux.cc index 52c7f73d..c77a4f38 100644 --- a/src/asio_server_serve_mux.cc +++ b/src/asio_server_serve_mux.cc @@ -24,7 +24,7 @@ */ #include "asio_server_serve_mux.h" -#include "asio_http2_handler.h" +#include "asio_server_request_impl.h" #include "util.h" #include "http2.h" diff --git a/src/asio_server_stream.cc b/src/asio_server_stream.cc new file mode 100644 index 00000000..216fabe0 --- /dev/null +++ b/src/asio_server_stream.cc @@ -0,0 +1,51 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2015 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "asio_server_stream.h" + +#include "asio_server_http2_handler.h" +#include "asio_server_request_impl.h" +#include "asio_server_response_impl.h" + +namespace nghttp2 { +namespace asio_http2 { +namespace server { + +stream::stream(http2_handler *h, int32_t stream_id) + : handler_(h), stream_id_(stream_id) { + request_.impl().stream(this); + response_.impl().stream(this); +} + +int32_t stream::get_stream_id() const { return stream_id_; } + +request &stream::request() { return request_; } + +response &stream::response() { return response_; } + +http2_handler *stream::handler() const { return handler_; } + +} // namespace server +} // namespace asio_http2 +} // namespace nghttp2 diff --git a/src/asio_server_stream.h b/src/asio_server_stream.h new file mode 100644 index 00000000..e9dab447 --- /dev/null +++ b/src/asio_server_stream.h @@ -0,0 +1,59 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2015 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef ASIO_SERVER_STREAM_H +#define ASIO_SERVER_STREAM_H + +#include "nghttp2_config.h" + +#include + +namespace nghttp2 { +namespace asio_http2 { +namespace server { + +class http2_handler; + +class stream { +public: + stream(http2_handler *h, int32_t stream_id); + + int32_t get_stream_id() const; + request &request(); + response &response(); + + http2_handler *handler() const; + +private: + http2_handler *handler_; + class request request_; + class response response_; + int32_t stream_id_; +}; + +} // namespace server +} // namespace asio_http2 +} // namespace nghttp2 + +#endif // ASIO_SERVER_STREAM_H