diff --git a/.gitignore b/.gitignore index e6d440e03..ae6362ad2 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ _build build/ libs/network/doc/doxygen/ .DS_Store +*.swo diff --git a/boost/network/protocol/http/server.hpp b/boost/network/protocol/http/server.hpp index 386901c13..b70381fa6 100644 --- a/boost/network/protocol/http/server.hpp +++ b/boost/network/protocol/http/server.hpp @@ -12,37 +12,35 @@ #include #include -#include #include namespace boost { namespace network { namespace http { -template -struct server_base { - typedef unsupported_tag type; -}; - -template -struct server_base >::type> { - typedef async_server_base type; -}; - -template -struct server_base >::type> { - typedef sync_server_base type; -}; - -template -struct basic_server : server_base::type {}; - +/** + * The main HTTP Server template implementing an asynchronous HTTP service. + * + * Usage Example: + * \code{.cpp} + * handler_type handler; + * http_server::options options(handler); + * options.thread_pool( + * std::make_shared()); + * http_server server(options.address("localhost").port("8000")); + * \endcode + * + */ template -struct server : server_base::type { - typedef typename server_base::type server_base; +struct server : async_server_base { + /// A convenience typedef for the base of this type, implementing most of + /// the internal details. + typedef async_server_base server_base; + + /// The options supported by the server. typedef server_options options; - explicit server(options const &options) : server_base(options) {} + using server_base::server_base; }; } // namespace http diff --git a/boost/network/protocol/http/server/async_connection.hpp b/boost/network/protocol/http/server/async_connection.hpp index 0c259f9cc..e5c361ab6 100644 --- a/boost/network/protocol/http/server/async_connection.hpp +++ b/boost/network/protocol/http/server/async_connection.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -35,16 +36,17 @@ #include #ifndef BOOST_NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE -/** Here we define a page's worth of header connection buffer data. - * This can be tuned to reduce the memory cost of connections, but this - * default size is set to be friendly to typical service applications. - * This is the maximum size though and Boost.Asio's internal representation - * of a streambuf would make appropriate decisions on how big a buffer - * is to begin with. +/** + * Here we define a page's worth of header connection buffer data. + * This can be tuned to reduce the memory cost of connections, but this + * default size is set to be friendly to typical service applications. + * This is the maximum size though and Boost.Asio's internal representation + * of a streambuf would make appropriate decisions on how big a buffer + * is to begin with. * - * This kinda assumes that a page is by default 4096. Since we're using - * the default allocator with the static buffers, it's not guaranteed that - * the static buffers will be page-aligned when they are allocated. + * This kinda assumes that a page is by default 4096. Since we're using + * the default allocator with the static buffers, it's not guaranteed that + * the static buffers will be page-aligned when they are allocated. */ #define BOOST_NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE 4096 #endif /* BOOST_NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE */ @@ -61,17 +63,15 @@ namespace boost { namespace network { namespace http { -#ifndef BOOST_NETWORK_NO_LIB extern void parse_version(std::string const& partial_parsed, std::tuple& version_pair); extern void parse_headers(std::string const& input, std::vector& container); -#endif template struct async_connection : std::enable_shared_from_this > { - + /// The set of known status codes for HTTP server responses. enum status_t { ok = 200, created = 201, @@ -100,6 +100,8 @@ struct async_connection typedef typename string::type string_type; typedef basic_request request; + + /// The connection pointer type. typedef std::shared_ptr connection_ptr; private: @@ -180,10 +182,10 @@ struct async_connection } public: - async_connection(asio::io_service& io_service, Handler& handler, - utils::thread_pool& thread_pool, - std::shared_ptr ctx = - std::shared_ptr()) + async_connection( + asio::io_service& io_service, Handler& handler, + utils::thread_pool& thread_pool, + std::shared_ptr ctx = std::shared_ptr()) : strand(io_service), handler(handler), thread_pool_(thread_pool), @@ -207,17 +209,16 @@ struct async_connection socket_.shutdown(asio::ip::tcp::socket::shutdown_receive, ignored); } - /** Function: template set_headers(Range headers) - * Precondition: headers have not been sent yet - * Postcondition: headers have been linearized to a buffer, - * and assumed to have been sent already when the - *function exits - * Throws: std::logic_error in case the headers have already been sent. + /** + * A call to set_headers takes a Range where each element models the Header + * concept. This Range will be linearized onto a buffer, which is then sent + * as soon as the first call to `write` or `flush` commences. * - * A call to set_headers takes a Range where each element models the - * Header concept. This Range will be linearized onto a buffer, which - *is - * then sent as soon as the first call to `write` or `flush` commences. + * @param[in] headers A range of Header objects to write out. + * @pre Headers have not been sent yet. + * @post Headers have been linearized to a buffer, and assumed to have been + * sent already when the function exits. + * @throw std::logic_error when the precondition is violated. */ template void set_headers(Range headers) { @@ -249,6 +250,14 @@ struct async_connection write_headers_only([self] {}); } + /** + * Sets the status of the response. + * + * @param[in] new_status The new status for this response. + * @pre Headers have not been sent. + * @post Status is set on the response. + * @throw std::logic_error when the precondition is violated. + */ void set_status(status_t new_status) { lock_guard lock(headers_mutex); if (headers_already_sent) @@ -260,33 +269,78 @@ struct async_connection status = new_status; } + /** + * Writes a given range of bytes out in order. + * + * Even though this function looks synchronous, all it does is schedules + * asynchronous writes to the connection as soon as the range is serialised + * into appropriately sized buffers. + * + * To use in your handler, it would look like: + * + * Example: + * \code{.cpp} + * connection->write("Hello, world!\n"); + * std::string sample = "I have a string!"; + * connection->write(sample); + * \endcode + * + * Note that if you want to send custom status and headers, you MUST call + * set_status and/or set_headers before any calls to write. + * + * @param[in] range A Boost.Range ``Single Pass Range`` of char's for writing. + * @throw std::system_error The encountered underlying error in previous + * operations. + * @post Status and headers have been sent, contents in the range have been + * serialized. + */ template void write(Range const& range) { lock_guard lock(headers_mutex); if (error_encountered) boost::throw_exception(std::system_error(*error_encountered)); auto self = this->shared_from_this(); - auto f = [this, self](std::error_code ec) { - this->default_error(ec); - }; + auto f = [this, self](std::error_code ec) { this->default_error(ec); }; write_impl(boost::make_iterator_range(range), f); } + /** + * Writes a given range out and schedules a completion callback to be invoked + * when the writes are done. This works similarly to write above. + * + * This overload is useful for writing streaming applications that send out + * chunks of data at a time, or for writing data that may not all fit in + * memory at once. + * + * @param[in] range A Boost.Range ``Single Pass Range`` of char's for writing. + * @param[in] callback A function of type `void(std::error_code)`. + * @throw std::system_error The encountered underlying error in previous + * operations. + * @post Status and headers have been sent, contents in the range have been + * serialized and scheduled for writing through the socket. + */ template typename disable_if< is_base_of, void>::type - write(Range const& range, Callback const& callback) { + write(Range const& range, Callback const& callback) { lock_guard lock(headers_mutex); if (error_encountered) boost::throw_exception(std::system_error(*error_encountered)); write_impl(boost::make_iterator_range(range), callback); } + /** + * Writes a given set of `asio::const_buffer`s out using a more efficient + * implementation. + * + * @param[in] seq A sequence of `asio::const_buffer` objects. + * @param[in] callback A function of type `void(std::error_code)`. + */ template typename enable_if< is_base_of, void>::type - write(ConstBufferSeq const& seq, Callback const& callback) { + write(ConstBufferSeq const& seq, Callback const& callback) { write_vec_impl(seq, callback, shared_array_list(), shared_buffers()); } @@ -295,11 +349,30 @@ struct async_connection buffer_type; public: + /// The input range taken by ``read`` callbacks. Typically a range of + /// ``char``s. typedef iterator_range input_range; - typedef std::function< - void(input_range, std::error_code, std::size_t, connection_ptr)> - read_callback_function; + /// Type required for ``read`` callbacks. Takes an input range, an error + /// code, the number of bytes read, and a connection pointer. + typedef std::function read_callback_function; + + /** + * Schedules an asynchronous read from the connection. This is generally + * useful for handling POST/PUT or other requests that may have data coming + * in through the HTTP request's body in a streaming manner. + * + * To use this function, the caller needs to provide a callback that handles + * a chunk of data at a time. The signature of the function (lambda or actual + * function pointer) should be of the following form: + * + * void(input_range, error_code, size_t, connection_ptr) + * + * @param[in] callback Invoked when the read has data ready for processing. + * @throw std::system_error The underlying error encountered in previous + * operations. + */ void read(read_callback_function callback) { if (error_encountered) boost::throw_exception(std::system_error(*error_encountered)); @@ -316,17 +389,24 @@ struct async_connection } auto self = this->shared_from_this(); - socket().async_read_some( - asio::buffer(read_buffer_), - strand.wrap([this, self, callback](std::error_code ec, - size_t bytes_transferred) { - callback(ec, bytes_transferred); - })); + socket().async_read_some(asio::buffer(read_buffer_), + strand.wrap([this, self, callback]( + std::error_code ec, size_t bytes_transferred) { + callback(ec, bytes_transferred); + })); } + /// Returns a reference to the underlying socket. boost::network::stream_handler& socket() { return socket_; } + + /// Returns a reference to the thread_pool running this handler. utils::thread_pool& thread_pool() { return thread_pool_; } + + /// Returns whether or not there were errors encountered in previous + /// operations. bool has_error() { return (!!error_encountered); } + + /// Returns the most recent error encountered. optional error() { return error_encountered; } private: @@ -378,12 +458,7 @@ struct async_connection template friend struct async_server_base; - enum state_t { - method, - uri, - version, - headers - }; + enum state_t { method, uri, version, headers }; void start() { typename ostringstream::type ip_stream; @@ -397,11 +472,10 @@ struct async_connection auto self = this->shared_from_this(); #ifdef BOOST_NETWORK_ENABLE_HTTPS if (socket_.is_ssl_enabled() && !handshake_done) { - socket_.async_handshake( - asio::ssl::stream_base::server, - [this, self, state](std::error_code ec) { - handle_handshake(ec, state); - }); + socket_.async_handshake(asio::ssl::stream_base::server, + [this, self, state](std::error_code ec) { + handle_handshake(ec, state); + }); } else { #endif socket_.async_read_some( @@ -530,11 +604,11 @@ struct async_connection "text/plain\r\nContent-Length: 12\r\n\r\nBad Request."; auto self = this->shared_from_this(); - asio::async_write(socket(), asio::buffer(bad_request, strlen(bad_request)), - strand.wrap([this, self](std::error_code ec, - size_t bytes_transferred) { - client_error_sent(ec, bytes_transferred); - })); + asio::async_write( + socket(), asio::buffer(bad_request, strlen(bad_request)), + strand.wrap([this, self](std::error_code ec, size_t bytes_transferred) { + client_error_sent(ec, bytes_transferred); + })); } void client_error_sent(std::error_code const& ec, std::size_t) { @@ -551,11 +625,11 @@ struct async_connection if (headers_in_progress) return; headers_in_progress = true; auto self = this->shared_from_this(); - asio::async_write( - socket(), headers_buffer, - strand.wrap([this, self, callback] (std::error_code ec, size_t bytes_transferred) { - handle_write_headers(callback, ec, bytes_transferred); - })); + asio::async_write(socket(), headers_buffer, + strand.wrap([this, self, callback]( + std::error_code ec, size_t bytes_transferred) { + handle_write_headers(callback, ec, bytes_transferred); + })); } void handle_write_headers(std::function callback, @@ -575,17 +649,15 @@ struct async_connection } } - void handle_write( - std::function callback, - shared_array_list, shared_buffers, std::error_code const& ec, - std::size_t) { + void handle_write(std::function callback, + shared_array_list, shared_buffers, + std::error_code const& ec, std::size_t) { // we want to forget the temporaries and buffers thread_pool().post([callback, ec] { callback(ec); }); } template - void write_impl(Range range, - std::function callback) { + void write_impl(Range range, std::function callback) { // linearize the whole range into a vector // of fixed-sized buffers, then schedule an asynchronous // write of these buffers -- make sure they are live @@ -645,11 +717,11 @@ struct async_connection pending_actions.push_back(continuation); return; } - asio::async_write(socket_, seq, [this, self, callback, temporaries, - buffers](std::error_code ec, - size_t bytes_transferred) { - handle_write(callback, temporaries, buffers, ec, bytes_transferred); - }); + asio::async_write( + socket_, seq, [this, self, callback, temporaries, buffers]( + std::error_code ec, size_t bytes_transferred) { + handle_write(callback, temporaries, buffers, ec, bytes_transferred); + }); } void handle_handshake(const std::error_code& ec, state_t state) { diff --git a/boost/network/protocol/http/server/async_server.hpp b/boost/network/protocol/http/server/async_server.hpp index f3d665d51..954e0a5c3 100644 --- a/boost/network/protocol/http/server/async_server.hpp +++ b/boost/network/protocol/http/server/async_server.hpp @@ -21,15 +21,21 @@ namespace http { template struct async_server_base : server_storage_base, socket_options_base { + /// The request type for this server. typedef basic_request request; - typedef basic_response response; typedef typename string::type string_type; - typedef typename boost::network::http::response_header::type - response_header; + + /// The header type for this server. + typedef + typename boost::network::http::response_header::type response_header; + + /// The connection type for this server. typedef async_connection connection; + + /// Defines the type for the connection pointer. typedef std::shared_ptr connection_ptr; - typedef std::unique_lock scoped_mutex_lock; + /// Constructs and initializes the asynchronous server core. explicit async_server_base(server_options const &options) : server_storage_base(options), socket_options_base(options), @@ -47,11 +53,31 @@ struct async_server_base : server_storage_base, socket_options_base { listening(false), ctx_(options.context()) {} + /** + * Listens to the correct port and runs the server's event loop. This can be + * run on multiple threads, as in the example below: + * + * Example: + * handler_type handler; + * http_server::options options(handler); + * options.thread_pool( + * std::make_shared()); + * http_server server(options.address("localhost").port("8000")); + * + * // Run in three threads including the current thread. + * std::thread t1([&server] { server.run() }); + * std::thread t2([&server] { server.run() }); + * server.run(); + * t1.join(); + * t2.join(); + */ void run() { listen(); service_.run(); }; + /// Stops the HTTP server acceptor and waits for all pending request handlers + /// to finish. void stop() { // stop accepting new requests and let all the existing // handlers finish. @@ -63,10 +89,12 @@ struct async_server_base : server_storage_base, socket_options_base { std::error_code ignored; acceptor.close(ignored); listening = false; - service_.post([this] () { this->handle_stop(); }); + service_.post([this]() { this->handle_stop(); }); } } + /// Explicitly listens on the configured host and port. May be called + /// multiple times but only takes effect once. void listen() { scoped_mutex_lock listening_lock(listening_mutex_); BOOST_NETWORK_MESSAGE("Listening on " << address_ << ':' << port_); @@ -81,6 +109,8 @@ struct async_server_base : server_storage_base, socket_options_base { } private: + typedef std::unique_lock scoped_mutex_lock; + Handler &handler; string_type address_, port_; std::shared_ptr thread_pool; @@ -126,7 +156,7 @@ struct async_server_base : server_storage_base, socket_options_base { #else new_connection->socket(), #endif - [this] (std::error_code const &ec) { this->handle_accept(ec); }); + [this](std::error_code const &ec) { this->handle_accept(ec); }); } void start_listening() { @@ -168,7 +198,7 @@ struct async_server_base : server_storage_base, socket_options_base { #else new_connection->socket(), #endif - [this] (std::error_code const &ec) { this->handle_accept(ec); }); + [this](std::error_code const &ec) { this->handle_accept(ec); }); listening = true; scoped_mutex_lock stopping_lock(stopping_mutex_); stopping = false; // if we were in the process of stopping, we revoke diff --git a/boost/network/protocol/http/server/options.hpp b/boost/network/protocol/http/server/options.hpp index a9db0e23c..d3d9f03a1 100644 --- a/boost/network/protocol/http/server/options.hpp +++ b/boost/network/protocol/http/server/options.hpp @@ -20,10 +20,15 @@ namespace boost { namespace network { namespace http { +/** + * The options supported by an HTTP Server's constructor. + */ template struct server_options { typedef typename string::type string_type; + /// A single-argument constructor that takes a Handler, and sets all options + /// to defaults. explicit server_options(Handler &handler) : io_service_(), handler_(handler), @@ -41,139 +46,186 @@ struct server_options { thread_pool_(), context_() {} - server_options(const server_options &other) - : io_service_(other.io_service()), - handler_(other.handler_), - address_(other.address_), - port_(other.port_), - reuse_address_(other.reuse_address_), - report_aborted_(other.report_aborted_), - non_blocking_io_(other.non_blocking_io_), - linger_(other.linger_), - linger_timeout_(0), - receive_buffer_size_(other.receive_buffer_size_), - send_buffer_size_(other.send_buffer_size_), - receive_low_watermark_(other.receive_low_watermark_), - send_low_watermark_(other.send_low_watermark_), - thread_pool_(other.thread_pool_), - context_(other.context_) {} - - server_options &operator=(server_options other) { - other.swap(*this); - return *this; - } + /// Disabled default constructor for the options class. + server_options() = delete; - void swap(server_options &other) { - using std::swap; - swap(io_service_, other.io_service_); - swap(address_, other.address_); - swap(port_, other.port_); - swap(reuse_address_, other.reuse_address_); - swap(report_aborted_, other.report_aborted_); - swap(non_blocking_io_, other.non_blocking_io_); - swap(linger_, other.linger_); - swap(linger_timeout_, other.linger_timeout_); - swap(receive_buffer_size_, other.receive_buffer_size_); - swap(send_buffer_size_, other.send_buffer_size_); - swap(receive_low_watermark_, other.receive_low_watermark_); - swap(send_low_watermark_, other.send_low_watermark_); - swap(thread_pool_, other.thread_pool_); - swap(context_, other.context_); - } + /// Copy constructor for the options class. + server_options(const server_options &) = default; + + /// Copy assignment for the options class. + server_options &operator=(const server_options &) = default; + + /// Move constructor for the options class. + server_options(server_options &&) = default; + + /// Move assignment for the options class. + server_options &operator=(server_options &&) = default; + /// Destructor for the options class. + ~server_options() = default; + + /// Sets the SSL context for the server. Default is nullptr. server_options &context(std::shared_ptr v) { context_ = v; return *this; } + + /// Provides an Asio io_service for the server. Default is nullptr. server_options &io_service(std::shared_ptr v) { io_service_ = v; return *this; } - server_options &address(string_type const &v) { - address_ = v; + + /// Sets the address to listen to for the server. Default is localhost. + server_options &address(string_type v) { + address_ = std::move(v); return *this; } + + /// Set the port to listen to for the server. Default is 80. server_options &port(string_type const &v) { port_ = v; return *this; } + + /// Set whether to reuse the address (SO_REUSE_ADDR). Default is false. server_options &reuse_address(bool v) { reuse_address_ = v; return *this; } + + /// Set whether to report aborted connections. Default is false. server_options &report_aborted(bool v) { report_aborted_ = v; return *this; } + + /// Set whether to use non-blocking IO. Default is true. server_options &non_blocking_io(bool v) { non_blocking_io_ = v; return *this; } + + /// Set whether sockets linger (SO_LINGER). Default is true. server_options &linger(bool v) { linger_ = v; return *this; } + + /// Set the linger timeout. Default is 0. server_options &linger_timeout(size_t v) { linger_timeout_ = v; return *this; } + + /// Set the socket receive buffer size. Unset by default. server_options &receive_buffer_size( asio::socket_base::receive_buffer_size v) { receive_buffer_size_ = v; return *this; } - server_options &send_buffer_size( - asio::socket_base::send_buffer_size v) { + + /// Set the send buffer size. Unset by default. + server_options &send_buffer_size(asio::socket_base::send_buffer_size v) { send_buffer_size_ = v; return *this; } + + /// Set the socket receive low watermark. Unset by default. server_options &receive_low_watermark( asio::socket_base::receive_low_watermark v) { receive_low_watermark_ = v; return *this; } - server_options &send_low_watermark( - asio::socket_base::send_low_watermark v) { + + /// Set the socket send low watermark. Unset by default. + server_options &send_low_watermark(asio::socket_base::send_low_watermark v) { send_low_watermark_ = v; return *this; } + + /// Set the thread-pool to use. Default is nullptr. server_options &thread_pool(std::shared_ptr v) { thread_pool_ = v; return *this; } - std::shared_ptr io_service() const { - return io_service_; - } + /// Returns the provided Asio io_service. + std::shared_ptr io_service() const { return io_service_; } + + /// Returns the address to listen on. string_type address() const { return address_; } + + /// Returns the port to listen on. string_type port() const { return port_; } + + /// Returns a reference to the provided handler. Handler &handler() const { return handler_; } + + /// Returns whether to reuse the address. bool reuse_address() const { return reuse_address_; } + + /// Returns whether to report aborted connections. bool report_aborted() const { return report_aborted_; } + + /// Returns whether to perform non-blocking IO. bool non_blocking_io() const { return non_blocking_io_; } + + /// Returns whether to linger. bool linger() const { return linger_; } + + /// Returns the linger timeout. size_t linger_timeout() const { return linger_timeout_; } - boost::optional - receive_buffer_size() const { + + /// Returns the optional receive buffer size. + boost::optional receive_buffer_size() + const { return receive_buffer_size_; } + + /// Returns the optional send buffer size. boost::optional send_buffer_size() const { return send_buffer_size_; } + + /// Returns the optional receive low watermark. boost::optional - receive_low_watermark() const { + receive_low_watermark() const { return receive_low_watermark_; } - boost::optional - send_low_watermark() const { + + /// Returns the optional send low watermark. + boost::optional send_low_watermark() + const { return send_low_watermark_; } + + /// Returns a pointer to the provided thread pool. std::shared_ptr thread_pool() const { return thread_pool_; } - std::shared_ptr context() const { - return context_; + + /// Returns a pointer to the provided context. + std::shared_ptr context() const { return context_; } + + /// Swap implementation for the server options. + void swap(server_options &other) { + using std::swap; + swap(io_service_, other.io_service_); + swap(address_, other.address_); + swap(port_, other.port_); + swap(reuse_address_, other.reuse_address_); + swap(report_aborted_, other.report_aborted_); + swap(non_blocking_io_, other.non_blocking_io_); + swap(linger_, other.linger_); + swap(linger_timeout_, other.linger_timeout_); + swap(receive_buffer_size_, other.receive_buffer_size_); + swap(send_buffer_size_, other.send_buffer_size_); + swap(receive_low_watermark_, other.receive_low_watermark_); + swap(send_low_watermark_, other.send_low_watermark_); + swap(thread_pool_, other.thread_pool_); + swap(context_, other.context_); } private: @@ -186,13 +238,11 @@ struct server_options { bool non_blocking_io_; bool linger_; size_t linger_timeout_; - boost::optional - receive_buffer_size_; + boost::optional receive_buffer_size_; boost::optional send_buffer_size_; boost::optional receive_low_watermark_; - boost::optional - send_low_watermark_; + boost::optional send_low_watermark_; std::shared_ptr thread_pool_; std::shared_ptr context_; }; diff --git a/boost/network/protocol/http/server/sync_connection.hpp b/boost/network/protocol/http/server/sync_connection.hpp deleted file mode 100644 index 969ce6bba..000000000 --- a/boost/network/protocol/http/server/sync_connection.hpp +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright 2009 (c) Dean Michael Berris -// Copyright 2009 (c) Tarroo, Inc. -// Adapted from Christopher Kholhoff's Boost.Asio Example, released under -// the Boost Software License, Version 1.0. (See acccompanying file -// LICENSE_1_0.txt -// or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_NETWORK_HTTP_SERVER_SYNC_CONNECTION_HPP_ -#define BOOST_NETWORK_HTTP_SERVER_SYNC_CONNECTION_HPP_ - -#ifndef BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE -#define BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE 1024uL -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace network { -namespace http { - -template -struct sync_connection - : std::enable_shared_from_this > { - - sync_connection(asio::io_service &service, Handler &handler) - : service_(service), - handler_(handler), - socket_(service_), - wrapper_(service_) {} - - asio::ip::tcp::socket &socket() { return socket_; } - - void start() { - // This is HTTP so we really want to just - // read and parse a request that's incoming - // and then pass that request object to the - // handler_ instance. - // - using asio::ip::tcp; - std::error_code option_error; - socket_.set_option(tcp::no_delay(true), option_error); - if (option_error) - handler_.log(std::system_error(option_error).what()); - auto self = this->shared_from_this(); - socket_.async_read_some( - asio::buffer(buffer_), - wrapper_.wrap([=] (std::error_code const &ec, - std::size_t bytes_transferred) { - self->handle_read_headers(ec, bytes_transferred); - })); - } - - private: - struct is_content_length { - template - bool operator()(Header const &header) { - return boost::to_lower_copy(header.name) == "content-length"; - } - }; - - void handle_read_headers(std::error_code const &ec, - size_t bytes_transferred) { - if (!ec) { - request_.source = socket_.remote_endpoint().address().to_string(); - request_.source_port = socket_.remote_endpoint().port(); - boost::tribool done; - buffer_type::iterator new_start; - tie(done, new_start) = parser_.parse_headers( - request_, buffer_.data(), buffer_.data() + bytes_transferred); - if (done) { - if (request_.method[0] == 'P') { - // look for the content-length header - auto - it = std::find_if(request_.headers.begin(), - request_.headers.end(), is_content_length()); - if (it == request_.headers.end()) { - response_ = basic_response::stock_reply( - basic_response::bad_request); - auto self = this->shared_from_this(); - asio::async_write( - socket_, response_.to_buffers(), - wrapper_.wrap([=] (std::error_code const &ec) { - self->handle_write(ec); - })); - return; - } - - size_t content_length = 0; - - try { - content_length = std::stoul(it->value); - } - catch (...) { - response_ = basic_response::stock_reply( - basic_response::bad_request); - auto self = this->shared_from_this(); - asio::async_write( - socket_, response_.to_buffers(), - wrapper_.wrap([=] (std::error_code const &ec) { - self->handle_write(ec); - })); - return; - } - - if (content_length != 0) { - if (new_start != (buffer_.begin() + bytes_transferred)) { - request_.body.append(new_start, - buffer_.begin() + bytes_transferred); - content_length -= - std::distance(new_start, buffer_.begin() + bytes_transferred); - } - if (content_length > 0) { - auto self = this->shared_from_this(); - socket_.async_read_some( - asio::buffer(buffer_), - wrapper_.wrap([=] (std::error_code const &ec, - std::size_t bytes_transferred) { - self->handle_read_body_contents(ec, content_length, - bytes_transferred); - })); - return; - } - } - - handler_(request_, response_); - auto self = this->shared_from_this(); - asio::async_write( - socket_, response_.to_buffers(), - wrapper_.wrap([=] (std::error_code const &ec) { - self->handle_write(ec); - })); - } else { - handler_(request_, response_); - auto self = this->shared_from_this(); - asio::async_write( - socket_, response_.to_buffers(), - wrapper_.wrap([=] (std::error_code const &ec) { - self->handle_write(ec); - })); - } - } else if (!done) { - response_ = - basic_response::stock_reply(basic_response::bad_request); - auto self = this->shared_from_this(); - asio::async_write( - socket_, response_.to_buffers(), - wrapper_.wrap([=] (std::error_code const &ec) { - self->handle_write(ec); - })); - } else { - auto self = this->shared_from_this(); - socket_.async_read_some( - asio::buffer(buffer_), - wrapper_.wrap([=] (std::error_code const &ec, - std::size_t bytes_transferred) { - self->handle_read_headers(ec, bytes_transferred); - })); - } - } - // TODO Log the error? - } - - void handle_read_body_contents(std::error_code const &ec, - size_t bytes_to_read, - size_t bytes_transferred) { - if (!ec) { - size_t difference = bytes_to_read - bytes_transferred; - buffer_type::iterator start = buffer_.begin(), past_end = start; - std::advance(past_end, (std::min)(bytes_to_read, bytes_transferred)); - request_.body.append(buffer_.begin(), past_end); - if (difference == 0) { - handler_(request_, response_); - auto self = this->shared_from_this(); - asio::async_write( - socket_, response_.to_buffers(), - wrapper_.wrap([=] (std::error_code const &ec) { - self->handle_write(ec); - })); - } else { - auto self = this->shared_from_this(); - socket_.async_read_some( - asio::buffer(buffer_), - wrapper_.wrap([=] (std::error_code const &ec, - std::size_t bytes_transferred) { - self->handle_read_body_contents(ec, difference, bytes_transferred); - })); - } - } - // TODO Log the error? - } - - void handle_write(std::error_code const &ec) { - if (!ec) { - using asio::ip::tcp; - std::error_code ignored_ec; - socket_.shutdown(tcp::socket::shutdown_receive, ignored_ec); - } - } - - asio::io_service &service_; - Handler &handler_; - asio::ip::tcp::socket socket_; - asio::io_service::strand wrapper_; - - typedef std::array - buffer_type; - buffer_type buffer_; - typedef basic_request_parser request_parser; - request_parser parser_; - basic_request request_; - basic_response response_; -}; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_HTTP_SERVER_SYNC_CONNECTION_HPP_ diff --git a/boost/network/protocol/http/server/sync_server.hpp b/boost/network/protocol/http/server/sync_server.hpp deleted file mode 100644 index 2b4b976da..000000000 --- a/boost/network/protocol/http/server/sync_server.hpp +++ /dev/null @@ -1,133 +0,0 @@ - -// Copyright 2010 Dean Michael Berris. -// Copyright 2010 Glyn Matthews. -// 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) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_SYNC_SERVER_HPP_20101025 -#define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_SYNC_SERVER_HPP_20101025 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace network { -namespace http { - -template -struct sync_server_base : server_storage_base, socket_options_base { - typedef typename string::type string_type; - typedef basic_request request; - typedef basic_response response; - typedef typename boost::network::http::response_header::type - response_header; - - sync_server_base(server_options const& options) - : server_storage_base(options), - socket_options_base(options), - handler_(options.handler()), - address_(options.address()), - port_(options.port()), - acceptor_(server_storage_base::service_), - new_connection(), - listening_mutex_(), - listening_(false) {} - - void run() { - listen(); - service_.run(); - } - - void stop() { - // stop accepting new connections and let all the existing handlers - // finish. - std::error_code ignored; - acceptor_.close(ignored); - service_.stop(); - } - - void listen() { - std::unique_lock listening_lock(listening_mutex_); - if (!listening_) start_listening(); - } - - private: - Handler& handler_; - string_type address_, port_; - asio::ip::tcp::acceptor acceptor_; - std::shared_ptr > new_connection; - std::mutex listening_mutex_; - bool listening_; - - void handle_accept(std::error_code const& ec) { - if (ec) { - } - socket_options_base::socket_options(new_connection->socket()); - new_connection->start(); - new_connection.reset(new sync_connection(service_, handler_)); - auto self = this->shared_from_this(); - acceptor_.async_accept( - new_connection->socket(), - [=] (std::error_code const &ec) { self->handle_accept(); }); - } - - void start_listening() { - using asio::ip::tcp; - std::error_code error; - tcp::resolver resolver(service_); - tcp::resolver::query query(address_, port_); - tcp::resolver::iterator endpoint_iterator = resolver.resolve(query, error); - if (error) { - BOOST_NETWORK_MESSAGE("Error resolving address: " << address_ << ':' - << port_); - boost::throw_exception(std::runtime_error("Error resolving address.")); - } - tcp::endpoint endpoint = *endpoint_iterator; - acceptor_.open(endpoint.protocol(), error); - if (error) { - BOOST_NETWORK_MESSAGE("Error opening socket: " << address_ << ':' << port_ - << " -- reason: '" << error - << '\''); - boost::throw_exception(std::runtime_error("Error opening socket.")); - } - socket_options_base::acceptor_options(acceptor_); - acceptor_.bind(endpoint, error); - if (error) { - BOOST_NETWORK_MESSAGE("Error binding to socket: " - << address_ << ':' << port_ << " -- reason: '" - << error << '\''); - boost::throw_exception(std::runtime_error("Error binding to socket.")); - } - acceptor_.listen(tcp::socket::max_connections, error); - if (error) { - BOOST_NETWORK_MESSAGE("Error listening on socket: " - << address_ << ':' << port_ << " -- reason: '" - << error << '\''); - boost::throw_exception(std::runtime_error("Error listening on socket.")); - } - new_connection.reset(new sync_connection(service_, handler_)); - auto self = this->shared_from_this(); - acceptor_.async_accept( - new_connection->socket(), - [=] (std::error_code const &ec) { self->handle_accept(ec); }); - listening_ = true; - } -}; - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_SYNC_SERVER_HPP_20101025 */ diff --git a/libs/network/doc/contents.rst b/libs/network/doc/contents.rst index b014eab03..0c41b80a7 100644 --- a/libs/network/doc/contents.rst +++ b/libs/network/doc/contents.rst @@ -10,8 +10,5 @@ Contents whats_new.rst getting_started.rst examples.rst - in_depth.rst - techniques.rst - history.rst reference.rst references.rst diff --git a/libs/network/doc/history.rst b/libs/network/doc/history.rst deleted file mode 100644 index 24f503f0a..000000000 --- a/libs/network/doc/history.rst +++ /dev/null @@ -1,54 +0,0 @@ -Project history -=============== - -The :mod:`cpp-netlib` was founded by Dean Michael Berris in 2007. -Initially it consisted of a message template and an HTTP client. It -found a home on Sourceforge_ but was migrated at the end of 2009 to -Github_ where development is actively continued by a committed -community. - -Motivation -~~~~~~~~~~ - -We're a group of C++ developers and we kept becoming annoyed that we -had to repeatedly write the same code when building applications that -needed to be network-aware. - -We found that there was a lack of accessible networking libraries, -either standard or open source, that fulfilled our needs. Such -libraries exist for every other major language. So, building on top -of `Boost.Asio`_, we decided to get together and build our own. - -Objectives -~~~~~~~~~~ - -The objectives of the :mod:`cpp-netlib` are to: - -* develop a high quality, portable, easy to use C++ networking library -* enable developers to easily extend the library -* lower the barrier to entry for cross-platform network-aware C++ - applications - -The goal the of :mod:`cpp-netlib` has never been to build a -fully-featured web server - there are plenty of excellent options -already available. The niche that this library targets is for -light-weight networking functionality for C++ applications that have -demanding performance requirements or memory constraints, but that -also need to be portable. This type of application is becoming -increasingly common as software becomes more distributed, and -applications need to communicate with services. - -While many languages provide direct library support for high level -network programming, this feature is missing in C++. Therefore, this -library has been developed with the intention of eventually being -submitted to Boost_, a collection of general, high quality -libraries for C++ developers. - -Eventually, the :mod:`cpp-netlib` will be extended to support many of -the application layer protocols such as SMTP, FTP, SOAP, XMPP etc. - - -.. _Sourceforge: http://sourceforge.net/projects/cpp-netlib/ -.. _Github: http://github.com/cpp-netlib/cpp-netlib -.. _Boost: http://www.boost.org/ -.. _`Boost.Asio`: http://www.boost.org/libs/asio/ diff --git a/libs/network/doc/html/_images/ftp_uri.png b/libs/network/doc/html/_images/ftp_uri.png deleted file mode 100644 index f77d3c87b..000000000 Binary files a/libs/network/doc/html/_images/ftp_uri.png and /dev/null differ diff --git a/libs/network/doc/html/_images/http_uri.png b/libs/network/doc/html/_images/http_uri.png deleted file mode 100644 index a7bf7561b..000000000 Binary files a/libs/network/doc/html/_images/http_uri.png and /dev/null differ diff --git a/libs/network/doc/html/_images/mailto_uri.png b/libs/network/doc/html/_images/mailto_uri.png deleted file mode 100644 index 118d6f4ba..000000000 Binary files a/libs/network/doc/html/_images/mailto_uri.png and /dev/null differ diff --git a/libs/network/doc/html/_sources/contents.txt b/libs/network/doc/html/_sources/contents.txt index b014eab03..0c41b80a7 100644 --- a/libs/network/doc/html/_sources/contents.txt +++ b/libs/network/doc/html/_sources/contents.txt @@ -10,8 +10,5 @@ Contents whats_new.rst getting_started.rst examples.rst - in_depth.rst - techniques.rst - history.rst reference.rst references.rst diff --git a/libs/network/doc/html/_sources/history.txt b/libs/network/doc/html/_sources/history.txt deleted file mode 100644 index 24f503f0a..000000000 --- a/libs/network/doc/html/_sources/history.txt +++ /dev/null @@ -1,54 +0,0 @@ -Project history -=============== - -The :mod:`cpp-netlib` was founded by Dean Michael Berris in 2007. -Initially it consisted of a message template and an HTTP client. It -found a home on Sourceforge_ but was migrated at the end of 2009 to -Github_ where development is actively continued by a committed -community. - -Motivation -~~~~~~~~~~ - -We're a group of C++ developers and we kept becoming annoyed that we -had to repeatedly write the same code when building applications that -needed to be network-aware. - -We found that there was a lack of accessible networking libraries, -either standard or open source, that fulfilled our needs. Such -libraries exist for every other major language. So, building on top -of `Boost.Asio`_, we decided to get together and build our own. - -Objectives -~~~~~~~~~~ - -The objectives of the :mod:`cpp-netlib` are to: - -* develop a high quality, portable, easy to use C++ networking library -* enable developers to easily extend the library -* lower the barrier to entry for cross-platform network-aware C++ - applications - -The goal the of :mod:`cpp-netlib` has never been to build a -fully-featured web server - there are plenty of excellent options -already available. The niche that this library targets is for -light-weight networking functionality for C++ applications that have -demanding performance requirements or memory constraints, but that -also need to be portable. This type of application is becoming -increasingly common as software becomes more distributed, and -applications need to communicate with services. - -While many languages provide direct library support for high level -network programming, this feature is missing in C++. Therefore, this -library has been developed with the intention of eventually being -submitted to Boost_, a collection of general, high quality -libraries for C++ developers. - -Eventually, the :mod:`cpp-netlib` will be extended to support many of -the application layer protocols such as SMTP, FTP, SOAP, XMPP etc. - - -.. _Sourceforge: http://sourceforge.net/projects/cpp-netlib/ -.. _Github: http://github.com/cpp-netlib/cpp-netlib -.. _Boost: http://www.boost.org/ -.. _`Boost.Asio`: http://www.boost.org/libs/asio/ diff --git a/libs/network/doc/html/_sources/in_depth.txt b/libs/network/doc/html/_sources/in_depth.txt deleted file mode 100644 index 39af9a4f4..000000000 --- a/libs/network/doc/html/_sources/in_depth.txt +++ /dev/null @@ -1,15 +0,0 @@ -.. _in_depth: - -An in-depth look at the :mod:`cpp-netlib` -========================================= - -The :mod:`cpp-netlib` is composed of three different sets of -functionality: a **message** template, a **URI** template and -different **protocol** implementations. - -.. toctree:: - :maxdepth: 2 - - in_depth/message - in_depth/uri - in_depth/http diff --git a/libs/network/doc/html/_sources/in_depth/http.txt b/libs/network/doc/html/_sources/in_depth/http.txt deleted file mode 100644 index 711bf6b3e..000000000 --- a/libs/network/doc/html/_sources/in_depth/http.txt +++ /dev/null @@ -1,180 +0,0 @@ -HTTP implementation -=================== - -HTTP client -``````````` - -At the heart of the HTTP client implementation is a single class aptly named -``basic_client``, which is also a template. The template ``basic_client`` takes -three template parameters: - -.. code-block:: c++ - - namespace boost { namespace http { - - template - struct basic_client; - - } // namespace http - - } // namespace boost - -The ``Tag`` template parameter follows the same tag-dispatch mechanism to -determine the behavior of the ``basic_client``. The interface of -``basic_client`` may change depending on certain properties defined for the tag -you provide. Below is a table of predefined supported tags you can use in your -overload of the ``basic_client``: - ------------- - -.. include:: http_client_tags.rst - -.. _Boost.Thread: http://www.boost.org/libs/thread - - -The default typedef for the HTTP client that is provided uses the -``http_async_8bit_udp_resolve`` tag, and implements HTTP 1.1. The exact -typedef is in the ``boost::network::http`` namespace as the following: - -.. code-block:: c++ - - namespace boost { namespace network { namespace http { - - typedef basic_client - client; - - }}} - - -This type has nested typedefs for the correct types for the ``basic_request`` -and ``basic_response`` templates. To use the correct types for ``basic_request`` -or ``basic_response`` you can use these nested typedefs like so: - - -.. code-block:: c++ - - boost::network::http::client::request request; - boost::network::http::client::response response; - - // or... - using namespace boost::network; - http::client::request request; - http::client::response response; - - -Typical use cases for the HTTP client would look something like the following: - - -.. code-block:: c++ - - using namespace boost::network; - http::request request("http://www.boost.org/"); - request << header("Connection", "close"); - - -The ``basic_client`` implements all HTTP methods as member functions -(HEAD, GET, POST, PUT, DELETE). Therefore, the code to make an HTTP -request looks trivially simple: - - -.. code-block:: c++ - - using namespace boost::network; - http::client client; - http::client::request request("http://www.boost.org/"); - http::client::response response = client.get(request); - - -Accessing data from ``http::response`` is done using wrappers. -To get the response headers, we use the ``headers`` wrapper which -returns, in the default case, a multimap of strings to strings: - - -.. code-block:: c++ - - using namespace boost::network; - typedef headers_range::type response_headers; - boost::range_iterator::type iterator; - - response_headers headers_ = headers(response); - for (iterator it = headers_.begin(); it != headers_.end(); ++it) { - std::cout << it->first << ": " << it->second << std::endl; - } - std::cout << std::endl; - - -HTTP server -``````````` - -As with the HTTP client, the HTTP server that is provided with -cpp-netlib is extensible through the tag mechanism and is embeddable. -The template class declaration of ``basic_server`` is given below: - - -.. code-block:: c++ - - namespace boost { namespace network { namespace http { - - template basic_server; - - }}} - - -The second template argument is used to specify the request handler -type. The request handler type is a functor type which should overload -the function call operator (``RequestHandler::operator()`` should be -overloaded) that takes two parameters: the first one being a reference -to a ``const basic_request`` and the second being a reference to -a ``basic_response`` instance. - -All the logic for parsing the HTTP request and building the ``const -basic_request`` object resides internally in the ``basic_server`` -template. Processing the request is delegated to the -``RequestHandler`` type, and the assumption of which would be that the -response is formed inside the ``RequestHandler`` function call -operator overload. - -The ``basic_server`` template however is only an underlying -implementation while the user-visible implementation is the -``http::server`` template. This simply specializes the -``basic_server`` template to use the ``default_`` tag and forwards the -``RequestHandler`` parameter: - -.. code-block:: c++ - - namespace boost { namespace network { namespace http { - - template - class server : - public basic_server {}; - - }}} - -To use the forwarding server type you just supply the request handler -implementation as the parameter. For example, an "echo" server example -might look something like this: - - -.. code-block:: c++ - - using namespace boost::network; - struct echo; - typedef http::server echo_server; - - struct echo { - void operator () (const echo_server::request &request, - echo_server::response &response) const { - std::string ip = source(request); - response = echo_server::response::stock_reply( - echo_server::response::ok, - body(request)); - std::cerr << "[" << ip << "]: " << request.uri << - " status = " << echo_server::response::ok << '\n'; - } - }; - - -Here, all we're doing is returning the original request body with an -HTTP OK response (200). We are also printing the IP address from where the -request came from. Notice that we are using a wrapper to access the source of -the request. diff --git a/libs/network/doc/html/_sources/in_depth/http_client_tags.txt b/libs/network/doc/html/_sources/in_depth/http_client_tags.txt deleted file mode 100644 index 5d79ed1ea..000000000 --- a/libs/network/doc/html/_sources/in_depth/http_client_tags.txt +++ /dev/null @@ -1,42 +0,0 @@ -+---------------------------------+---------------------------------------------+ -| Tag | Description | -+=================================+=============================================+ -| http_default_8bit_tcp_resolve | This is the default HTTP implementation tag | -| | that resolves addresses with a TCP resolver | -| | and provides a synchronous/blocking HTTP | -| | client interface. | -+---------------------------------+---------------------------------------------+ -| http_default_8bit_udp_resolve | This is similar to the above tag except that| -| | it specifies the HTTP client to use a UDP | -| | resolver. It also provides a synchronous/ | -| | blocking HTTP client interface. | -+---------------------------------+---------------------------------------------+ -| http_keepalive_8bit_tcp_resolve | This tag specifies that the HTTP client by | -| | default will keep connections to the server | -| | alive. It only makes sense if the | -| | ``version_major`` and ``version_minor`` are | -| | both ``1``, to indicate HTTP 1.1. This tag | -| | causes the HTTP client to resolve using a | -| | TCP resolver and provides a synchronous/ | -| | blocking HTTP client interface. | -+---------------------------------+---------------------------------------------+ -| http_keepalive_8bit_udp_resolve | This is similar to the above tag except that| -| | it specifies the HTTP client to use a UDP | -| | resolver. It also provides a synchronous/ | -| | blocking HTTP client interface. | -+---------------------------------+---------------------------------------------+ -| http_async_8bit_tcp_resolve | This tag provides an active HTTP client | -| | object implementation that uses a TCP | -| | resolver. Response objects returned will | -| | encapsulate a number of Boost.Thread_ | -| | shared futures to hold values. Users don't | -| | have to see this as they are implementation | -| | details. | -+---------------------------------+---------------------------------------------+ -| http_async_8bit_udp_resolve | This is similar to the above tag except that| -| | specifies the HTTP client to use a UDP | -| | resolver. | -+---------------------------------+---------------------------------------------+ - -.. _Boost.Thread: http://www.boost.org/libs/thread - diff --git a/libs/network/doc/html/_sources/in_depth/message.txt b/libs/network/doc/html/_sources/in_depth/message.txt deleted file mode 100644 index 51512314b..000000000 --- a/libs/network/doc/html/_sources/in_depth/message.txt +++ /dev/null @@ -1,233 +0,0 @@ -The message template -==================== - -One of the core components in the library is the concept and the -implementation of a common message type. In most (not all) network -protocols, the concept of a message is central to the definition of -the protocol. In HTTP, SMTP, XMPP, and even other protocols like SNMP -and ICMP, there is a common notion of a "packet" or a message. In -cpp-netlib we chose to implement the concept of a message that has the -following common parts: - - * **Source** - every message has a source identifier which varies - from protocol to protocol. - - * **Destination** - every message has a destination identifier which - varies from protocol to protocol. - - * **Headers** - each message is assumed to contain headers, which - may be empty in cases where the protocol does not support it, but - is nonetheless supported by cpp-netlib messages. - - * **Body** - the content area of a message which varies from - protocol to protocol (also sometimes referred to as payload). - -This division is purely logical -- in the underlying implementation, -the message type can choose to have different means of storing the -data, depending on the type used to tag the message. This section -covers the `Message Concept`_ as well as the `basic_message`_ -implementation. - -Message Concept -``````````````` - -.. warning:: The Message framework is deprecated in the 0.11 release, and will - be removed in future versions of the library. - -The Message Concept specifies what the valid operations on a message -are as well as what messages look like semantically. The following -table summarize the operations and syntactic as well as semantic -properties of messages. - -**Legend** - -:M: The message type. -:H: A headers container type. -:m,n: An instance of **M**. -:S: A string type. -:s,k,v: An instance of **S**. -:O: The source type. -:D: The destination type. -:B: The body type. -:T: The Tag type. - -+----------------------------+----------------------+-----------------------------------------+ -| Construct | Result | Description | -+============================+======================+=========================================+ -| ``typename M::tag`` | T | The nested tag type. | -+----------------------------+----------------------+-----------------------------------------+ -| ``M()`` | Instance of M | Default constructible. | -+----------------------------+----------------------+-----------------------------------------+ -| ``M(m)`` | Instance of M | Copy constructible. | -+----------------------------+----------------------+-----------------------------------------+ -| ``m = n;`` | Reference to m | Assignable. | -+----------------------------+----------------------+-----------------------------------------+ -| ``swap(m, n);`` | ``void`` | Swappable. | -+----------------------------+----------------------+-----------------------------------------+ -| ``source(m);`` | Convertible to O | Retrieve the source of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``destination(m);`` | Convertible to D | Retrieve the destination of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``headers(m);`` | Convertible to H | Retrieve the headers of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``body(m);`` | Convertible to B | Retrieve the body of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``m << source(s);`` | ``M &`` | Set the source of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``m << destination(s);`` | ``M &`` | Set the destination of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``m << header(k, v);`` | ``M &`` | Add a header to ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``m << remove_header(k);`` | ``M &`` | Remove a header from ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``m << body(s);`` | ``M &`` | Set the body of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``source(m,s);`` | ``void`` | Set the source of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``destination(m,s);`` | ``void`` | Set the destination of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``add_header(m, k, v);`` | ``void`` | Add a header to ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``remove_header(m, k);`` | ``void`` | Remove a header from ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``clear_headers(m);`` | ``void`` | Clear the headers of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``body(m,s);`` | ``M &`` | Set the body of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ - -Types that model the Message Concept are meant to encapsulate data -that has a source, a destination, one or more named headers, and a -body/payload. Because the accessors and the directives are not -required to be part of the message type that models the Message -Concept, a message can be implemented as a POD type and have all -manipulations performed in the directive implementations, as well as -value transformations done in the accessors. - -Directives, Modifiers, and Wrappers -``````````````````````````````````` - -In the Message Concept definition there are three basic constructs that follow a -certain pattern. These patterns are Directives_, Modifiers_, and Wrappers_. - -Directives -~~~~~~~~~~ - -A directive is a function object that is applied to a Message. Directives -encapsulate a set of operations that apply to messages. The general requirement -for a Directive is that it should apply these operations on a message. - -A directive may dispatch on the type of the message passed to it at the point of -the function call. Typically, directives are generated using a factory function -that returns the correct directive type. - -For a given directive ``foo_directive`` a generator function called ``foo`` is -typically implemented: - -.. code-block:: c++ - - struct foo_directive { - template - Message & operator()(Message & m) const { - // do something to m - return m; - } - }; - - foo_directive const foo() { - return foo_directive(); - } - - // to apply a directive, we use the << operator - message m; - m << foo(); - -Modifiers -~~~~~~~~~ - -A modifier is generally defined as a free function that takes a reference to a -non-const lvalue message as the first parameter, and any number of parameters. -In the concept definition of the Message Concept, a modifier follows the form: - -.. code-block:: c++ - - modifier(message, ...) - -Modifiers are meant to imply modifications on a message, which also allows for -easier dispatch based on Argument Dependent Lookup (ADL_) on the type of the -message. Note that Directives_ can be implemented in terms of Modifiers and -vice versa, although that is not required nor specified. - -.. _ADL: http://en.wikipedia.org/wiki/Argument-dependent_name_lookup - -Wrappers -~~~~~~~~ - -A Wrapper is basically an implementation detail that ensures that a given -message, when wrapped, can be converted to the associated part of the message. A -wrapper has a type that encapsulates the conversion logic from a message to a -given type. - -An example of a Wrapper would be ``source_wrapper`` which would be returned by a -call to the wrapper generator function ``source``. An example implementation of -the ``source_wrapper`` would look like: - -.. code-block:: c++ - - template class Message> - struct source_wrapper { - Message const & m; - explicit source_wrapper(Message const & m) - : m(m) {} - typedef typename source::type source_type; - operator source_type const & () { - return m.source; - } - operator source_type const () { - return m.source; - } - operator source_type () { - return m.source; - } - }; - - template class Message> - source_wrapper const - source(Message const & message) { - return source_wrapper(message); - } - -This pattern is similar to an adapter, but the specific notion of wrapping a -data type (in this case, an object of a type that models the Message Concept) -using an intermediary wrapper is what is pertained to by the Wrapper pattern. -In this case, the Wrapper is ``source_wrapper`` while ``source`` is merely a -wrapper generator function. - -``basic_message`` -````````````````` - -The default implementation of a simple type that models the Message -Concept is available in cpp-netlib. This default implementation is -named ``basic_message`` which supports a ``Tag`` template -parameter. The definition of ``basic_message`` looks like this: - -.. code-block:: c++ - - template - class basic_message; - -The ``basic_message`` template requires that the following -tag-dispatched metafunctions are defined for the type ``Tag``: - -.. code-block:: c++ - - template - struct string; - - template - struct headers_container; - -All the operations defined by the message concept are implemented by -this basic message type. Other message implementations can either use -this common message type or specialize it according to whether they -want to use different containers or whether it's going to be just a -POD type. diff --git a/libs/network/doc/html/_sources/in_depth/uri.txt b/libs/network/doc/html/_sources/in_depth/uri.txt deleted file mode 100644 index 84eca62e2..000000000 --- a/libs/network/doc/html/_sources/in_depth/uri.txt +++ /dev/null @@ -1,151 +0,0 @@ -The URI class -============= - -In addition to protocol implementations, the :mod:`cpp-netlib` -provides a powerful URI class. The class implements a parser based -on `RFC 3986`_ and `RFC 2732`_. - -Generic URI syntax overview -``````````````````````````` - -A generic URI will take the form:: - - [scheme:]scheme-specific-part[#fragment] - -A URI is known as `absolute` if it specifies the scheme. Otherwise, -it is known as a relative URI. Currently, ``uri`` supports only -absolute URIs. - -URIs can be further classified according to whether they're -hierarchical or opaque (non-hierarchical). - -Some examples of non-hierarchical URIs include:: - - mailto:john.doe@example.com - news:comp.infosystems.www.servers.unix - tel:+1-816-555-1212 - -The data following the first ``":"`` is said to be opaque to the URI -parser and requires no further parsing. By way of example, the -following shows how a non-hierarchical URI is processed by the parser -by defining everything after the ``":"`` to be a part of the path: - -.. image:: ../_static/mailto_uri.png - -A hierarchical URI is identified by a double slash (``"//"``) after -the scheme and a scheme-specific component, which `RFC 3986`_ defines -to be:: - - [scheme:][//authority][path][?query][#fragment] - -The authority component can be further broken down to:: - - [user_info@]host[:port] - -Examples of hierarchical URIs include:: - - http://www.boost.org/ - file:///bin/bash - -The following example, describing a complex URI using FTP, shows how -a URI is broken down by the parser: - -.. image:: ../_static/ftp_uri.png - -Note that the ``authority`` is further subdivided into different -elements. Another example, using HTTP is given below: - -.. image:: ../_static/http_uri.png - -The difference here between the path in a hierarchical URI and that in -the example above for the non-hierarchical URI. - -The ``uri`` class -````````````````` - -As of version 0.9.3, ``uri`` supplies a URI parser and builder. -To use the parser, it's as simple as supplying a string to the -constructor: - -.. code-block:: c++ - - using namespace boost::network; - uri::uri instance("http://cpp-netlib.github.com/"); - assert(instance.is_valid()); - std::cout << "scheme: " << instance.scheme() << std::endl - << "host: " << instance.host() << std::endl; - -The command-line output of this program will be:: - - scheme: http - host: cpp-netlib.github.com - -The ``uri`` builder -``````````````````` - -``uri`` support a stream style syntax to create a URI from it's -elements. For example the program: - -.. code-block:: c++ - - #include - #include - #include - using namespace boost::network; - - int main() { - uri::uri url; - url << uri::scheme("http") - << uri::host("www.github.com") - << uri::path("/cpp-netlib"); - std::cout << url << std::endl; - return 0; - } - -will output:: - - http://www.github.com/cpp-netlib - -``URI Concept`` -``````````````` - -**Legend** - -:U: The URI type. -:u,u_: An instance of **M**. -:S: A string type. -:s,v: An instance of **S**. -:T: The Tag type. - -+----------------------------+----------------------+-----------------------------------------+ -| Construct | Result | Description | -+============================+======================+=========================================+ -| ``U(u)`` | Instance of U | Copy constructible. | -+----------------------------+----------------------+-----------------------------------------+ -| ``U(s)`` | Instance of U | Constructible from string. | -+----------------------------+----------------------+-----------------------------------------+ -| ``u = u_;`` | Reference to u | Assignable. | -+----------------------------+----------------------+-----------------------------------------+ -| ``u = s;`` | Reference to u | Assignable from string. | -+----------------------------+----------------------+-----------------------------------------+ -| ``swap(u, u_);`` | ``void`` | Swappable. | -+----------------------------+----------------------+-----------------------------------------+ -| ``scheme(u);`` | Convertible to S | Retrieve the URI scheme of ``u``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``user_info(u);`` | Convertible to S | Retrieve the user info of ``u``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``host(u);`` | Convertible to S | Retrieve the host of ``u``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``port(u);`` | Convertible to H | Retrieve the port of ``u``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``path(u);`` | Convertible to S | Retrieve the path of ``u``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``query(u);`` | Convertible to S | Retrieve the query string of ``u``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``fragment(u);`` | Convertible to S | Retrieve the fragment of ``u``. | -+----------------------------+----------------------+-----------------------------------------+ - -.. _`RFC 3986`: http://tools.ietf.org/html/rfc3986 -.. _`RFC 2368`: http://tools.ietf.org/html/rfc2368 -.. _`RFC 3513`: http://tools.ietf.org/html/rfc3513 -.. _`RFC 2732`: http://tools.ietf.org/html/rfc2732 diff --git a/libs/network/doc/html/_sources/index.txt b/libs/network/doc/html/_sources/index.txt index fc9e65405..3329b8a30 100644 --- a/libs/network/doc/html/_sources/index.txt +++ b/libs/network/doc/html/_sources/index.txt @@ -108,7 +108,6 @@ Want to learn more? * :ref:`Take a look at the getting started guide ` * :ref:`Learn from some simple examples ` * :ref:`Find out what's new ` - * :ref:`Study the library in more depth ` * :ref:`Discover more through the full reference ` * :ref:`Full table of contents ` diff --git a/libs/network/doc/html/_sources/reference/http_server.txt b/libs/network/doc/html/_sources/reference/http_server.txt index 26ceb9b65..c0022bdda 100644 --- a/libs/network/doc/html/_sources/reference/http_server.txt +++ b/libs/network/doc/html/_sources/reference/http_server.txt @@ -5,9 +5,9 @@ HTTP Server API General ------- -:mod:`cpp-netlib` includes and implements two distinct HTTP server -implementations that you can use and embed in your own applications. Both HTTP -Server implementations: +:mod:`cpp-netlib` includes and implements and asynchronous HTTP server +implementation that you can use and embed in your own applications. The HTTP +Server implementation: * **Cannot be copied.** This means you may have to store instances of the HTTP Server in dynamic memory if you intend to use them as function parameters or @@ -15,60 +15,19 @@ Server implementations: * **Assume that requests made are independent of each other.** None of the HTTP Server implementations support request pipelining (yet) so a single connection only deals with a single request. - * **Are header-only and are compiled-into your application.** Future releases - in case you want to upgrade the implementation you are using in your - application will be distributed as header-only implementations, which means - you have to re-compile your application to use a newer version of the - implementations. - -The HTTP Servers have different semantics, and in some cases require different -APIs from the supplied template parameters. - -Implementations ---------------- - -There are two different user-facing template classes that differentiate the -`Synchronous Servers`_ from the `Asynchronous Servers`_. Both templates take a -single template parameter named ``Handler`` which describes the type of the -Handler function object. - -There are two different Handler concepts, one concept for `Synchronous Servers`_ -and another for `Asynchronous Servers`. - -The SynchronousHandler concept for `Synchronous Servers`_ is described by the -following table: - ---------------- - -**Legend:** - -H - The Handler type. -h - An instance of H. -Req - A type that models the Request Concept. -Res - A type that models the Response Concept. -req - An instance of Req. -res - An instance of Res. - -+----------------+-------------+----------------------------------------------+ -| Construct | Return Type | Description | -+================+=============+==============================================+ -| ``h(req,res)`` | ``void`` | Handle the request; res is passed in as a | -| | | non-const lvalue, which represents the | -| | | response to be returned to the client | -| | | performing the request. | -+----------------+-------------+----------------------------------------------+ - -More information about the internals of the `Synchronous Servers`_ can be found -in the following section. - -The AsynchronousHandler concept for `Asynchronous Servers`_ is described by the -following table: + * **The Handler instance is invoked asynchronously**. This means the I/O + thread used to handle network-related events are free to handle only the + I/O related events. This enables the server to scale better as to the + number of concurrent connections it can handle. + * **The Handler is able to schedule asynchronous actions on the thread pool + associated with the server.** This allows handlers to perform multiple + asynchronous computations that later on perform writes to the connection. + * **The Handler is able to control the (asynchronous) writes to and reads + from the HTTP connection.** Because the connection is available to the + Handler, that means it can write out chunks of data at a time or stream + data through the connection continuously. + +The Handler concept for the HTTP Server is described by the following table: --------------- @@ -95,270 +54,30 @@ conn | | | writing to and reading from the connection.| +------------------+-------------+--------------------------------------------+ -More information about the internals of the `Asynchronous Servers`_ can be found -in the following section. - -Synchronous Servers -------------------- - -The synchronous server implementation is represented by the template ``server`` -in namespace ``boost::network::http``. The ``server`` template takes in a single -template parameter named ``Handler`` which models the SynchronousHandler -concept (described above). - -An instance of Handler is taken in by reference to the constructor of the HTTP -server. This means the Handler is not copied around and only a single instance -of the handler is used for all connections and requests performed against the -HTTP server. - -.. warning:: It is important to note that the HTTP server does not implement any - locking upon invoking the Handler. In case you have any state in the Handler - that will be associated with the synchronous server, you would have to - implement your own synchronization internal to the Handler implementation. - This matters especially if you run the synchronous server in multiple - threads. - -The general pattern of usage for the HTTP Server template is shown below: - -.. code-block:: c++ - - struct handler; - typedef boost::network::http::server http_server; - - struct handler { - void operator()( - http_server::request const & req, - http_server::response & res - ) { - // do something, and then edit the res object here. - } - }; - -More information about the actual HTTP Server API follows in the next section. -It is important to understand that the HTTP Server is actually embedded in your -application, which means you can expose almost all your application logic -through the Handler type, which you can also initialize appropriately. - -API Documentation -~~~~~~~~~~~~~~~~~ - -The following sections assume that the following file has been included: - -.. code-block:: c++ - - #include - -And that the following typedef's have been put in place: - -.. code-block:: c++ - - struct handler_type; - typedef boost::network::http::server http_server; - - struct handler_type { - void operator()(http_server::request const & request, - http_server::response & response) { - // do something here - } - }; - -Constructor -``````````` - -``explicit http_server(options)`` - Construct an HTTP Server instance, passing in a ``server_options`` object. The following table shows the supported options in - ``server_options``. - -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| Parameter Name | Type | Description | -+=======================+==========================================+==================================================================================================+ -| address | string_type | The hostname or IP address from which the server should be bound to. This parameter is required. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| port | string_type | The port to which the server should bind and listen to. This parameter is required. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| thread_pool | ``shared_ptr`` | A shared pointer to an instance of ``boost::network::utils::thread_pool`` -- this is the | -| | | thread pool from where the handler is invoked. This parameter is only applicable and required | -| | | for ``async_server`` instances. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| io_service | ``shared_ptr`` | An optional lvalue to an instance of ``boost::asio::io_service`` which allows the server to use | -| | | an already-constructed ``boost::asio::io_service`` instance instead of instantiating one that it | -| | | manages. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| reuse_address | ``bool`` | A boolean that specifies whether to re-use the address and port on which the server will be | -| | | bound to. This enables or disables the socket option for listener sockets. The default is | -| | | ``false``. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| report_aborted | ``bool`` | A boolean that specifies whether the listening socket should report aborted connection attempts | -| | | to the accept handler (an internal detail of cpp-netlib). This is put in place to allow for | -| | | future-proofing the code in case an optional error handler function is supported in later | -| | | releases of cpp-netlib. The default is ``false``. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| receive_buffer_size | ``int`` | The size of the socket's receive buffer. The default is defined by Boost.Asio and is | -| | | platform-dependent. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| send_buffer_size | ``int`` | The size of the socket's send buffer. The default is defined by Boost.Asio and is | -| | | platform-dependent. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| receive_low_watermark | ``int`` | The size of the socket's low watermark for its receive buffer. The default is defined by | -| | | Boost.Asio and is platform-dependent. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| send_buffer_size | ``int`` | The size of the socket's send low watermark for its send buffer. The default is defined by | -| | | Boost.Asio and is platform-dependent. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| non_blocking_io | ``bool`` | An optional bool to define whether the socket should use non-blocking I/O in case the platform | -| | | supports it. The default is ``true``. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| linger | ``bool`` | An optional bool to determine whether the socket should linger in case there's still data to be | -| | | sent out at the time of its closing. The default is ``true``. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| linger_timeout | ``int`` | An optional int to define the timeout to wait for socket closes before it is set to linger. | -| | | The default is ``0``. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| context | ``shared_ptr`` | An optional shared pointer to an instance of ``boost::asio::ssl::context`` -- this contains the | -| | | settings needed to support SSL. This parameter is only applicable for ``async_server`` instances.| -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ - -To use the above supported named parameters, you'll have code that looks like the following: - -.. code-block:: c++ - - using namespace boost::network::http; // parameters are in this namespace - handler handler_instance; - sync_server::options options(handler_instance); - options.address("0.0.0.0") - .port("80") - .io_service(boost::make_shared()) - .reuse_address(true); - sync_server instance(options); - instance.run(); - -Public Members -`````````````` - -The following definitions assume that a properly constructed ``http_server`` -instance has been constructed in the following manner: - -.. code-block:: c++ - - handler_type handler; - http_server::options options(handler); - http_server server(options.address("127.0.0.1").port("8000")); - -``server.run()`` - Run the HTTP Server event loop. This function can be run on multiple threads - following the example: - -.. code-block:: c++ - - boost::thread t1(boost::bind(&http_server::run, &server)); - boost::thread t2(boost::bind(&http_server::run, &server)); - server.run(); - t1.join(); - t2.join(); - -``server.stop()`` - Stop the HTTP Server acceptor and wait for all pending requests to finish. - -Response Object -``````````````` - -The response object has its own public member functions which can be very -helpful in certain simple situations. - -``response = http_server::response::stock_reply(status, body)`` - Code like the above should go inside the handler's ``operator()`` overload. - The body parameter is an ``std::string``. The status parameter is any of - the following values from the ``http_server::response`` enum - ``status_type``: - -.. code-block:: c++ - - enum status_type { - ok = 200, - created = 201, - accepted = 202, - no_content = 204, - multiple_choices = 300, - moved_permanently = 301, - moved_temporarily = 302, - not_modified = 304, - bad_request = 400, - unauthorized = 401, - forbidden = 403, - not_found = 404, - not_supported = 405, - not_acceptable = 406, - internal_server_error = 500, - not_implemented = 501, - bad_gateway = 502, - service_unavailable = 503 - }; +--------------- -The response object also has the following publicly accessible member values -which can be directly manipulated by the handler. - -+------------------+----------------------+------------------------------------+ -| Member Name | Type | Description | -+==================+======================+====================================+ -| status | ``status_type`` | The HTTP status of the response. | -+------------------+----------------------+------------------------------------+ -| headers | ``vector
`` | Vector of headers. [#]_ | -+------------------+----------------------+------------------------------------+ -| content | ``string_type`` [#]_ | The contents of the response. | -+------------------+----------------------+------------------------------------+ - -.. [#] A header is a struct of type - ``response_header``. An instance always has the - members ``name`` and ``value`` both of which are of type ``string_type``. -.. [#] ``string_type`` is - ``boost::network::string::type``. - -Asynchronous Servers --------------------- - -The asynchronous server implementation is significantly different to the -synchronous server implementation in three ways: - - #. **The Handler instance is invoked asynchronously**. This means the I/O - thread used to handle network-related events are free to handle only the - I/O related events. This enables the server to scale better as to the - number of concurrent connections it can handle. - #. **The Handler is able to schedule asynchronous actions on the thread pool - associated with the server.** This allows handlers to perform multiple - asynchronous computations that later on perform writes to the connection. - #. **The Handler is able to control the (asynchronous) writes to and reads from - the HTTP connection.** Because the connection is available to the Handler, - that means it can write out chunks of data at a time or stream data through - the connection continuously. - -The asynchronous server is meant to allow for better scalability in terms of the -number of concurrent connections and for performing asynchronous actions within -the handlers. If your application does not need to write out information -asynchronously or perform potentially long computations, then the synchronous -server gives a generally better performance profile than the asynchronous -server. - -The asynchronous server implementation is available from a single user-facing -template named ``async_server``. This template takes in a single template +The HTTP Server is meant to allow for better scalability in terms of the number +of concurrent connections and for performing asynchronous actions within the +handlers. The HTTP Server implementation is available from a single +user-facing template named ``server``. This template takes in a single template parameter which is the type of the Handler to be called once a request has been parsed from a connection. -An instance of Handler is taken as a reference to the constructor similar to the -synchronous server implementation. +An instance of Handler is taken as a reference to the constructor of the server +instance. -.. warning:: The asynchronous server implementation, like the synchronous server - implementation, does not perform any synchronization on the calls to the - Handler invocation. This means if your handler contains or maintains internal - state, you are responsible for implementing your own synchronization on - accesses to the internal state of the Handler. +.. warning:: The HTTP Server implementation does not perform any + synchronization on the calls to the Handler invocation. This means if your + handler contains or maintains internal state, you are responsible for + implementing your own synchronization on accesses to the internal state of + the Handler. -The general pattern for using the ``async_server`` template is shown below: +The general pattern for using the ``server`` template is shown below: .. code-block:: c++ struct handler; - typedef boost::network::http::async_server http_server; + typedef boost::network::http::server http_server; struct handler { void operator()( @@ -371,7 +90,7 @@ The general pattern for using the ``async_server`` template is shown below: }; API Documentation -~~~~~~~~~~~~~~~~~ +----------------- The following sections assume that the following file has been included: @@ -395,135 +114,36 @@ And that the following typedef's have been put in place: }; Constructor -``````````` +~~~~~~~~~~~ ``explicit http_server(options)`` Construct an HTTP server instance passing in a ``server_options`` instance. -Public Members -`````````````` - -The following definitions assume that a properly constructed ``http_server`` -instance has been constructed in the following manner: +Server Options +~~~~~~~~~~~~~~ -.. code-block:: c++ - - handler_type handler; - http_server::options options(handler); - options.thread_pool(boost::make_shared(2)); - http_server server(options.address("127.0.0.1").port("8000")); - -``server.run()`` - Run the HTTP Server event loop. This function can be run on multiple threads - following the example: - -.. code-block:: c++ +.. doxygenstruct:: boost::network::http::server_options + :project: cppnetlib + :members: - boost::thread t1(boost::bind(&http_server::run, &server)); - boost::thread t2(boost::bind(&http_server::run, &server)); - server.run(); - t1.join(); - t2.join(); +Public Members +~~~~~~~~~~~~~~ -``server.stop()`` - Stop the HTTP Server acceptor and wait for all pending requests to finish. +.. doxygenstruct:: boost::network::http::server + :project: cppnetlib + :members: + :undoc-members: Connection Object -````````````````` - -The connection object has its own public member functions which will be the -primary means for reading from and writing to the connection. - -``template write(Range range)`` - The connection object exposes a function ``write`` that can be given a - parameter that adheres to the Boost.Range_ ``Single Pass Range`` Concept. - The write function, although it looks synchronous, starts of a series of - asynchronous writes to the connection as soon as the range is serialized to - appropriately sized buffers. - - To use this in your handler, it would look something like this: - -.. code-block:: c++ - - connection->write("Hello, world!"); - std::string sample = "I have a string!"; - connection->write(sample); - -``template void write(Range range, Callback callback)`` - The connection object also exposes a function ``write`` that can be given a - parameter that adheres to the Boost.Range_ ``Single Pass Range`` Concept, as - well as a Callback function that returns ``void`` and takes a - ``boost::system::error_code`` as a parameter. This overload of ``write`` is - useful for writing streaming applications that send out chunks of data at a - time, or for writing data that may not all fit in memory right away. - -``template void read(ReadCallback callback)`` - The connection object has a function ``read`` which can be used to read more - information from the connection. This ``read`` function takes in a callback - that can be assigned to a Boost.Function_ with the signature - ``void(input_range,error_code,size_t,connection_ptr)``. The following list - shows what the types actually mean: - - * **input_range** -- ``boost::iterator_range`` : The range - that denotes the data read from the connection. - * **error_code** -- ``boost::system::error_code`` : The error code if - there were any errors encountered from the read. - * **size_t** -- ``std::size_t`` : The number of bytes transferred. - * **connection_ptr** -- ``http_server::connection_ptr`` : A handle to the - current connection, so that it is kept alive at the time of the read - callback invocation. - - This interface is useful when doing reads of uploaded data that can be - potentially large and may not fit in memory. The read handler is then - responsible for dealing with the chunks of data available from the - connection. - -``void set_status(status_t new_status)`` - The ``set_status`` function takes a parameter of type ``status_t`` which is - an enum type nested in ``http_status::connection`` which is given in the - following code listing. - -.. code-block:: c++ - - enum status_t { - ok = 200 - , created = 201 - , accepted = 202 - , no_content = 204 - , multiple_choices = 300 - , moved_permanently = 301 - , moved_temporarily = 302 - , not_modified = 304 - , bad_request = 400 - , unauthorized = 401 - , forbidden = 403 - , not_found = 404 - , not_supported = 405 - , not_acceptable = 406 - , internal_server_error = 500 - , not_implemented = 501 - , bad_gateway = 502 - , service_unavailable = 503 - }; - -.. note:: You may set and re-set the status several times as long as you have - not set the headers or sent data through the connection. If you do this after - data has already been set, the function will throw an instance of - ``std::logic_error``. - -``template void set_headers(Range range)`` - The ``set_headers`` function takes a Single Pass Range of - ``boost::network::http::response_header`` - instances and linearizes them to a buffer with at most - ``BOOST_NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE`` and - immediately schedules an asynchronous write once that is done. +~~~~~~~~~~~~~~~~~ - The function throws an instance of ``std::logic_error`` if you try to set - the headers for a connection more than once. +.. doxygenstruct:: boost::network::http::async_connection + :project: cppnetlib + :members: -Adding SSL support to Asynchronous Server ------------------------------------------ +Adding SSL support to the HTTP Server +------------------------------------- In order to setup SSL support for an Asynchronous Server, it is best to start from a regular Asynchronous Server (see above). Once this server is setup, SSL can be @@ -533,24 +153,25 @@ used are defined in the link. .. code-block:: c++ // Initialize SSL context - boost::shared_ptr ctx = boost::make_shared(boost::asio::ssl::context::sslv23); + std::shared_ptr ctx = + std::make_shared(asio::ssl::context::sslv23); ctx->set_options( - boost::asio::ssl::context::default_workarounds - | boost::asio::ssl::context::no_sslv2 - | boost::asio::ssl::context::single_dh_use); + asio::ssl::context::default_workarounds + | asio::ssl::context::no_sslv3 + | asio::ssl::context::single_dh_use); // Set keys ctx->set_password_callback(password_callback); ctx->use_certificate_chain_file("server.pem"); - ctx->use_private_key_file("server.pem", boost::asio::ssl::context::pem); + ctx->use_private_key_file("server.pem", asio::ssl::context::pem); ctx->use_tmp_dh_file("dh512.pem"); handler_type handler; http_server::options options(handler); - options.thread_pool(boost::make_shared(2)); + options.thread_pool(std::make_shared(2)); http_server server(options.address("127.0.0.1").port("8442").context(ctx)); - std::string password_callback(std::size_t max_length, boost::asio::ssl::context_base::password_purpose purpose) { + std::string password_callback(std::size_t max_length, asio::ssl::context_base::password_purpose purpose) { return std::string("test"); } diff --git a/libs/network/doc/html/_sources/techniques.txt b/libs/network/doc/html/_sources/techniques.txt deleted file mode 100644 index b52bf7e36..000000000 --- a/libs/network/doc/html/_sources/techniques.txt +++ /dev/null @@ -1,12 +0,0 @@ -Techniques -========== - -The :mod:`cpp-netlib` uses several advanced techniques to achieve it's -aims. This chapter describes some of those techniques. - -.. toctree:: - :maxdepth: 1 - - techniques/tag_metafunctions - techniques/directives - techniques/polymorphism diff --git a/libs/network/doc/html/_sources/techniques/directives.txt b/libs/network/doc/html/_sources/techniques/directives.txt deleted file mode 100644 index e40882d95..000000000 --- a/libs/network/doc/html/_sources/techniques/directives.txt +++ /dev/null @@ -1,92 +0,0 @@ -Directives -========== - -The :mod:`cpp-netlib` uses a technique for allowing message-passing -semantics in a chainable fashion in the form of directives. The basic -concept for directives is, in a general sense, an encapsulated -transformation that can be applied to objects that abide by the -directive protocol. - -Using the object-oriented notion of message passing, where an object -accepts a message (usually a function call) we define a simple DSEL in -order for the protocol to be supported by certain object types. In the -:mod:`cpp-netlib` the protocol implemented is similar to that of the -standard iostream formatting system: - -.. code-block:: c++ - - object << directive1(...) - << directive2(...) - ... - << directiveN(...); - -In :mod:`cpp-netlib` the directives are simple function objects that -take a target object as reference and returns a reference to the same -object as a result. In code the directive pattern looks like the -following: - -.. code-block:: c++ - - struct directive_type { - template - Input & operator()(Input & input) const { - // do something to input - return input; - } - }; - -To simplify directive creation, usually factory or generator functions -are defined to return concrete objects of the directive's type. - -.. code-block:: c++ - - inline - directive_type directive(...) { - return directive_type(); - } - -The trivial implementation of the directive protocol then boils down -to the specialization of the shift-left operator on the target type. - -.. code-block:: c++ - - template - inline target_type & operator<< - (target_type & x, Directive const & f) { - return f(x); - } - -.. todo:: - - An example using a directive. - -The rationale for implementing directives include the following: - - * **Encapsulation** - by moving logic into the directive types the - target object's interface can remain rudimentary and even hidden - to the user's immediate attention. Adding this layer of - indirection also allows for changing the underlying - implementations while maintaining the same syntactic and semantic - properties. - * **Flexibility** - by allowing the creation of directives that are - independent from the target object's type, generic operations can - be applied based on the concept being modeled by the target - type. The flexibility also afforded comes in the directive's - generator function, which can also generate different concrete - directive specializations based on parameters to the function. - * **Extensibility** - because the directives are independent of the - target object's type, new directives can be added and supported - without having to change the target object at all. - * **Reuse** - truly generic directives can then be used for a broad - set of target object types that model the same concepts supported - by the directive. Because the directives are self-contained - objects, the state and other object references it keeps are only - accessible to it and can be re-used in different contexts as well. - -Extending a system that uses directives is trivial in header-only -systems because new directives are simply additive. The protocol is -simple and can be applied to a broad class of situations. - -In a header-only library, the static nature of the wiring and chaining -of the operations lends itself to compiler abuse. A deep enough -nesting of the directives can lead to prolonged compilation times. diff --git a/libs/network/doc/html/_sources/techniques/polymorphism.txt b/libs/network/doc/html/_sources/techniques/polymorphism.txt deleted file mode 100644 index d5e42f8c9..000000000 --- a/libs/network/doc/html/_sources/techniques/polymorphism.txt +++ /dev/null @@ -1,92 +0,0 @@ -Static and dynamic polymorphism -=============================== - - -With a header only library, you can only do so much with static -polymorphism alone. There are some situations where you have to handle -dynamic polymorphism because of unavoidable runtime-based decision -making. Although you can deal with the base types that remain static, -behavior can vary greatly which derived type should be handling the -situation based on runtime values. - -This situation comes up in the :mod:`cpp-netlib` when we decide what -kind of connection handler to use for a given HTTP URI -- whether it's -plain HTTP or HTTPS. Although the HTTP semantics are the same for -HTTP and HTTPS the implementation of the connection handler greatly -varies on whether to use a plain TCP connection or an SSL-wrapped TCP -connection. - -The general pattern or technique is to combine tag-based dispatch with -a strategy factory, all while not requiring any externally built -libraries. Doing it in a header-only library requires a little -creativity and additional layers of indirection that you otherwise -will not need for a library with externally built static/dynamic -libraries. - -First we define the base type which we want to support dynamic -behavior with. There's nothing special with the base type, except -that it supports the tag dispatch earlier defined and has a virtual -destructor. In code it looks like this: - -.. code-block:: c++ - - template - struct base { - virtual void foo() = 0; // make this an abstract base - virtual ~base() { - // do the base destructor thing here. - } - }; - -We then define a set of derived types that specialize the -implementation of the ``foo`` member function. To facilitate the -dispatch of the correct type based on an input, we create a strategy -factory function: - -.. code-block:: c++ - - template - unique_ptr > strategy(int input, Tag) { - unique_ptr > ptr; - switch(input) { - case 0: ptr.reset(new derived0()); break; - case 1: ptr.reset(new derived1()); break; - // ... - default: ptr.reset(0); break; - } - return ptr; - } - - unique_ptr > ptr = - strategy(input, default_()); // input is a runtime value - -The strategy factory can be a standalone function, or a static member -of a factory class that is specialized by tag dispatch. This can be -done like the following: - -.. code-block:: c++ - - template - struct strategy; - - template <> - struct strategy { - static unique_ptr > create(int input) { - unique_ptr > ptr; - switch(input) { - case 0: ptr.reset(new derived0()); break; - case 1: ptr.reset(new derived1()); break; - //... - default: ptr.reset(0); break; - } - return ptr; - } - }; - -This approach allows the header-only libraries to define new dynamic -types in subsequent versions of the library while keeping the -static-dynamic bridge fluid. The only down-side to this is the -possibility of derived type explosion in case there are a lot of -different strategies or specializations available -- this though is -not unique to static-dynamic bridging, but is also a problem with pure -object oriented programming with dynamic polymorphism. diff --git a/libs/network/doc/html/_sources/techniques/tag_metafunctions.txt b/libs/network/doc/html/_sources/techniques/tag_metafunctions.txt deleted file mode 100644 index 68edd1449..000000000 --- a/libs/network/doc/html/_sources/techniques/tag_metafunctions.txt +++ /dev/null @@ -1,172 +0,0 @@ -Tag metafunctions -================= - -Sometimes you want to vary a function or a type's behavior based on a -static parameter. In the :mod:`cpp-netlib` there are a number of -things you might want to change based on some such parameter -- like -what the underlying string type should be and how large a buffer -should be, among other things. The primary way to define this in a -header-only manner is to use tag-based metafunctions. - -The skeleton of the approach is based on a similar technique for -defining type traits. In the :mod:`cpp-netlib` however the type traits -are defined on opaque tag types which serve to associate results to a -family of metafunctions. - -Template Specialization ------------------------ - -To illustrate this point, let's define a tag ``default_`` which we use -to denote the default implementation of a certain type ``foo``. For -instance we decide that the default string type we will use for -``default_`` tagged ``foo`` specializations will be an -``std::string``. - -In the :mod:`cpp-netlib` this is done by defining a ``string`` -metafunction type that is specialized on the tag ``default_`` whose -nested ``type`` result is the type ``std::string``. In code this would -translate to: - -.. code-block:: c++ - - template - struct string { - typedef void type; - }; - - struct default_; - - template <> - struct string { - typedef std::string type; - }; - -Template Metaprogramming ------------------------- - -Starting with version 0.7, the tag dispatch mechanism changed slightly to use -Boost.MPL_. The idea is still the same, although we can get a little smarter -than just using template specializations. Instead of just defining an opaque -type ``default_``, we use the Boost.MPL equivalent of a vector to define which -root types of properties this ``default_`` tag supports. The idea is to make the -opaque type ``default_`` inherit property tags which the library supports -internally as definite extension points. - -.. _Boost.MPL: http://www.boost.org/libs/mpl/index.html - -Our definition of the ``default_`` tag will then look something like the -following: - -.. code-block:: c++ - - typedef mpl::vector default_tags; - - template - struct components; - - typedef mpl::inherit_linearly< - default_tags, - mpl::inherit - >::type default_; - - template - struct components { - typedef default_tags type; - }; - -In the above listing, ``default_string`` is what we call a "root" tag which is -meant to be combined with other "root" tags to form composite tags. In this case -our composite tag is the tag ``default_``. There are a number of these "root" -tags that :mod:`cpp-netlib` provides. These are in the namespace -``boost::network::tags`` and are defined in ``boost/network/tags.hpp``. - -Using this technique we change slightly our definition of the ``string`` -metafunction class into this: - -.. code-block:: c++ - - template - struct unsupported_tag; - - template - struct string : - mpl::if_< - is_base_of< - tags::default_string, - Tag - >, - std::string, - unsupported_tag - > - {}; - -Notice that we don't have the typedef for ``type`` in the body of ``string`` -anymore, but we do inherit from ``mpl::if_``. Since ``mpl::if_`` is a template -metafunction itself, it contains a definition of the resulting ``type`` which -``string`` inherits. - -You can see the real definition of the ``string`` metafunction in -``boost/network/traits/string.hpp``. - -Using Tags ----------- - -Once we have the defined tag, we can then use this in the definition of our -types. In the definition of the type ``foo`` we use this type function -``string`` and pass the tag type parameter to determine what to use as -the string type in the context of the type ``foo``. In code this would -translate into: - -.. code-block:: c++ - - template - struct foo { - typedef typename string::type string_type; - - // .. use string_type where you need a string. - }; - -Using this approach we can support different types of strings for -different tags on the type ``foo``. In case we want to use a different -type of string for the tag ``default_`` we only change the -composition of the ``string_tags`` MPL vector. For example, in :mod:`cpp-netlib` -there is a root tag ``default_wstring`` which causes the ``string`` metafunction -to define ``std::wstring`` as the resulting type. - -The approach also allows for the control of the structure and features -of types like ``foo`` based on the specialization of the tag. Whole -type function families can be defined on tags where they are supported -and ignored in cases where they are not. - -To illustrate let's define a new tag ``swappable``. Given the above -definition of ``foo``, we want to make the ``swappable``-tagged -``foo`` define a ``swap`` function that extends the original -``default_``-tagged ``foo``. In code this would look like: - -.. code-block:: c++ - - struct swappable; - - template <> - struct foo : foo { - void swap(foo & other) { - // ... - } - }; - -We also for example want to enable an ADL-reachable ``swap`` function: - -.. code-block:: c++ - - struct swappable; - - inline - void swap(foo & left, foo & right) { - left.swap(right); - } - -Overall what the tag-based definition approach allows is for static -definition of extension points that ensures type-safety and -invariants. This keeps the whole extension mechanism static and yet -flexible. - diff --git a/libs/network/doc/html/contents.html b/libs/network/doc/html/contents.html index af9c12b4d..ce952c360 100644 --- a/libs/network/doc/html/contents.html +++ b/libs/network/doc/html/contents.html @@ -144,48 +144,6 @@

Navigation

-
  • An in-depth look at the cpp-netlib -
  • -
  • Techniques -
  • -
  • Project history -
  • Reference Manual
    • HTTP Client API
      • General
      • @@ -220,16 +178,14 @@

        Navigation

      • HTTP Server API @@ -280,7 +236,7 @@

        Navigation

        diff --git a/libs/network/doc/html/examples.html b/libs/network/doc/html/examples.html index 88fc1c073..767f3579d 100644 --- a/libs/network/doc/html/examples.html +++ b/libs/network/doc/html/examples.html @@ -129,7 +129,7 @@

        Navigation

        diff --git a/libs/network/doc/html/examples/http/atom_reader.html b/libs/network/doc/html/examples/http/atom_reader.html index 8a09a4e34..f833de2c2 100644 --- a/libs/network/doc/html/examples/http/atom_reader.html +++ b/libs/network/doc/html/examples/http/atom_reader.html @@ -175,7 +175,7 @@

        Navigation

        diff --git a/libs/network/doc/html/examples/http/hello_world_client.html b/libs/network/doc/html/examples/http/hello_world_client.html index ba547bf9b..e9ff6a48e 100644 --- a/libs/network/doc/html/examples/http/hello_world_client.html +++ b/libs/network/doc/html/examples/http/hello_world_client.html @@ -192,7 +192,7 @@

        Navigation

        diff --git a/libs/network/doc/html/examples/http/hello_world_server.html b/libs/network/doc/html/examples/http/hello_world_server.html index aee567a99..cdea75e8f 100644 --- a/libs/network/doc/html/examples/http/hello_world_server.html +++ b/libs/network/doc/html/examples/http/hello_world_server.html @@ -242,7 +242,7 @@

        Navigation

        diff --git a/libs/network/doc/html/examples/http/http_client.html b/libs/network/doc/html/examples/http/http_client.html index a3b4ef0c0..b5ef618f8 100644 --- a/libs/network/doc/html/examples/http/http_client.html +++ b/libs/network/doc/html/examples/http/http_client.html @@ -206,7 +206,7 @@

        Navigation

        diff --git a/libs/network/doc/html/examples/http/simple_wget.html b/libs/network/doc/html/examples/http/simple_wget.html index 005e83026..709d941cd 100644 --- a/libs/network/doc/html/examples/http/simple_wget.html +++ b/libs/network/doc/html/examples/http/simple_wget.html @@ -203,7 +203,7 @@

        Navigation

        diff --git a/libs/network/doc/html/examples/http/twitter_search.html b/libs/network/doc/html/examples/http/twitter_search.html index 7e526d8eb..62018b073 100644 --- a/libs/network/doc/html/examples/http/twitter_search.html +++ b/libs/network/doc/html/examples/http/twitter_search.html @@ -25,7 +25,7 @@ - + @@ -40,7 +40,7 @@

        Navigation

        • - next
        • Previous topic

          Atom feed reader

          Next topic

          -

          An in-depth look at the cpp-netlib

          +

          Reference Manual

          diff --git a/libs/network/doc/html/getting_started.html b/libs/network/doc/html/getting_started.html index 6bd8f7c00..3c8a000cc 100644 --- a/libs/network/doc/html/getting_started.html +++ b/libs/network/doc/html/getting_started.html @@ -350,7 +350,7 @@

          Navigation

          diff --git a/libs/network/doc/html/history.html b/libs/network/doc/html/history.html deleted file mode 100644 index 271921c2a..000000000 --- a/libs/network/doc/html/history.html +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - - - Project history — cpp-netlib v0.11.2 - - - - - - - - - - - - - - - - - - - - -
          -
          -
          -
          - -
          -

          Project history¶

          -

          The cpp-netlib was founded by Dean Michael Berris in 2007. -Initially it consisted of a message template and an HTTP client. It -found a home on Sourceforge but was migrated at the end of 2009 to -Github where development is actively continued by a committed -community.

          -
          -

          Motivation¶

          -

          We’re a group of C++ developers and we kept becoming annoyed that we -had to repeatedly write the same code when building applications that -needed to be network-aware.

          -

          We found that there was a lack of accessible networking libraries, -either standard or open source, that fulfilled our needs. Such -libraries exist for every other major language. So, building on top -of Boost.Asio, we decided to get together and build our own.

          -
          -
          -

          Objectives¶

          -

          The objectives of the cpp-netlib are to:

          -
            -
          • develop a high quality, portable, easy to use C++ networking library
          • -
          • enable developers to easily extend the library
          • -
          • lower the barrier to entry for cross-platform network-aware C++ -applications
          • -
          -

          The goal the of cpp-netlib has never been to build a -fully-featured web server - there are plenty of excellent options -already available. The niche that this library targets is for -light-weight networking functionality for C++ applications that have -demanding performance requirements or memory constraints, but that -also need to be portable. This type of application is becoming -increasingly common as software becomes more distributed, and -applications need to communicate with services.

          -

          While many languages provide direct library support for high level -network programming, this feature is missing in C++. Therefore, this -library has been developed with the intention of eventually being -submitted to Boost, a collection of general, high quality -libraries for C++ developers.

          -

          Eventually, the cpp-netlib will be extended to support many of -the application layer protocols such as SMTP, FTP, SOAP, XMPP etc.

          -
          -
          - - -
          -
          -
          - -
          -
          - - - - \ No newline at end of file diff --git a/libs/network/doc/html/in_depth.html b/libs/network/doc/html/in_depth.html deleted file mode 100644 index 0a4148354..000000000 --- a/libs/network/doc/html/in_depth.html +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - An in-depth look at the cpp-netlib — cpp-netlib v0.11.2 - - - - - - - - - - - - - - - - - - - - -
          -
          -
          -
          - -
          -

          An in-depth look at the cpp-netlib¶

          -

          The cpp-netlib is composed of three different sets of -functionality: a message template, a URI template and -different protocol implementations.

          - -
          - - -
          -
          -
          - -
          -
          - - - - \ No newline at end of file diff --git a/libs/network/doc/html/in_depth/http.html b/libs/network/doc/html/in_depth/http.html deleted file mode 100644 index c0fca35a9..000000000 --- a/libs/network/doc/html/in_depth/http.html +++ /dev/null @@ -1,311 +0,0 @@ - - - - - - - - HTTP implementation — cpp-netlib v0.11.2 - - - - - - - - - - - - - - - - - - - - - -
          -
          -
          -
          - -
          -

          HTTP implementation¶

          -
          -

          HTTP client¶

          -

          At the heart of the HTTP client implementation is a single class aptly named -basic_client, which is also a template. The template basic_client takes -three template parameters:

          -
          namespace boost { namespace http {
          -
          -    template <class Tag, unsigned version_major, unsigned version_minor>
          -    struct basic_client;
          -
          -} // namespace http
          -
          -} // namespace boost
          -
          -
          -

          The Tag template parameter follows the same tag-dispatch mechanism to -determine the behavior of the basic_client. The interface of -basic_client may change depending on certain properties defined for the tag -you provide. Below is a table of predefined supported tags you can use in your -overload of the basic_client:

          -
          - ---- - - - - - - - - - - - - - - - - - - - - - - - - - -
          TagDescription
          http_default_8bit_tcp_resolveThis is the default HTTP implementation tag -that resolves addresses with a TCP resolver -and provides a synchronous/blocking HTTP -client interface.
          http_default_8bit_udp_resolveThis is similar to the above tag except that -it specifies the HTTP client to use a UDP -resolver. It also provides a synchronous/ -blocking HTTP client interface.
          http_keepalive_8bit_tcp_resolveThis tag specifies that the HTTP client by -default will keep connections to the server -alive. It only makes sense if the -version_major and version_minor are -both 1, to indicate HTTP 1.1. This tag -causes the HTTP client to resolve using a -TCP resolver and provides a synchronous/ -blocking HTTP client interface.
          http_keepalive_8bit_udp_resolveThis is similar to the above tag except that -it specifies the HTTP client to use a UDP -resolver. It also provides a synchronous/ -blocking HTTP client interface.
          http_async_8bit_tcp_resolveThis tag provides an active HTTP client -object implementation that uses a TCP -resolver. Response objects returned will -encapsulate a number of Boost.Thread -shared futures to hold values. Users don’t -have to see this as they are implementation -details.
          http_async_8bit_udp_resolveThis is similar to the above tag except that -specifies the HTTP client to use a UDP -resolver.
          -

          The default typedef for the HTTP client that is provided uses the -http_async_8bit_udp_resolve tag, and implements HTTP 1.1. The exact -typedef is in the boost::network::http namespace as the following:

          -
          namespace boost { namespace network { namespace http {
          -
          -    typedef basic_client<tags::http_async_8bit_udp_resolve, 1, 1>
          -        client;
          -
          -}}}
          -
          -
          -

          This type has nested typedefs for the correct types for the basic_request -and basic_response templates. To use the correct types for basic_request -or basic_response you can use these nested typedefs like so:

          -
          boost::network::http::client::request request;
          -boost::network::http::client::response response;
          -
          -// or...
          -using namespace boost::network;
          -http::client::request request;
          -http::client::response response;
          -
          -
          -

          Typical use cases for the HTTP client would look something like the following:

          -
          using namespace boost::network;
          -http::request request("http://www.boost.org/");
          -request << header("Connection", "close");
          -
          -
          -

          The basic_client implements all HTTP methods as member functions -(HEAD, GET, POST, PUT, DELETE). Therefore, the code to make an HTTP -request looks trivially simple:

          -
          using namespace boost::network;
          -http::client client;
          -http::client::request request("http://www.boost.org/");
          -http::client::response response = client.get(request);
          -
          -
          -

          Accessing data from http::response is done using wrappers. -To get the response headers, we use the headers wrapper which -returns, in the default case, a multimap of strings to strings:

          -
          using namespace boost::network;
          -typedef headers_range<http_client::response>::type response_headers;
          -boost::range_iterator<response_headers>::type iterator;
          -
          -response_headers headers_ = headers(response);
          -for (iterator it = headers_.begin(); it != headers_.end(); ++it) {
          -    std::cout << it->first << ": " << it->second << std::endl;
          -}
          -std::cout << std::endl;
          -
          -
          -
          -
          -

          HTTP server¶

          -

          As with the HTTP client, the HTTP server that is provided with -cpp-netlib is extensible through the tag mechanism and is embeddable. -The template class declaration of basic_server is given below:

          -
          namespace boost { namespace network { namespace http {
          -
          -    template <class Tag, class RequestHandler> basic_server;
          -
          -}}}
          -
          -
          -

          The second template argument is used to specify the request handler -type. The request handler type is a functor type which should overload -the function call operator (RequestHandler::operator() should be -overloaded) that takes two parameters: the first one being a reference -to a const basic_request<Tag> and the second being a reference to -a basic_response<Tag> instance.

          -

          All the logic for parsing the HTTP request and building the const -basic_request<Tag> object resides internally in the basic_server -template. Processing the request is delegated to the -RequestHandler type, and the assumption of which would be that the -response is formed inside the RequestHandler function call -operator overload.

          -

          The basic_server template however is only an underlying -implementation while the user-visible implementation is the -http::server template. This simply specializes the -basic_server template to use the default_ tag and forwards the -RequestHandler parameter:

          -
          namespace boost { namespace network { namespace http {
          -
          -    template <class RequestHandler>
          -    class server :
          -        public basic_server<default_, RequestHandler> {};
          -
          -}}}
          -
          -
          -

          To use the forwarding server type you just supply the request handler -implementation as the parameter. For example, an “echo” server example -might look something like this:

          -
          using namespace boost::network;
          -struct echo;
          -typedef http::server<echo> echo_server;
          -
          -struct echo {
          -    void operator () (const echo_server::request &request,
          -                      echo_server::response &response) const {
          -        std::string ip = source(request);
          -        response = echo_server::response::stock_reply(
          -            echo_server::response::ok,
          -            body(request));
          -        std::cerr << "[" << ip << "]: " << request.uri <<
          -            " status = " << echo_server::response::ok << '\n';
          -    }
          -};
          -
          -
          -

          Here, all we’re doing is returning the original request body with an -HTTP OK response (200). We are also printing the IP address from where the -request came from. Notice that we are using a wrapper to access the source of -the request.

          -
          -
          - - -
          -
          -
          - -
          -
          - - - - \ No newline at end of file diff --git a/libs/network/doc/html/in_depth/http_client_tags.html b/libs/network/doc/html/in_depth/http_client_tags.html deleted file mode 100644 index e7f75be59..000000000 --- a/libs/network/doc/html/in_depth/http_client_tags.html +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - - - <no title> — cpp-netlib v0.11.2 - - - - - - - - - - - - - - - - - - -
          -
          -
          -
          - - ---- - - - - - - - - - - - - - - - - - - - - - - - - - -
          TagDescription
          http_default_8bit_tcp_resolveThis is the default HTTP implementation tag -that resolves addresses with a TCP resolver -and provides a synchronous/blocking HTTP -client interface.
          http_default_8bit_udp_resolveThis is similar to the above tag except that -it specifies the HTTP client to use a UDP -resolver. It also provides a synchronous/ -blocking HTTP client interface.
          http_keepalive_8bit_tcp_resolveThis tag specifies that the HTTP client by -default will keep connections to the server -alive. It only makes sense if the -version_major and version_minor are -both 1, to indicate HTTP 1.1. This tag -causes the HTTP client to resolve using a -TCP resolver and provides a synchronous/ -blocking HTTP client interface.
          http_keepalive_8bit_udp_resolveThis is similar to the above tag except that -it specifies the HTTP client to use a UDP -resolver. It also provides a synchronous/ -blocking HTTP client interface.
          http_async_8bit_tcp_resolveThis tag provides an active HTTP client -object implementation that uses a TCP -resolver. Response objects returned will -encapsulate a number of Boost.Thread -shared futures to hold values. Users don’t -have to see this as they are implementation -details.
          http_async_8bit_udp_resolveThis is similar to the above tag except that -specifies the HTTP client to use a UDP -resolver.
          - - -
          -
          -
          - -
          -
          - - - - \ No newline at end of file diff --git a/libs/network/doc/html/in_depth/message.html b/libs/network/doc/html/in_depth/message.html deleted file mode 100644 index 8951f6e90..000000000 --- a/libs/network/doc/html/in_depth/message.html +++ /dev/null @@ -1,399 +0,0 @@ - - - - - - - - The message template — cpp-netlib v0.11.2 - - - - - - - - - - - - - - - - - - - - - -
          -
          -
          -
          - -
          -

          The message template¶

          -

          One of the core components in the library is the concept and the -implementation of a common message type. In most (not all) network -protocols, the concept of a message is central to the definition of -the protocol. In HTTP, SMTP, XMPP, and even other protocols like SNMP -and ICMP, there is a common notion of a “packet” or a message. In -cpp-netlib we chose to implement the concept of a message that has the -following common parts:

          -
          -
            -
          • Source - every message has a source identifier which varies -from protocol to protocol.
          • -
          • Destination - every message has a destination identifier which -varies from protocol to protocol.
          • -
          • Headers - each message is assumed to contain headers, which -may be empty in cases where the protocol does not support it, but -is nonetheless supported by cpp-netlib messages.
          • -
          • Body - the content area of a message which varies from -protocol to protocol (also sometimes referred to as payload).
          • -
          -
          -

          This division is purely logical – in the underlying implementation, -the message type can choose to have different means of storing the -data, depending on the type used to tag the message. This section -covers the Message Concept as well as the basic_message -implementation.

          -
          -

          Message Concept¶

          -
          -

          Warning

          -

          The Message framework is deprecated in the 0.11 release, and will -be removed in future versions of the library.

          -
          -

          The Message Concept specifies what the valid operations on a message -are as well as what messages look like semantically. The following -table summarize the operations and syntactic as well as semantic -properties of messages.

          -

          Legend

          - --- - - - - - - - - - - - - - - - - - - - -
          M:The message type.
          H:A headers container type.
          m,n:An instance of M.
          S:A string type.
          s,k,v:An instance of S.
          O:The source type.
          D:The destination type.
          B:The body type.
          T:The Tag type.
          - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          ConstructResultDescription
          typename M::tagTThe nested tag type.
          M()Instance of MDefault constructible.
          M(m)Instance of MCopy constructible.
          m = n;Reference to mAssignable.
          swap(m, n);voidSwappable.
          source(m);Convertible to ORetrieve the source of m.
          destination(m);Convertible to DRetrieve the destination of m.
          headers(m);Convertible to HRetrieve the headers of m.
          body(m);Convertible to BRetrieve the body of m.
          m << source(s);M &Set the source of m.
          m << destination(s);M &Set the destination of m.
          m << header(k, v);M &Add a header to m.
          m << remove_header(k);M &Remove a header from m.
          m << body(s);M &Set the body of m.
          source(m,s);voidSet the source of m.
          destination(m,s);voidSet the destination of m.
          add_header(m, k, v);voidAdd a header to m.
          remove_header(m, k);voidRemove a header from m.
          clear_headers(m);voidClear the headers of m.
          body(m,s);M &Set the body of m.
          -

          Types that model the Message Concept are meant to encapsulate data -that has a source, a destination, one or more named headers, and a -body/payload. Because the accessors and the directives are not -required to be part of the message type that models the Message -Concept, a message can be implemented as a POD type and have all -manipulations performed in the directive implementations, as well as -value transformations done in the accessors.

          -
          -
          -

          Directives, Modifiers, and Wrappers¶

          -

          In the Message Concept definition there are three basic constructs that follow a -certain pattern. These patterns are Directives, Modifiers, and Wrappers.

          -
          -

          Directives¶

          -

          A directive is a function object that is applied to a Message. Directives -encapsulate a set of operations that apply to messages. The general requirement -for a Directive is that it should apply these operations on a message.

          -

          A directive may dispatch on the type of the message passed to it at the point of -the function call. Typically, directives are generated using a factory function -that returns the correct directive type.

          -

          For a given directive foo_directive a generator function called foo is -typically implemented:

          -
          struct foo_directive {
          -    template <class Message>
          -    Message & operator()(Message & m) const {
          -        // do something to m
          -        return m;
          -    }
          -};
          -
          -foo_directive const foo() {
          -    return foo_directive();
          -}
          -
          -// to apply a directive, we use the << operator
          -message m;
          -m << foo();
          -
          -
          -
          -
          -

          Modifiers¶

          -

          A modifier is generally defined as a free function that takes a reference to a -non-const lvalue message as the first parameter, and any number of parameters. -In the concept definition of the Message Concept, a modifier follows the form:

          -
          modifier(message, ...)
          -
          -
          -

          Modifiers are meant to imply modifications on a message, which also allows for -easier dispatch based on Argument Dependent Lookup (ADL) on the type of the -message. Note that Directives can be implemented in terms of Modifiers and -vice versa, although that is not required nor specified.

          -
          -
          -

          Wrappers¶

          -

          A Wrapper is basically an implementation detail that ensures that a given -message, when wrapped, can be converted to the associated part of the message. A -wrapper has a type that encapsulates the conversion logic from a message to a -given type.

          -

          An example of a Wrapper would be source_wrapper which would be returned by a -call to the wrapper generator function source. An example implementation of -the source_wrapper would look like:

          -
          template <class Tag, template <class> class Message>
          -struct source_wrapper {
          -    Message<Tag> const & m;
          -    explicit source_wrapper(Message<Tag> const & m)
          -    : m(m) {}
          -    typedef typename source<Tag>::type source_type;
          -    operator source_type const & () {
          -        return m.source;
          -    }
          -    operator source_type const () {
          -        return m.source;
          -    }
          -    operator source_type () {
          -        return m.source;
          -    }
          -};
          -
          -template <class Tag, template <class> class Message>
          -source_wrapper<Tag, Message> const
          -source(Message<Tag> const & message) {
          -    return source_wrapper<Tag, Message>(message);
          -}
          -
          -
          -

          This pattern is similar to an adapter, but the specific notion of wrapping a -data type (in this case, an object of a type that models the Message Concept) -using an intermediary wrapper is what is pertained to by the Wrapper pattern. -In this case, the Wrapper is source_wrapper while source is merely a -wrapper generator function.

          -
          -
          -
          -

          basic_message¶

          -

          The default implementation of a simple type that models the Message -Concept is available in cpp-netlib. This default implementation is -named basic_message which supports a Tag template -parameter. The definition of basic_message looks like this:

          -
          template <class Tag>
          -class basic_message;
          -
          -
          -

          The basic_message template requires that the following -tag-dispatched metafunctions are defined for the type Tag:

          -
          template <class Tag>
          -struct string;
          -
          -template <class Tag>
          -struct headers_container;
          -
          -
          -

          All the operations defined by the message concept are implemented by -this basic message type. Other message implementations can either use -this common message type or specialize it according to whether they -want to use different containers or whether it’s going to be just a -POD type.

          -
          -
          - - -
          -
          -
          - -
          -
          - - - - \ No newline at end of file diff --git a/libs/network/doc/html/in_depth/uri.html b/libs/network/doc/html/in_depth/uri.html deleted file mode 100644 index fc59ce7d0..000000000 --- a/libs/network/doc/html/in_depth/uri.html +++ /dev/null @@ -1,295 +0,0 @@ - - - - - - - - The URI class — cpp-netlib v0.11.2 - - - - - - - - - - - - - - - - - - - - - -
          -
          -
          -
          - -
          -

          The URI class¶

          -

          In addition to protocol implementations, the cpp-netlib -provides a powerful URI class. The class implements a parser based -on RFC 3986 and RFC 2732.

          -
          -

          Generic URI syntax overview¶

          -

          A generic URI will take the form:

          -
          [scheme:]scheme-specific-part[#fragment]
          -
          -
          -

          A URI is known as absolute if it specifies the scheme. Otherwise, -it is known as a relative URI. Currently, uri supports only -absolute URIs.

          -

          URIs can be further classified according to whether they’re -hierarchical or opaque (non-hierarchical).

          -

          Some examples of non-hierarchical URIs include:

          -
          mailto:john.doe@example.com
          -news:comp.infosystems.www.servers.unix
          -tel:+1-816-555-1212
          -
          -
          -

          The data following the first ":" is said to be opaque to the URI -parser and requires no further parsing. By way of example, the -following shows how a non-hierarchical URI is processed by the parser -by defining everything after the ":" to be a part of the path:

          -../_images/mailto_uri.png -

          A hierarchical URI is identified by a double slash ("//") after -the scheme and a scheme-specific component, which RFC 3986 defines -to be:

          -
          [scheme:][//authority][path][?query][#fragment]
          -
          -
          -

          The authority component can be further broken down to:

          -
          [user_info@]host[:port]
          -
          -
          -

          Examples of hierarchical URIs include:

          -
          http://www.boost.org/
          -file:///bin/bash
          -
          -
          -

          The following example, describing a complex URI using FTP, shows how -a URI is broken down by the parser:

          -../_images/ftp_uri.png -

          Note that the authority is further subdivided into different -elements. Another example, using HTTP is given below:

          -../_images/http_uri.png -

          The difference here between the path in a hierarchical URI and that in -the example above for the non-hierarchical URI.

          -
          -
          -

          The uri class¶

          -

          As of version 0.9.3, uri supplies a URI parser and builder. -To use the parser, it’s as simple as supplying a string to the -constructor:

          -
          using namespace boost::network;
          -uri::uri instance("http://cpp-netlib.github.com/");
          -assert(instance.is_valid());
          -std::cout << "scheme: " << instance.scheme() << std::endl
          -          << "host: " << instance.host() << std::endl;
          -
          -
          -

          The command-line output of this program will be:

          -
          scheme: http
          -host: cpp-netlib.github.com
          -
          -
          -
          -
          -

          The uri builder¶

          -

          uri support a stream style syntax to create a URI from it’s -elements. For example the program:

          -
          #include <iostream>
          -#include <boost/network/uri.hpp>
          -#include <boost/network/uri/uri_io.hpp>
          -using namespace boost::network;
          -
          -int main() {
          -    uri::uri url;
          -    url << uri::scheme("http")
          -        << uri::host("www.github.com")
          -        << uri::path("/cpp-netlib");
          -    std::cout << url << std::endl;
          -    return 0;
          -}
          -
          -
          -

          will output:

          -
          http://www.github.com/cpp-netlib
          -
          -
          -
          -
          -

          URI Concept¶

          -

          Legend

          - --- - - - - - - - - - - - -
          U:The URI type.
          u,u_:An instance of M.
          S:A string type.
          s,v:An instance of S.
          T:The Tag type.
          - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          ConstructResultDescription
          U(u)Instance of UCopy constructible.
          U(s)Instance of UConstructible from string.
          u = u_;Reference to uAssignable.
          u = s;Reference to uAssignable from string.
          swap(u, u_);voidSwappable.
          scheme(u);Convertible to SRetrieve the URI scheme of u.
          user_info(u);Convertible to SRetrieve the user info of u.
          host(u);Convertible to SRetrieve the host of u.
          port(u);Convertible to HRetrieve the port of u.
          path(u);Convertible to SRetrieve the path of u.
          query(u);Convertible to SRetrieve the query string of u.
          fragment(u);Convertible to SRetrieve the fragment of u.
          -
          -
          - - -
          -
          -
          - -
          -
          - - - - \ No newline at end of file diff --git a/libs/network/doc/html/index.html b/libs/network/doc/html/index.html index 17217be76..6627ee1cc 100644 --- a/libs/network/doc/html/index.html +++ b/libs/network/doc/html/index.html @@ -137,7 +137,6 @@

          Want to learn more?Take a look at the getting started guide

        • Learn from some simple examples
        • Find out what’s new
        • -
        • Study the library in more depth
        • Discover more through the full reference
        • Full table of contents
        @@ -203,7 +202,7 @@

        Navigation

        diff --git a/libs/network/doc/html/objects.inv b/libs/network/doc/html/objects.inv index 40077345c..16d62166a 100644 Binary files a/libs/network/doc/html/objects.inv and b/libs/network/doc/html/objects.inv differ diff --git a/libs/network/doc/html/reference.html b/libs/network/doc/html/reference.html index e98115678..1206f38f7 100644 --- a/libs/network/doc/html/reference.html +++ b/libs/network/doc/html/reference.html @@ -25,7 +25,7 @@ - + - - - - - - -
        -
        -
        -
        - -
        -

        Techniques¶

        -

        The cpp-netlib uses several advanced techniques to achieve it’s -aims. This chapter describes some of those techniques.

        - -
        - - -
        -
        -
        - -
        -
        - - - - \ No newline at end of file diff --git a/libs/network/doc/html/techniques/directives.html b/libs/network/doc/html/techniques/directives.html deleted file mode 100644 index 5323d47cd..000000000 --- a/libs/network/doc/html/techniques/directives.html +++ /dev/null @@ -1,191 +0,0 @@ - - - - - - - - Directives — cpp-netlib v0.11.2 - - - - - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Directives¶

        -

        The cpp-netlib uses a technique for allowing message-passing -semantics in a chainable fashion in the form of directives. The basic -concept for directives is, in a general sense, an encapsulated -transformation that can be applied to objects that abide by the -directive protocol.

        -

        Using the object-oriented notion of message passing, where an object -accepts a message (usually a function call) we define a simple DSEL in -order for the protocol to be supported by certain object types. In the -cpp-netlib the protocol implemented is similar to that of the -standard iostream formatting system:

        -
        object << directive1(...)
        -       << directive2(...)
        -       ...
        -       << directiveN(...);
        -
        -
        -

        In cpp-netlib the directives are simple function objects that -take a target object as reference and returns a reference to the same -object as a result. In code the directive pattern looks like the -following:

        -
        struct directive_type {
        -    template <class Input>
        -    Input & operator()(Input & input) const {
        -        // do something to input
        -        return input;
        -    }
        -};
        -
        -
        -

        To simplify directive creation, usually factory or generator functions -are defined to return concrete objects of the directive’s type.

        -
        inline
        -directive_type directive(...) {
        -    return directive_type();
        -}
        -
        -
        -

        The trivial implementation of the directive protocol then boils down -to the specialization of the shift-left operator on the target type.

        -
        template <class Directive>
        -inline target_type & operator<<
        -(target_type & x, Directive const & f) {
        -    return f(x);
        -}
        -
        -
        -
        -

        Todo

        -

        An example using a directive.

        -
        -

        The rationale for implementing directives include the following:

        -
        -
          -
        • Encapsulation - by moving logic into the directive types the -target object’s interface can remain rudimentary and even hidden -to the user’s immediate attention. Adding this layer of -indirection also allows for changing the underlying -implementations while maintaining the same syntactic and semantic -properties.
        • -
        • Flexibility - by allowing the creation of directives that are -independent from the target object’s type, generic operations can -be applied based on the concept being modeled by the target -type. The flexibility also afforded comes in the directive’s -generator function, which can also generate different concrete -directive specializations based on parameters to the function.
        • -
        • Extensibility - because the directives are independent of the -target object’s type, new directives can be added and supported -without having to change the target object at all.
        • -
        • Reuse - truly generic directives can then be used for a broad -set of target object types that model the same concepts supported -by the directive. Because the directives are self-contained -objects, the state and other object references it keeps are only -accessible to it and can be re-used in different contexts as well.
        • -
        -
        -

        Extending a system that uses directives is trivial in header-only -systems because new directives are simply additive. The protocol is -simple and can be applied to a broad class of situations.

        -

        In a header-only library, the static nature of the wiring and chaining -of the operations lends itself to compiler abuse. A deep enough -nesting of the directives can lead to prolonged compilation times.

        -
        - - -
        -
        -
        - -
        -
        - - - - \ No newline at end of file diff --git a/libs/network/doc/html/techniques/polymorphism.html b/libs/network/doc/html/techniques/polymorphism.html deleted file mode 100644 index 7f0cceb55..000000000 --- a/libs/network/doc/html/techniques/polymorphism.html +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - - - Static and dynamic polymorphism — cpp-netlib v0.11.2 - - - - - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Static and dynamic polymorphism¶

        -

        With a header only library, you can only do so much with static -polymorphism alone. There are some situations where you have to handle -dynamic polymorphism because of unavoidable runtime-based decision -making. Although you can deal with the base types that remain static, -behavior can vary greatly which derived type should be handling the -situation based on runtime values.

        -

        This situation comes up in the cpp-netlib when we decide what -kind of connection handler to use for a given HTTP URI – whether it’s -plain HTTP or HTTPS. Although the HTTP semantics are the same for -HTTP and HTTPS the implementation of the connection handler greatly -varies on whether to use a plain TCP connection or an SSL-wrapped TCP -connection.

        -

        The general pattern or technique is to combine tag-based dispatch with -a strategy factory, all while not requiring any externally built -libraries. Doing it in a header-only library requires a little -creativity and additional layers of indirection that you otherwise -will not need for a library with externally built static/dynamic -libraries.

        -

        First we define the base type which we want to support dynamic -behavior with. There’s nothing special with the base type, except -that it supports the tag dispatch earlier defined and has a virtual -destructor. In code it looks like this:

        -
        template <class Tag>
        -struct base {
        -    virtual void foo() = 0; // make this an abstract base
        -    virtual ~base() {
        -        // do the base destructor thing here.
        -    }
        -};
        -
        -
        -

        We then define a set of derived types that specialize the -implementation of the foo member function. To facilitate the -dispatch of the correct type based on an input, we create a strategy -factory function:

        -
        template <class Tag>
        -unique_ptr<base<Tag> > strategy(int input, Tag) {
        -    unique_ptr<base<Tag> > ptr;
        -    switch(input) {
        -        case 0: ptr.reset(new derived0()); break;
        -        case 1: ptr.reset(new derived1()); break;
        -        // ...
        -        default: ptr.reset(0); break;
        -    }
        -    return ptr;
        -}
        -
        -unique_ptr<base<default_> > ptr =
        -    strategy(input, default_()); // input is a runtime value
        -
        -
        -

        The strategy factory can be a standalone function, or a static member -of a factory class that is specialized by tag dispatch. This can be -done like the following:

        -
        template <class Tag>
        -struct strategy;
        -
        -template <>
        -struct strategy<default_> {
        -    static unique_ptr<base<default_> > create(int input) {
        -        unique_ptr<base<default_> > ptr;
        -        switch(input) {
        -            case 0: ptr.reset(new derived0()); break;
        -            case 1: ptr.reset(new derived1()); break;
        -            //...
        -            default: ptr.reset(0); break;
        -        }
        -        return ptr;
        -    }
        -};
        -
        -
        -

        This approach allows the header-only libraries to define new dynamic -types in subsequent versions of the library while keeping the -static-dynamic bridge fluid. The only down-side to this is the -possibility of derived type explosion in case there are a lot of -different strategies or specializations available – this though is -not unique to static-dynamic bridging, but is also a problem with pure -object oriented programming with dynamic polymorphism.

        -
        - - -
        -
        -
        - -
        -
        - - - - \ No newline at end of file diff --git a/libs/network/doc/html/techniques/tag_metafunctions.html b/libs/network/doc/html/techniques/tag_metafunctions.html deleted file mode 100644 index 45274f5f4..000000000 --- a/libs/network/doc/html/techniques/tag_metafunctions.html +++ /dev/null @@ -1,265 +0,0 @@ - - - - - - - - Tag metafunctions — cpp-netlib v0.11.2 - - - - - - - - - - - - - - - - - - - - - -
        -
        -
        -
        - -
        -

        Tag metafunctions¶

        -

        Sometimes you want to vary a function or a type’s behavior based on a -static parameter. In the cpp-netlib there are a number of -things you might want to change based on some such parameter – like -what the underlying string type should be and how large a buffer -should be, among other things. The primary way to define this in a -header-only manner is to use tag-based metafunctions.

        -

        The skeleton of the approach is based on a similar technique for -defining type traits. In the cpp-netlib however the type traits -are defined on opaque tag types which serve to associate results to a -family of metafunctions.

        -
        -

        Template Specialization¶

        -

        To illustrate this point, let’s define a tag default_ which we use -to denote the default implementation of a certain type foo. For -instance we decide that the default string type we will use for -default_ tagged foo specializations will be an -std::string.

        -

        In the cpp-netlib this is done by defining a string -metafunction type that is specialized on the tag default_ whose -nested type result is the type std::string. In code this would -translate to:

        -
        template <class Tag>
        -struct string {
        -    typedef void type;
        -};
        -
        -struct default_;
        -
        -template <>
        -struct string<default_> {
        -    typedef std::string type;
        -};
        -
        -
        -
        -
        -

        Template Metaprogramming¶

        -

        Starting with version 0.7, the tag dispatch mechanism changed slightly to use -Boost.MPL. The idea is still the same, although we can get a little smarter -than just using template specializations. Instead of just defining an opaque -type default_, we use the Boost.MPL equivalent of a vector to define which -root types of properties this default_ tag supports. The idea is to make the -opaque type default_ inherit property tags which the library supports -internally as definite extension points.

        -

        Our definition of the default_ tag will then look something like the -following:

        -
        typedef mpl::vector<default_string> default_tags;
        -
        -template <class Tag>
        -struct components;
        -
        -typedef mpl::inherit_linearly<
        -    default_tags,
        -    mpl::inherit<mpl::placeholders::_1, mpl::placeholders::_2>
        -    >::type default_;
        -
        -template <class Tag>
        -struct components<default_> {
        -    typedef default_tags type;
        -};
        -
        -
        -

        In the above listing, default_string is what we call a “root” tag which is -meant to be combined with other “root” tags to form composite tags. In this case -our composite tag is the tag default_. There are a number of these “root” -tags that cpp-netlib provides. These are in the namespace -boost::network::tags and are defined in boost/network/tags.hpp.

        -

        Using this technique we change slightly our definition of the string -metafunction class into this:

        -
        template <class Tag>
        -struct unsupported_tag;
        -
        -template <class Tag>
        -struct string :
        -    mpl::if_<
        -        is_base_of<
        -            tags::default_string,
        -            Tag
        -        >,
        -        std::string,
        -        unsupported_tag<Tag>
        -    >
        -{};
        -
        -
        -

        Notice that we don’t have the typedef for type in the body of string -anymore, but we do inherit from mpl::if_. Since mpl::if_ is a template -metafunction itself, it contains a definition of the resulting type which -string inherits.

        -

        You can see the real definition of the string metafunction in -boost/network/traits/string.hpp.

        -
        -
        -

        Using Tags¶

        -

        Once we have the defined tag, we can then use this in the definition of our -types. In the definition of the type foo we use this type function -string and pass the tag type parameter to determine what to use as -the string type in the context of the type foo. In code this would -translate into:

        -
        template <class Tag>
        -struct foo {
        -    typedef typename string<Tag>::type string_type;
        -
        -    // .. use string_type where you need a string.
        -};
        -
        -
        -

        Using this approach we can support different types of strings for -different tags on the type foo. In case we want to use a different -type of string for the tag default_ we only change the -composition of the string_tags MPL vector. For example, in cpp-netlib -there is a root tag default_wstring which causes the string metafunction -to define std::wstring as the resulting type.

        -

        The approach also allows for the control of the structure and features -of types like foo based on the specialization of the tag. Whole -type function families can be defined on tags where they are supported -and ignored in cases where they are not.

        -

        To illustrate let’s define a new tag swappable. Given the above -definition of foo, we want to make the swappable-tagged -foo define a swap function that extends the original -default_-tagged foo. In code this would look like:

        -
        struct swappable;
        -
        -template <>
        -struct foo<swappable> : foo<default_> {
        -    void swap(foo<swappable> & other) {
        -        // ...
        -    }
        -};
        -
        -
        -

        We also for example want to enable an ADL-reachable swap function:

        -
        struct swappable;
        -
        -inline
        -void swap(foo<swappable> & left, foo<swappable> & right) {
        -    left.swap(right);
        -}
        -
        -
        -

        Overall what the tag-based definition approach allows is for static -definition of extension points that ensures type-safety and -invariants. This keeps the whole extension mechanism static and yet -flexible.

        -
        -
        - - -
        -
        -
        - -
        -
        - - - - \ No newline at end of file diff --git a/libs/network/doc/html/whats_new.html b/libs/network/doc/html/whats_new.html index 4cdee36af..b08baf7be 100644 --- a/libs/network/doc/html/whats_new.html +++ b/libs/network/doc/html/whats_new.html @@ -358,7 +358,7 @@

        Navigation

        diff --git a/libs/network/doc/in_depth.rst b/libs/network/doc/in_depth.rst deleted file mode 100644 index 39af9a4f4..000000000 --- a/libs/network/doc/in_depth.rst +++ /dev/null @@ -1,15 +0,0 @@ -.. _in_depth: - -An in-depth look at the :mod:`cpp-netlib` -========================================= - -The :mod:`cpp-netlib` is composed of three different sets of -functionality: a **message** template, a **URI** template and -different **protocol** implementations. - -.. toctree:: - :maxdepth: 2 - - in_depth/message - in_depth/uri - in_depth/http diff --git a/libs/network/doc/in_depth/http.rst b/libs/network/doc/in_depth/http.rst deleted file mode 100644 index 711bf6b3e..000000000 --- a/libs/network/doc/in_depth/http.rst +++ /dev/null @@ -1,180 +0,0 @@ -HTTP implementation -=================== - -HTTP client -``````````` - -At the heart of the HTTP client implementation is a single class aptly named -``basic_client``, which is also a template. The template ``basic_client`` takes -three template parameters: - -.. code-block:: c++ - - namespace boost { namespace http { - - template - struct basic_client; - - } // namespace http - - } // namespace boost - -The ``Tag`` template parameter follows the same tag-dispatch mechanism to -determine the behavior of the ``basic_client``. The interface of -``basic_client`` may change depending on certain properties defined for the tag -you provide. Below is a table of predefined supported tags you can use in your -overload of the ``basic_client``: - ------------- - -.. include:: http_client_tags.rst - -.. _Boost.Thread: http://www.boost.org/libs/thread - - -The default typedef for the HTTP client that is provided uses the -``http_async_8bit_udp_resolve`` tag, and implements HTTP 1.1. The exact -typedef is in the ``boost::network::http`` namespace as the following: - -.. code-block:: c++ - - namespace boost { namespace network { namespace http { - - typedef basic_client - client; - - }}} - - -This type has nested typedefs for the correct types for the ``basic_request`` -and ``basic_response`` templates. To use the correct types for ``basic_request`` -or ``basic_response`` you can use these nested typedefs like so: - - -.. code-block:: c++ - - boost::network::http::client::request request; - boost::network::http::client::response response; - - // or... - using namespace boost::network; - http::client::request request; - http::client::response response; - - -Typical use cases for the HTTP client would look something like the following: - - -.. code-block:: c++ - - using namespace boost::network; - http::request request("http://www.boost.org/"); - request << header("Connection", "close"); - - -The ``basic_client`` implements all HTTP methods as member functions -(HEAD, GET, POST, PUT, DELETE). Therefore, the code to make an HTTP -request looks trivially simple: - - -.. code-block:: c++ - - using namespace boost::network; - http::client client; - http::client::request request("http://www.boost.org/"); - http::client::response response = client.get(request); - - -Accessing data from ``http::response`` is done using wrappers. -To get the response headers, we use the ``headers`` wrapper which -returns, in the default case, a multimap of strings to strings: - - -.. code-block:: c++ - - using namespace boost::network; - typedef headers_range::type response_headers; - boost::range_iterator::type iterator; - - response_headers headers_ = headers(response); - for (iterator it = headers_.begin(); it != headers_.end(); ++it) { - std::cout << it->first << ": " << it->second << std::endl; - } - std::cout << std::endl; - - -HTTP server -``````````` - -As with the HTTP client, the HTTP server that is provided with -cpp-netlib is extensible through the tag mechanism and is embeddable. -The template class declaration of ``basic_server`` is given below: - - -.. code-block:: c++ - - namespace boost { namespace network { namespace http { - - template basic_server; - - }}} - - -The second template argument is used to specify the request handler -type. The request handler type is a functor type which should overload -the function call operator (``RequestHandler::operator()`` should be -overloaded) that takes two parameters: the first one being a reference -to a ``const basic_request`` and the second being a reference to -a ``basic_response`` instance. - -All the logic for parsing the HTTP request and building the ``const -basic_request`` object resides internally in the ``basic_server`` -template. Processing the request is delegated to the -``RequestHandler`` type, and the assumption of which would be that the -response is formed inside the ``RequestHandler`` function call -operator overload. - -The ``basic_server`` template however is only an underlying -implementation while the user-visible implementation is the -``http::server`` template. This simply specializes the -``basic_server`` template to use the ``default_`` tag and forwards the -``RequestHandler`` parameter: - -.. code-block:: c++ - - namespace boost { namespace network { namespace http { - - template - class server : - public basic_server {}; - - }}} - -To use the forwarding server type you just supply the request handler -implementation as the parameter. For example, an "echo" server example -might look something like this: - - -.. code-block:: c++ - - using namespace boost::network; - struct echo; - typedef http::server echo_server; - - struct echo { - void operator () (const echo_server::request &request, - echo_server::response &response) const { - std::string ip = source(request); - response = echo_server::response::stock_reply( - echo_server::response::ok, - body(request)); - std::cerr << "[" << ip << "]: " << request.uri << - " status = " << echo_server::response::ok << '\n'; - } - }; - - -Here, all we're doing is returning the original request body with an -HTTP OK response (200). We are also printing the IP address from where the -request came from. Notice that we are using a wrapper to access the source of -the request. diff --git a/libs/network/doc/in_depth/http_client_tags.rst b/libs/network/doc/in_depth/http_client_tags.rst deleted file mode 100644 index 5d79ed1ea..000000000 --- a/libs/network/doc/in_depth/http_client_tags.rst +++ /dev/null @@ -1,42 +0,0 @@ -+---------------------------------+---------------------------------------------+ -| Tag | Description | -+=================================+=============================================+ -| http_default_8bit_tcp_resolve | This is the default HTTP implementation tag | -| | that resolves addresses with a TCP resolver | -| | and provides a synchronous/blocking HTTP | -| | client interface. | -+---------------------------------+---------------------------------------------+ -| http_default_8bit_udp_resolve | This is similar to the above tag except that| -| | it specifies the HTTP client to use a UDP | -| | resolver. It also provides a synchronous/ | -| | blocking HTTP client interface. | -+---------------------------------+---------------------------------------------+ -| http_keepalive_8bit_tcp_resolve | This tag specifies that the HTTP client by | -| | default will keep connections to the server | -| | alive. It only makes sense if the | -| | ``version_major`` and ``version_minor`` are | -| | both ``1``, to indicate HTTP 1.1. This tag | -| | causes the HTTP client to resolve using a | -| | TCP resolver and provides a synchronous/ | -| | blocking HTTP client interface. | -+---------------------------------+---------------------------------------------+ -| http_keepalive_8bit_udp_resolve | This is similar to the above tag except that| -| | it specifies the HTTP client to use a UDP | -| | resolver. It also provides a synchronous/ | -| | blocking HTTP client interface. | -+---------------------------------+---------------------------------------------+ -| http_async_8bit_tcp_resolve | This tag provides an active HTTP client | -| | object implementation that uses a TCP | -| | resolver. Response objects returned will | -| | encapsulate a number of Boost.Thread_ | -| | shared futures to hold values. Users don't | -| | have to see this as they are implementation | -| | details. | -+---------------------------------+---------------------------------------------+ -| http_async_8bit_udp_resolve | This is similar to the above tag except that| -| | specifies the HTTP client to use a UDP | -| | resolver. | -+---------------------------------+---------------------------------------------+ - -.. _Boost.Thread: http://www.boost.org/libs/thread - diff --git a/libs/network/doc/in_depth/message.rst b/libs/network/doc/in_depth/message.rst deleted file mode 100644 index 51512314b..000000000 --- a/libs/network/doc/in_depth/message.rst +++ /dev/null @@ -1,233 +0,0 @@ -The message template -==================== - -One of the core components in the library is the concept and the -implementation of a common message type. In most (not all) network -protocols, the concept of a message is central to the definition of -the protocol. In HTTP, SMTP, XMPP, and even other protocols like SNMP -and ICMP, there is a common notion of a "packet" or a message. In -cpp-netlib we chose to implement the concept of a message that has the -following common parts: - - * **Source** - every message has a source identifier which varies - from protocol to protocol. - - * **Destination** - every message has a destination identifier which - varies from protocol to protocol. - - * **Headers** - each message is assumed to contain headers, which - may be empty in cases where the protocol does not support it, but - is nonetheless supported by cpp-netlib messages. - - * **Body** - the content area of a message which varies from - protocol to protocol (also sometimes referred to as payload). - -This division is purely logical -- in the underlying implementation, -the message type can choose to have different means of storing the -data, depending on the type used to tag the message. This section -covers the `Message Concept`_ as well as the `basic_message`_ -implementation. - -Message Concept -``````````````` - -.. warning:: The Message framework is deprecated in the 0.11 release, and will - be removed in future versions of the library. - -The Message Concept specifies what the valid operations on a message -are as well as what messages look like semantically. The following -table summarize the operations and syntactic as well as semantic -properties of messages. - -**Legend** - -:M: The message type. -:H: A headers container type. -:m,n: An instance of **M**. -:S: A string type. -:s,k,v: An instance of **S**. -:O: The source type. -:D: The destination type. -:B: The body type. -:T: The Tag type. - -+----------------------------+----------------------+-----------------------------------------+ -| Construct | Result | Description | -+============================+======================+=========================================+ -| ``typename M::tag`` | T | The nested tag type. | -+----------------------------+----------------------+-----------------------------------------+ -| ``M()`` | Instance of M | Default constructible. | -+----------------------------+----------------------+-----------------------------------------+ -| ``M(m)`` | Instance of M | Copy constructible. | -+----------------------------+----------------------+-----------------------------------------+ -| ``m = n;`` | Reference to m | Assignable. | -+----------------------------+----------------------+-----------------------------------------+ -| ``swap(m, n);`` | ``void`` | Swappable. | -+----------------------------+----------------------+-----------------------------------------+ -| ``source(m);`` | Convertible to O | Retrieve the source of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``destination(m);`` | Convertible to D | Retrieve the destination of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``headers(m);`` | Convertible to H | Retrieve the headers of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``body(m);`` | Convertible to B | Retrieve the body of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``m << source(s);`` | ``M &`` | Set the source of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``m << destination(s);`` | ``M &`` | Set the destination of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``m << header(k, v);`` | ``M &`` | Add a header to ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``m << remove_header(k);`` | ``M &`` | Remove a header from ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``m << body(s);`` | ``M &`` | Set the body of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``source(m,s);`` | ``void`` | Set the source of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``destination(m,s);`` | ``void`` | Set the destination of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``add_header(m, k, v);`` | ``void`` | Add a header to ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``remove_header(m, k);`` | ``void`` | Remove a header from ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``clear_headers(m);`` | ``void`` | Clear the headers of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``body(m,s);`` | ``M &`` | Set the body of ``m``. | -+----------------------------+----------------------+-----------------------------------------+ - -Types that model the Message Concept are meant to encapsulate data -that has a source, a destination, one or more named headers, and a -body/payload. Because the accessors and the directives are not -required to be part of the message type that models the Message -Concept, a message can be implemented as a POD type and have all -manipulations performed in the directive implementations, as well as -value transformations done in the accessors. - -Directives, Modifiers, and Wrappers -``````````````````````````````````` - -In the Message Concept definition there are three basic constructs that follow a -certain pattern. These patterns are Directives_, Modifiers_, and Wrappers_. - -Directives -~~~~~~~~~~ - -A directive is a function object that is applied to a Message. Directives -encapsulate a set of operations that apply to messages. The general requirement -for a Directive is that it should apply these operations on a message. - -A directive may dispatch on the type of the message passed to it at the point of -the function call. Typically, directives are generated using a factory function -that returns the correct directive type. - -For a given directive ``foo_directive`` a generator function called ``foo`` is -typically implemented: - -.. code-block:: c++ - - struct foo_directive { - template - Message & operator()(Message & m) const { - // do something to m - return m; - } - }; - - foo_directive const foo() { - return foo_directive(); - } - - // to apply a directive, we use the << operator - message m; - m << foo(); - -Modifiers -~~~~~~~~~ - -A modifier is generally defined as a free function that takes a reference to a -non-const lvalue message as the first parameter, and any number of parameters. -In the concept definition of the Message Concept, a modifier follows the form: - -.. code-block:: c++ - - modifier(message, ...) - -Modifiers are meant to imply modifications on a message, which also allows for -easier dispatch based on Argument Dependent Lookup (ADL_) on the type of the -message. Note that Directives_ can be implemented in terms of Modifiers and -vice versa, although that is not required nor specified. - -.. _ADL: http://en.wikipedia.org/wiki/Argument-dependent_name_lookup - -Wrappers -~~~~~~~~ - -A Wrapper is basically an implementation detail that ensures that a given -message, when wrapped, can be converted to the associated part of the message. A -wrapper has a type that encapsulates the conversion logic from a message to a -given type. - -An example of a Wrapper would be ``source_wrapper`` which would be returned by a -call to the wrapper generator function ``source``. An example implementation of -the ``source_wrapper`` would look like: - -.. code-block:: c++ - - template class Message> - struct source_wrapper { - Message const & m; - explicit source_wrapper(Message const & m) - : m(m) {} - typedef typename source::type source_type; - operator source_type const & () { - return m.source; - } - operator source_type const () { - return m.source; - } - operator source_type () { - return m.source; - } - }; - - template class Message> - source_wrapper const - source(Message const & message) { - return source_wrapper(message); - } - -This pattern is similar to an adapter, but the specific notion of wrapping a -data type (in this case, an object of a type that models the Message Concept) -using an intermediary wrapper is what is pertained to by the Wrapper pattern. -In this case, the Wrapper is ``source_wrapper`` while ``source`` is merely a -wrapper generator function. - -``basic_message`` -````````````````` - -The default implementation of a simple type that models the Message -Concept is available in cpp-netlib. This default implementation is -named ``basic_message`` which supports a ``Tag`` template -parameter. The definition of ``basic_message`` looks like this: - -.. code-block:: c++ - - template - class basic_message; - -The ``basic_message`` template requires that the following -tag-dispatched metafunctions are defined for the type ``Tag``: - -.. code-block:: c++ - - template - struct string; - - template - struct headers_container; - -All the operations defined by the message concept are implemented by -this basic message type. Other message implementations can either use -this common message type or specialize it according to whether they -want to use different containers or whether it's going to be just a -POD type. diff --git a/libs/network/doc/in_depth/uri.rst b/libs/network/doc/in_depth/uri.rst deleted file mode 100644 index 84eca62e2..000000000 --- a/libs/network/doc/in_depth/uri.rst +++ /dev/null @@ -1,151 +0,0 @@ -The URI class -============= - -In addition to protocol implementations, the :mod:`cpp-netlib` -provides a powerful URI class. The class implements a parser based -on `RFC 3986`_ and `RFC 2732`_. - -Generic URI syntax overview -``````````````````````````` - -A generic URI will take the form:: - - [scheme:]scheme-specific-part[#fragment] - -A URI is known as `absolute` if it specifies the scheme. Otherwise, -it is known as a relative URI. Currently, ``uri`` supports only -absolute URIs. - -URIs can be further classified according to whether they're -hierarchical or opaque (non-hierarchical). - -Some examples of non-hierarchical URIs include:: - - mailto:john.doe@example.com - news:comp.infosystems.www.servers.unix - tel:+1-816-555-1212 - -The data following the first ``":"`` is said to be opaque to the URI -parser and requires no further parsing. By way of example, the -following shows how a non-hierarchical URI is processed by the parser -by defining everything after the ``":"`` to be a part of the path: - -.. image:: ../_static/mailto_uri.png - -A hierarchical URI is identified by a double slash (``"//"``) after -the scheme and a scheme-specific component, which `RFC 3986`_ defines -to be:: - - [scheme:][//authority][path][?query][#fragment] - -The authority component can be further broken down to:: - - [user_info@]host[:port] - -Examples of hierarchical URIs include:: - - http://www.boost.org/ - file:///bin/bash - -The following example, describing a complex URI using FTP, shows how -a URI is broken down by the parser: - -.. image:: ../_static/ftp_uri.png - -Note that the ``authority`` is further subdivided into different -elements. Another example, using HTTP is given below: - -.. image:: ../_static/http_uri.png - -The difference here between the path in a hierarchical URI and that in -the example above for the non-hierarchical URI. - -The ``uri`` class -````````````````` - -As of version 0.9.3, ``uri`` supplies a URI parser and builder. -To use the parser, it's as simple as supplying a string to the -constructor: - -.. code-block:: c++ - - using namespace boost::network; - uri::uri instance("http://cpp-netlib.github.com/"); - assert(instance.is_valid()); - std::cout << "scheme: " << instance.scheme() << std::endl - << "host: " << instance.host() << std::endl; - -The command-line output of this program will be:: - - scheme: http - host: cpp-netlib.github.com - -The ``uri`` builder -``````````````````` - -``uri`` support a stream style syntax to create a URI from it's -elements. For example the program: - -.. code-block:: c++ - - #include - #include - #include - using namespace boost::network; - - int main() { - uri::uri url; - url << uri::scheme("http") - << uri::host("www.github.com") - << uri::path("/cpp-netlib"); - std::cout << url << std::endl; - return 0; - } - -will output:: - - http://www.github.com/cpp-netlib - -``URI Concept`` -``````````````` - -**Legend** - -:U: The URI type. -:u,u_: An instance of **M**. -:S: A string type. -:s,v: An instance of **S**. -:T: The Tag type. - -+----------------------------+----------------------+-----------------------------------------+ -| Construct | Result | Description | -+============================+======================+=========================================+ -| ``U(u)`` | Instance of U | Copy constructible. | -+----------------------------+----------------------+-----------------------------------------+ -| ``U(s)`` | Instance of U | Constructible from string. | -+----------------------------+----------------------+-----------------------------------------+ -| ``u = u_;`` | Reference to u | Assignable. | -+----------------------------+----------------------+-----------------------------------------+ -| ``u = s;`` | Reference to u | Assignable from string. | -+----------------------------+----------------------+-----------------------------------------+ -| ``swap(u, u_);`` | ``void`` | Swappable. | -+----------------------------+----------------------+-----------------------------------------+ -| ``scheme(u);`` | Convertible to S | Retrieve the URI scheme of ``u``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``user_info(u);`` | Convertible to S | Retrieve the user info of ``u``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``host(u);`` | Convertible to S | Retrieve the host of ``u``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``port(u);`` | Convertible to H | Retrieve the port of ``u``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``path(u);`` | Convertible to S | Retrieve the path of ``u``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``query(u);`` | Convertible to S | Retrieve the query string of ``u``. | -+----------------------------+----------------------+-----------------------------------------+ -| ``fragment(u);`` | Convertible to S | Retrieve the fragment of ``u``. | -+----------------------------+----------------------+-----------------------------------------+ - -.. _`RFC 3986`: http://tools.ietf.org/html/rfc3986 -.. _`RFC 2368`: http://tools.ietf.org/html/rfc2368 -.. _`RFC 3513`: http://tools.ietf.org/html/rfc3513 -.. _`RFC 2732`: http://tools.ietf.org/html/rfc2732 diff --git a/libs/network/doc/index.rst b/libs/network/doc/index.rst index fc9e65405..3329b8a30 100644 --- a/libs/network/doc/index.rst +++ b/libs/network/doc/index.rst @@ -108,7 +108,6 @@ Want to learn more? * :ref:`Take a look at the getting started guide ` * :ref:`Learn from some simple examples ` * :ref:`Find out what's new ` - * :ref:`Study the library in more depth ` * :ref:`Discover more through the full reference ` * :ref:`Full table of contents ` diff --git a/libs/network/doc/reference/http_server.rst b/libs/network/doc/reference/http_server.rst index 26ceb9b65..c0022bdda 100644 --- a/libs/network/doc/reference/http_server.rst +++ b/libs/network/doc/reference/http_server.rst @@ -5,9 +5,9 @@ HTTP Server API General ------- -:mod:`cpp-netlib` includes and implements two distinct HTTP server -implementations that you can use and embed in your own applications. Both HTTP -Server implementations: +:mod:`cpp-netlib` includes and implements and asynchronous HTTP server +implementation that you can use and embed in your own applications. The HTTP +Server implementation: * **Cannot be copied.** This means you may have to store instances of the HTTP Server in dynamic memory if you intend to use them as function parameters or @@ -15,60 +15,19 @@ Server implementations: * **Assume that requests made are independent of each other.** None of the HTTP Server implementations support request pipelining (yet) so a single connection only deals with a single request. - * **Are header-only and are compiled-into your application.** Future releases - in case you want to upgrade the implementation you are using in your - application will be distributed as header-only implementations, which means - you have to re-compile your application to use a newer version of the - implementations. - -The HTTP Servers have different semantics, and in some cases require different -APIs from the supplied template parameters. - -Implementations ---------------- - -There are two different user-facing template classes that differentiate the -`Synchronous Servers`_ from the `Asynchronous Servers`_. Both templates take a -single template parameter named ``Handler`` which describes the type of the -Handler function object. - -There are two different Handler concepts, one concept for `Synchronous Servers`_ -and another for `Asynchronous Servers`. - -The SynchronousHandler concept for `Synchronous Servers`_ is described by the -following table: - ---------------- - -**Legend:** - -H - The Handler type. -h - An instance of H. -Req - A type that models the Request Concept. -Res - A type that models the Response Concept. -req - An instance of Req. -res - An instance of Res. - -+----------------+-------------+----------------------------------------------+ -| Construct | Return Type | Description | -+================+=============+==============================================+ -| ``h(req,res)`` | ``void`` | Handle the request; res is passed in as a | -| | | non-const lvalue, which represents the | -| | | response to be returned to the client | -| | | performing the request. | -+----------------+-------------+----------------------------------------------+ - -More information about the internals of the `Synchronous Servers`_ can be found -in the following section. - -The AsynchronousHandler concept for `Asynchronous Servers`_ is described by the -following table: + * **The Handler instance is invoked asynchronously**. This means the I/O + thread used to handle network-related events are free to handle only the + I/O related events. This enables the server to scale better as to the + number of concurrent connections it can handle. + * **The Handler is able to schedule asynchronous actions on the thread pool + associated with the server.** This allows handlers to perform multiple + asynchronous computations that later on perform writes to the connection. + * **The Handler is able to control the (asynchronous) writes to and reads + from the HTTP connection.** Because the connection is available to the + Handler, that means it can write out chunks of data at a time or stream + data through the connection continuously. + +The Handler concept for the HTTP Server is described by the following table: --------------- @@ -95,270 +54,30 @@ conn | | | writing to and reading from the connection.| +------------------+-------------+--------------------------------------------+ -More information about the internals of the `Asynchronous Servers`_ can be found -in the following section. - -Synchronous Servers -------------------- - -The synchronous server implementation is represented by the template ``server`` -in namespace ``boost::network::http``. The ``server`` template takes in a single -template parameter named ``Handler`` which models the SynchronousHandler -concept (described above). - -An instance of Handler is taken in by reference to the constructor of the HTTP -server. This means the Handler is not copied around and only a single instance -of the handler is used for all connections and requests performed against the -HTTP server. - -.. warning:: It is important to note that the HTTP server does not implement any - locking upon invoking the Handler. In case you have any state in the Handler - that will be associated with the synchronous server, you would have to - implement your own synchronization internal to the Handler implementation. - This matters especially if you run the synchronous server in multiple - threads. - -The general pattern of usage for the HTTP Server template is shown below: - -.. code-block:: c++ - - struct handler; - typedef boost::network::http::server http_server; - - struct handler { - void operator()( - http_server::request const & req, - http_server::response & res - ) { - // do something, and then edit the res object here. - } - }; - -More information about the actual HTTP Server API follows in the next section. -It is important to understand that the HTTP Server is actually embedded in your -application, which means you can expose almost all your application logic -through the Handler type, which you can also initialize appropriately. - -API Documentation -~~~~~~~~~~~~~~~~~ - -The following sections assume that the following file has been included: - -.. code-block:: c++ - - #include - -And that the following typedef's have been put in place: - -.. code-block:: c++ - - struct handler_type; - typedef boost::network::http::server http_server; - - struct handler_type { - void operator()(http_server::request const & request, - http_server::response & response) { - // do something here - } - }; - -Constructor -``````````` - -``explicit http_server(options)`` - Construct an HTTP Server instance, passing in a ``server_options`` object. The following table shows the supported options in - ``server_options``. - -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| Parameter Name | Type | Description | -+=======================+==========================================+==================================================================================================+ -| address | string_type | The hostname or IP address from which the server should be bound to. This parameter is required. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| port | string_type | The port to which the server should bind and listen to. This parameter is required. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| thread_pool | ``shared_ptr`` | A shared pointer to an instance of ``boost::network::utils::thread_pool`` -- this is the | -| | | thread pool from where the handler is invoked. This parameter is only applicable and required | -| | | for ``async_server`` instances. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| io_service | ``shared_ptr`` | An optional lvalue to an instance of ``boost::asio::io_service`` which allows the server to use | -| | | an already-constructed ``boost::asio::io_service`` instance instead of instantiating one that it | -| | | manages. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| reuse_address | ``bool`` | A boolean that specifies whether to re-use the address and port on which the server will be | -| | | bound to. This enables or disables the socket option for listener sockets. The default is | -| | | ``false``. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| report_aborted | ``bool`` | A boolean that specifies whether the listening socket should report aborted connection attempts | -| | | to the accept handler (an internal detail of cpp-netlib). This is put in place to allow for | -| | | future-proofing the code in case an optional error handler function is supported in later | -| | | releases of cpp-netlib. The default is ``false``. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| receive_buffer_size | ``int`` | The size of the socket's receive buffer. The default is defined by Boost.Asio and is | -| | | platform-dependent. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| send_buffer_size | ``int`` | The size of the socket's send buffer. The default is defined by Boost.Asio and is | -| | | platform-dependent. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| receive_low_watermark | ``int`` | The size of the socket's low watermark for its receive buffer. The default is defined by | -| | | Boost.Asio and is platform-dependent. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| send_buffer_size | ``int`` | The size of the socket's send low watermark for its send buffer. The default is defined by | -| | | Boost.Asio and is platform-dependent. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| non_blocking_io | ``bool`` | An optional bool to define whether the socket should use non-blocking I/O in case the platform | -| | | supports it. The default is ``true``. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| linger | ``bool`` | An optional bool to determine whether the socket should linger in case there's still data to be | -| | | sent out at the time of its closing. The default is ``true``. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| linger_timeout | ``int`` | An optional int to define the timeout to wait for socket closes before it is set to linger. | -| | | The default is ``0``. | -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ -| context | ``shared_ptr`` | An optional shared pointer to an instance of ``boost::asio::ssl::context`` -- this contains the | -| | | settings needed to support SSL. This parameter is only applicable for ``async_server`` instances.| -+-----------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ - -To use the above supported named parameters, you'll have code that looks like the following: - -.. code-block:: c++ - - using namespace boost::network::http; // parameters are in this namespace - handler handler_instance; - sync_server::options options(handler_instance); - options.address("0.0.0.0") - .port("80") - .io_service(boost::make_shared()) - .reuse_address(true); - sync_server instance(options); - instance.run(); - -Public Members -`````````````` - -The following definitions assume that a properly constructed ``http_server`` -instance has been constructed in the following manner: - -.. code-block:: c++ - - handler_type handler; - http_server::options options(handler); - http_server server(options.address("127.0.0.1").port("8000")); - -``server.run()`` - Run the HTTP Server event loop. This function can be run on multiple threads - following the example: - -.. code-block:: c++ - - boost::thread t1(boost::bind(&http_server::run, &server)); - boost::thread t2(boost::bind(&http_server::run, &server)); - server.run(); - t1.join(); - t2.join(); - -``server.stop()`` - Stop the HTTP Server acceptor and wait for all pending requests to finish. - -Response Object -``````````````` - -The response object has its own public member functions which can be very -helpful in certain simple situations. - -``response = http_server::response::stock_reply(status, body)`` - Code like the above should go inside the handler's ``operator()`` overload. - The body parameter is an ``std::string``. The status parameter is any of - the following values from the ``http_server::response`` enum - ``status_type``: - -.. code-block:: c++ - - enum status_type { - ok = 200, - created = 201, - accepted = 202, - no_content = 204, - multiple_choices = 300, - moved_permanently = 301, - moved_temporarily = 302, - not_modified = 304, - bad_request = 400, - unauthorized = 401, - forbidden = 403, - not_found = 404, - not_supported = 405, - not_acceptable = 406, - internal_server_error = 500, - not_implemented = 501, - bad_gateway = 502, - service_unavailable = 503 - }; +--------------- -The response object also has the following publicly accessible member values -which can be directly manipulated by the handler. - -+------------------+----------------------+------------------------------------+ -| Member Name | Type | Description | -+==================+======================+====================================+ -| status | ``status_type`` | The HTTP status of the response. | -+------------------+----------------------+------------------------------------+ -| headers | ``vector
        `` | Vector of headers. [#]_ | -+------------------+----------------------+------------------------------------+ -| content | ``string_type`` [#]_ | The contents of the response. | -+------------------+----------------------+------------------------------------+ - -.. [#] A header is a struct of type - ``response_header``. An instance always has the - members ``name`` and ``value`` both of which are of type ``string_type``. -.. [#] ``string_type`` is - ``boost::network::string::type``. - -Asynchronous Servers --------------------- - -The asynchronous server implementation is significantly different to the -synchronous server implementation in three ways: - - #. **The Handler instance is invoked asynchronously**. This means the I/O - thread used to handle network-related events are free to handle only the - I/O related events. This enables the server to scale better as to the - number of concurrent connections it can handle. - #. **The Handler is able to schedule asynchronous actions on the thread pool - associated with the server.** This allows handlers to perform multiple - asynchronous computations that later on perform writes to the connection. - #. **The Handler is able to control the (asynchronous) writes to and reads from - the HTTP connection.** Because the connection is available to the Handler, - that means it can write out chunks of data at a time or stream data through - the connection continuously. - -The asynchronous server is meant to allow for better scalability in terms of the -number of concurrent connections and for performing asynchronous actions within -the handlers. If your application does not need to write out information -asynchronously or perform potentially long computations, then the synchronous -server gives a generally better performance profile than the asynchronous -server. - -The asynchronous server implementation is available from a single user-facing -template named ``async_server``. This template takes in a single template +The HTTP Server is meant to allow for better scalability in terms of the number +of concurrent connections and for performing asynchronous actions within the +handlers. The HTTP Server implementation is available from a single +user-facing template named ``server``. This template takes in a single template parameter which is the type of the Handler to be called once a request has been parsed from a connection. -An instance of Handler is taken as a reference to the constructor similar to the -synchronous server implementation. +An instance of Handler is taken as a reference to the constructor of the server +instance. -.. warning:: The asynchronous server implementation, like the synchronous server - implementation, does not perform any synchronization on the calls to the - Handler invocation. This means if your handler contains or maintains internal - state, you are responsible for implementing your own synchronization on - accesses to the internal state of the Handler. +.. warning:: The HTTP Server implementation does not perform any + synchronization on the calls to the Handler invocation. This means if your + handler contains or maintains internal state, you are responsible for + implementing your own synchronization on accesses to the internal state of + the Handler. -The general pattern for using the ``async_server`` template is shown below: +The general pattern for using the ``server`` template is shown below: .. code-block:: c++ struct handler; - typedef boost::network::http::async_server http_server; + typedef boost::network::http::server http_server; struct handler { void operator()( @@ -371,7 +90,7 @@ The general pattern for using the ``async_server`` template is shown below: }; API Documentation -~~~~~~~~~~~~~~~~~ +----------------- The following sections assume that the following file has been included: @@ -395,135 +114,36 @@ And that the following typedef's have been put in place: }; Constructor -``````````` +~~~~~~~~~~~ ``explicit http_server(options)`` Construct an HTTP server instance passing in a ``server_options`` instance. -Public Members -`````````````` - -The following definitions assume that a properly constructed ``http_server`` -instance has been constructed in the following manner: +Server Options +~~~~~~~~~~~~~~ -.. code-block:: c++ - - handler_type handler; - http_server::options options(handler); - options.thread_pool(boost::make_shared(2)); - http_server server(options.address("127.0.0.1").port("8000")); - -``server.run()`` - Run the HTTP Server event loop. This function can be run on multiple threads - following the example: - -.. code-block:: c++ +.. doxygenstruct:: boost::network::http::server_options + :project: cppnetlib + :members: - boost::thread t1(boost::bind(&http_server::run, &server)); - boost::thread t2(boost::bind(&http_server::run, &server)); - server.run(); - t1.join(); - t2.join(); +Public Members +~~~~~~~~~~~~~~ -``server.stop()`` - Stop the HTTP Server acceptor and wait for all pending requests to finish. +.. doxygenstruct:: boost::network::http::server + :project: cppnetlib + :members: + :undoc-members: Connection Object -````````````````` - -The connection object has its own public member functions which will be the -primary means for reading from and writing to the connection. - -``template write(Range range)`` - The connection object exposes a function ``write`` that can be given a - parameter that adheres to the Boost.Range_ ``Single Pass Range`` Concept. - The write function, although it looks synchronous, starts of a series of - asynchronous writes to the connection as soon as the range is serialized to - appropriately sized buffers. - - To use this in your handler, it would look something like this: - -.. code-block:: c++ - - connection->write("Hello, world!"); - std::string sample = "I have a string!"; - connection->write(sample); - -``template void write(Range range, Callback callback)`` - The connection object also exposes a function ``write`` that can be given a - parameter that adheres to the Boost.Range_ ``Single Pass Range`` Concept, as - well as a Callback function that returns ``void`` and takes a - ``boost::system::error_code`` as a parameter. This overload of ``write`` is - useful for writing streaming applications that send out chunks of data at a - time, or for writing data that may not all fit in memory right away. - -``template void read(ReadCallback callback)`` - The connection object has a function ``read`` which can be used to read more - information from the connection. This ``read`` function takes in a callback - that can be assigned to a Boost.Function_ with the signature - ``void(input_range,error_code,size_t,connection_ptr)``. The following list - shows what the types actually mean: - - * **input_range** -- ``boost::iterator_range`` : The range - that denotes the data read from the connection. - * **error_code** -- ``boost::system::error_code`` : The error code if - there were any errors encountered from the read. - * **size_t** -- ``std::size_t`` : The number of bytes transferred. - * **connection_ptr** -- ``http_server::connection_ptr`` : A handle to the - current connection, so that it is kept alive at the time of the read - callback invocation. - - This interface is useful when doing reads of uploaded data that can be - potentially large and may not fit in memory. The read handler is then - responsible for dealing with the chunks of data available from the - connection. - -``void set_status(status_t new_status)`` - The ``set_status`` function takes a parameter of type ``status_t`` which is - an enum type nested in ``http_status::connection`` which is given in the - following code listing. - -.. code-block:: c++ - - enum status_t { - ok = 200 - , created = 201 - , accepted = 202 - , no_content = 204 - , multiple_choices = 300 - , moved_permanently = 301 - , moved_temporarily = 302 - , not_modified = 304 - , bad_request = 400 - , unauthorized = 401 - , forbidden = 403 - , not_found = 404 - , not_supported = 405 - , not_acceptable = 406 - , internal_server_error = 500 - , not_implemented = 501 - , bad_gateway = 502 - , service_unavailable = 503 - }; - -.. note:: You may set and re-set the status several times as long as you have - not set the headers or sent data through the connection. If you do this after - data has already been set, the function will throw an instance of - ``std::logic_error``. - -``template void set_headers(Range range)`` - The ``set_headers`` function takes a Single Pass Range of - ``boost::network::http::response_header`` - instances and linearizes them to a buffer with at most - ``BOOST_NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE`` and - immediately schedules an asynchronous write once that is done. +~~~~~~~~~~~~~~~~~ - The function throws an instance of ``std::logic_error`` if you try to set - the headers for a connection more than once. +.. doxygenstruct:: boost::network::http::async_connection + :project: cppnetlib + :members: -Adding SSL support to Asynchronous Server ------------------------------------------ +Adding SSL support to the HTTP Server +------------------------------------- In order to setup SSL support for an Asynchronous Server, it is best to start from a regular Asynchronous Server (see above). Once this server is setup, SSL can be @@ -533,24 +153,25 @@ used are defined in the link. .. code-block:: c++ // Initialize SSL context - boost::shared_ptr ctx = boost::make_shared(boost::asio::ssl::context::sslv23); + std::shared_ptr ctx = + std::make_shared(asio::ssl::context::sslv23); ctx->set_options( - boost::asio::ssl::context::default_workarounds - | boost::asio::ssl::context::no_sslv2 - | boost::asio::ssl::context::single_dh_use); + asio::ssl::context::default_workarounds + | asio::ssl::context::no_sslv3 + | asio::ssl::context::single_dh_use); // Set keys ctx->set_password_callback(password_callback); ctx->use_certificate_chain_file("server.pem"); - ctx->use_private_key_file("server.pem", boost::asio::ssl::context::pem); + ctx->use_private_key_file("server.pem", asio::ssl::context::pem); ctx->use_tmp_dh_file("dh512.pem"); handler_type handler; http_server::options options(handler); - options.thread_pool(boost::make_shared(2)); + options.thread_pool(std::make_shared(2)); http_server server(options.address("127.0.0.1").port("8442").context(ctx)); - std::string password_callback(std::size_t max_length, boost::asio::ssl::context_base::password_purpose purpose) { + std::string password_callback(std::size_t max_length, asio::ssl::context_base::password_purpose purpose) { return std::string("test"); } diff --git a/libs/network/doc/techniques.rst b/libs/network/doc/techniques.rst deleted file mode 100644 index b52bf7e36..000000000 --- a/libs/network/doc/techniques.rst +++ /dev/null @@ -1,12 +0,0 @@ -Techniques -========== - -The :mod:`cpp-netlib` uses several advanced techniques to achieve it's -aims. This chapter describes some of those techniques. - -.. toctree:: - :maxdepth: 1 - - techniques/tag_metafunctions - techniques/directives - techniques/polymorphism diff --git a/libs/network/doc/techniques/directives.rst b/libs/network/doc/techniques/directives.rst deleted file mode 100644 index e40882d95..000000000 --- a/libs/network/doc/techniques/directives.rst +++ /dev/null @@ -1,92 +0,0 @@ -Directives -========== - -The :mod:`cpp-netlib` uses a technique for allowing message-passing -semantics in a chainable fashion in the form of directives. The basic -concept for directives is, in a general sense, an encapsulated -transformation that can be applied to objects that abide by the -directive protocol. - -Using the object-oriented notion of message passing, where an object -accepts a message (usually a function call) we define a simple DSEL in -order for the protocol to be supported by certain object types. In the -:mod:`cpp-netlib` the protocol implemented is similar to that of the -standard iostream formatting system: - -.. code-block:: c++ - - object << directive1(...) - << directive2(...) - ... - << directiveN(...); - -In :mod:`cpp-netlib` the directives are simple function objects that -take a target object as reference and returns a reference to the same -object as a result. In code the directive pattern looks like the -following: - -.. code-block:: c++ - - struct directive_type { - template - Input & operator()(Input & input) const { - // do something to input - return input; - } - }; - -To simplify directive creation, usually factory or generator functions -are defined to return concrete objects of the directive's type. - -.. code-block:: c++ - - inline - directive_type directive(...) { - return directive_type(); - } - -The trivial implementation of the directive protocol then boils down -to the specialization of the shift-left operator on the target type. - -.. code-block:: c++ - - template - inline target_type & operator<< - (target_type & x, Directive const & f) { - return f(x); - } - -.. todo:: - - An example using a directive. - -The rationale for implementing directives include the following: - - * **Encapsulation** - by moving logic into the directive types the - target object's interface can remain rudimentary and even hidden - to the user's immediate attention. Adding this layer of - indirection also allows for changing the underlying - implementations while maintaining the same syntactic and semantic - properties. - * **Flexibility** - by allowing the creation of directives that are - independent from the target object's type, generic operations can - be applied based on the concept being modeled by the target - type. The flexibility also afforded comes in the directive's - generator function, which can also generate different concrete - directive specializations based on parameters to the function. - * **Extensibility** - because the directives are independent of the - target object's type, new directives can be added and supported - without having to change the target object at all. - * **Reuse** - truly generic directives can then be used for a broad - set of target object types that model the same concepts supported - by the directive. Because the directives are self-contained - objects, the state and other object references it keeps are only - accessible to it and can be re-used in different contexts as well. - -Extending a system that uses directives is trivial in header-only -systems because new directives are simply additive. The protocol is -simple and can be applied to a broad class of situations. - -In a header-only library, the static nature of the wiring and chaining -of the operations lends itself to compiler abuse. A deep enough -nesting of the directives can lead to prolonged compilation times. diff --git a/libs/network/doc/techniques/polymorphism.rst b/libs/network/doc/techniques/polymorphism.rst deleted file mode 100644 index d5e42f8c9..000000000 --- a/libs/network/doc/techniques/polymorphism.rst +++ /dev/null @@ -1,92 +0,0 @@ -Static and dynamic polymorphism -=============================== - - -With a header only library, you can only do so much with static -polymorphism alone. There are some situations where you have to handle -dynamic polymorphism because of unavoidable runtime-based decision -making. Although you can deal with the base types that remain static, -behavior can vary greatly which derived type should be handling the -situation based on runtime values. - -This situation comes up in the :mod:`cpp-netlib` when we decide what -kind of connection handler to use for a given HTTP URI -- whether it's -plain HTTP or HTTPS. Although the HTTP semantics are the same for -HTTP and HTTPS the implementation of the connection handler greatly -varies on whether to use a plain TCP connection or an SSL-wrapped TCP -connection. - -The general pattern or technique is to combine tag-based dispatch with -a strategy factory, all while not requiring any externally built -libraries. Doing it in a header-only library requires a little -creativity and additional layers of indirection that you otherwise -will not need for a library with externally built static/dynamic -libraries. - -First we define the base type which we want to support dynamic -behavior with. There's nothing special with the base type, except -that it supports the tag dispatch earlier defined and has a virtual -destructor. In code it looks like this: - -.. code-block:: c++ - - template - struct base { - virtual void foo() = 0; // make this an abstract base - virtual ~base() { - // do the base destructor thing here. - } - }; - -We then define a set of derived types that specialize the -implementation of the ``foo`` member function. To facilitate the -dispatch of the correct type based on an input, we create a strategy -factory function: - -.. code-block:: c++ - - template - unique_ptr > strategy(int input, Tag) { - unique_ptr > ptr; - switch(input) { - case 0: ptr.reset(new derived0()); break; - case 1: ptr.reset(new derived1()); break; - // ... - default: ptr.reset(0); break; - } - return ptr; - } - - unique_ptr > ptr = - strategy(input, default_()); // input is a runtime value - -The strategy factory can be a standalone function, or a static member -of a factory class that is specialized by tag dispatch. This can be -done like the following: - -.. code-block:: c++ - - template - struct strategy; - - template <> - struct strategy { - static unique_ptr > create(int input) { - unique_ptr > ptr; - switch(input) { - case 0: ptr.reset(new derived0()); break; - case 1: ptr.reset(new derived1()); break; - //... - default: ptr.reset(0); break; - } - return ptr; - } - }; - -This approach allows the header-only libraries to define new dynamic -types in subsequent versions of the library while keeping the -static-dynamic bridge fluid. The only down-side to this is the -possibility of derived type explosion in case there are a lot of -different strategies or specializations available -- this though is -not unique to static-dynamic bridging, but is also a problem with pure -object oriented programming with dynamic polymorphism. diff --git a/libs/network/doc/techniques/tag_metafunctions.rst b/libs/network/doc/techniques/tag_metafunctions.rst deleted file mode 100644 index 68edd1449..000000000 --- a/libs/network/doc/techniques/tag_metafunctions.rst +++ /dev/null @@ -1,172 +0,0 @@ -Tag metafunctions -================= - -Sometimes you want to vary a function or a type's behavior based on a -static parameter. In the :mod:`cpp-netlib` there are a number of -things you might want to change based on some such parameter -- like -what the underlying string type should be and how large a buffer -should be, among other things. The primary way to define this in a -header-only manner is to use tag-based metafunctions. - -The skeleton of the approach is based on a similar technique for -defining type traits. In the :mod:`cpp-netlib` however the type traits -are defined on opaque tag types which serve to associate results to a -family of metafunctions. - -Template Specialization ------------------------ - -To illustrate this point, let's define a tag ``default_`` which we use -to denote the default implementation of a certain type ``foo``. For -instance we decide that the default string type we will use for -``default_`` tagged ``foo`` specializations will be an -``std::string``. - -In the :mod:`cpp-netlib` this is done by defining a ``string`` -metafunction type that is specialized on the tag ``default_`` whose -nested ``type`` result is the type ``std::string``. In code this would -translate to: - -.. code-block:: c++ - - template - struct string { - typedef void type; - }; - - struct default_; - - template <> - struct string { - typedef std::string type; - }; - -Template Metaprogramming ------------------------- - -Starting with version 0.7, the tag dispatch mechanism changed slightly to use -Boost.MPL_. The idea is still the same, although we can get a little smarter -than just using template specializations. Instead of just defining an opaque -type ``default_``, we use the Boost.MPL equivalent of a vector to define which -root types of properties this ``default_`` tag supports. The idea is to make the -opaque type ``default_`` inherit property tags which the library supports -internally as definite extension points. - -.. _Boost.MPL: http://www.boost.org/libs/mpl/index.html - -Our definition of the ``default_`` tag will then look something like the -following: - -.. code-block:: c++ - - typedef mpl::vector default_tags; - - template - struct components; - - typedef mpl::inherit_linearly< - default_tags, - mpl::inherit - >::type default_; - - template - struct components { - typedef default_tags type; - }; - -In the above listing, ``default_string`` is what we call a "root" tag which is -meant to be combined with other "root" tags to form composite tags. In this case -our composite tag is the tag ``default_``. There are a number of these "root" -tags that :mod:`cpp-netlib` provides. These are in the namespace -``boost::network::tags`` and are defined in ``boost/network/tags.hpp``. - -Using this technique we change slightly our definition of the ``string`` -metafunction class into this: - -.. code-block:: c++ - - template - struct unsupported_tag; - - template - struct string : - mpl::if_< - is_base_of< - tags::default_string, - Tag - >, - std::string, - unsupported_tag - > - {}; - -Notice that we don't have the typedef for ``type`` in the body of ``string`` -anymore, but we do inherit from ``mpl::if_``. Since ``mpl::if_`` is a template -metafunction itself, it contains a definition of the resulting ``type`` which -``string`` inherits. - -You can see the real definition of the ``string`` metafunction in -``boost/network/traits/string.hpp``. - -Using Tags ----------- - -Once we have the defined tag, we can then use this in the definition of our -types. In the definition of the type ``foo`` we use this type function -``string`` and pass the tag type parameter to determine what to use as -the string type in the context of the type ``foo``. In code this would -translate into: - -.. code-block:: c++ - - template - struct foo { - typedef typename string::type string_type; - - // .. use string_type where you need a string. - }; - -Using this approach we can support different types of strings for -different tags on the type ``foo``. In case we want to use a different -type of string for the tag ``default_`` we only change the -composition of the ``string_tags`` MPL vector. For example, in :mod:`cpp-netlib` -there is a root tag ``default_wstring`` which causes the ``string`` metafunction -to define ``std::wstring`` as the resulting type. - -The approach also allows for the control of the structure and features -of types like ``foo`` based on the specialization of the tag. Whole -type function families can be defined on tags where they are supported -and ignored in cases where they are not. - -To illustrate let's define a new tag ``swappable``. Given the above -definition of ``foo``, we want to make the ``swappable``-tagged -``foo`` define a ``swap`` function that extends the original -``default_``-tagged ``foo``. In code this would look like: - -.. code-block:: c++ - - struct swappable; - - template <> - struct foo : foo { - void swap(foo & other) { - // ... - } - }; - -We also for example want to enable an ADL-reachable ``swap`` function: - -.. code-block:: c++ - - struct swappable; - - inline - void swap(foo & left, foo & right) { - left.swap(right); - } - -Overall what the tag-based definition approach allows is for static -definition of extension points that ensures type-safety and -invariants. This keeps the whole extension mechanism static and yet -flexible. -