diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2016-10-06 10:41:18 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2016-10-06 10:43:11 +0900 |
commit | f763a99a501650eff2c60288aa6f10ef916d769e (patch) | |
tree | 02af7e13f9a38c888ebf340fe764cbe7dae99da9 /doc/html/boost_asio | |
parent | 5cde13f21d36c7224b0e13d11c4b49379ae5210d (diff) | |
download | boost-f763a99a501650eff2c60288aa6f10ef916d769e.tar.gz boost-f763a99a501650eff2c60288aa6f10ef916d769e.tar.bz2 boost-f763a99a501650eff2c60288aa6f10ef916d769e.zip |
Imported Upstream version 1.62.0upstream/1.62.0
Change-Id: I9d4c1ddb7b7d8f0069217ecc582700f9fda6dd4c
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'doc/html/boost_asio')
151 files changed, 0 insertions, 16324 deletions
diff --git a/doc/html/boost_asio/async_op1.png b/doc/html/boost_asio/async_op1.png Binary files differdeleted file mode 100644 index 0de79911e4..0000000000 --- a/doc/html/boost_asio/async_op1.png +++ /dev/null diff --git a/doc/html/boost_asio/async_op2.png b/doc/html/boost_asio/async_op2.png Binary files differdeleted file mode 100644 index 9b8d3c0872..0000000000 --- a/doc/html/boost_asio/async_op2.png +++ /dev/null diff --git a/doc/html/boost_asio/example/cpp03/allocation/server.cpp b/doc/html/boost_asio/example/cpp03/allocation/server.cpp deleted file mode 100644 index b213f47f3d..0000000000 --- a/doc/html/boost_asio/example/cpp03/allocation/server.cpp +++ /dev/null @@ -1,238 +0,0 @@ -// -// server.cpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstdlib> -#include <iostream> -#include <boost/aligned_storage.hpp> -#include <boost/array.hpp> -#include <boost/bind.hpp> -#include <boost/enable_shared_from_this.hpp> -#include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/asio.hpp> - -using boost::asio::ip::tcp; - -// Class to manage the memory to be used for handler-based custom allocation. -// It contains a single block of memory which may be returned for allocation -// requests. If the memory is in use when an allocation request is made, the -// allocator delegates allocation to the global heap. -class handler_allocator - : private boost::noncopyable -{ -public: - handler_allocator() - : in_use_(false) - { - } - - void* allocate(std::size_t size) - { - if (!in_use_ && size < storage_.size) - { - in_use_ = true; - return storage_.address(); - } - else - { - return ::operator new(size); - } - } - - void deallocate(void* pointer) - { - if (pointer == storage_.address()) - { - in_use_ = false; - } - else - { - ::operator delete(pointer); - } - } - -private: - // Storage space used for handler-based custom memory allocation. - boost::aligned_storage<1024> storage_; - - // Whether the handler-based custom allocation storage has been used. - bool in_use_; -}; - -// Wrapper class template for handler objects to allow handler memory -// allocation to be customised. Calls to operator() are forwarded to the -// encapsulated handler. -template <typename Handler> -class custom_alloc_handler -{ -public: - custom_alloc_handler(handler_allocator& a, Handler h) - : allocator_(a), - handler_(h) - { - } - - template <typename Arg1> - void operator()(Arg1 arg1) - { - handler_(arg1); - } - - template <typename Arg1, typename Arg2> - void operator()(Arg1 arg1, Arg2 arg2) - { - handler_(arg1, arg2); - } - - friend void* asio_handler_allocate(std::size_t size, - custom_alloc_handler<Handler>* this_handler) - { - return this_handler->allocator_.allocate(size); - } - - friend void asio_handler_deallocate(void* pointer, std::size_t /*size*/, - custom_alloc_handler<Handler>* this_handler) - { - this_handler->allocator_.deallocate(pointer); - } - -private: - handler_allocator& allocator_; - Handler handler_; -}; - -// Helper function to wrap a handler object to add custom allocation. -template <typename Handler> -inline custom_alloc_handler<Handler> make_custom_alloc_handler( - handler_allocator& a, Handler h) -{ - return custom_alloc_handler<Handler>(a, h); -} - -class session - : public boost::enable_shared_from_this<session> -{ -public: - session(boost::asio::io_service& io_service) - : socket_(io_service) - { - } - - tcp::socket& socket() - { - return socket_; - } - - void start() - { - socket_.async_read_some(boost::asio::buffer(data_), - make_custom_alloc_handler(allocator_, - boost::bind(&session::handle_read, - shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); - } - - void handle_read(const boost::system::error_code& error, - size_t bytes_transferred) - { - if (!error) - { - boost::asio::async_write(socket_, - boost::asio::buffer(data_, bytes_transferred), - make_custom_alloc_handler(allocator_, - boost::bind(&session::handle_write, - shared_from_this(), - boost::asio::placeholders::error))); - } - } - - void handle_write(const boost::system::error_code& error) - { - if (!error) - { - socket_.async_read_some(boost::asio::buffer(data_), - make_custom_alloc_handler(allocator_, - boost::bind(&session::handle_read, - shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); - } - } - -private: - // The socket used to communicate with the client. - tcp::socket socket_; - - // Buffer used to store data received from the client. - boost::array<char, 1024> data_; - - // The allocator to use for handler-based custom memory allocation. - handler_allocator allocator_; -}; - -typedef boost::shared_ptr<session> session_ptr; - -class server -{ -public: - server(boost::asio::io_service& io_service, short port) - : io_service_(io_service), - acceptor_(io_service, tcp::endpoint(tcp::v4(), port)) - { - session_ptr new_session(new session(io_service_)); - acceptor_.async_accept(new_session->socket(), - boost::bind(&server::handle_accept, this, new_session, - boost::asio::placeholders::error)); - } - - void handle_accept(session_ptr new_session, - const boost::system::error_code& error) - { - if (!error) - { - new_session->start(); - } - - new_session.reset(new session(io_service_)); - acceptor_.async_accept(new_session->socket(), - boost::bind(&server::handle_accept, this, new_session, - boost::asio::placeholders::error)); - } - -private: - boost::asio::io_service& io_service_; - tcp::acceptor acceptor_; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: server <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - using namespace std; // For atoi. - server s(io_service, atoi(argv[1])); - - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/buffers/reference_counted.cpp b/doc/html/boost_asio/example/cpp03/buffers/reference_counted.cpp deleted file mode 100644 index 9c1ce4f696..0000000000 --- a/doc/html/boost_asio/example/cpp03/buffers/reference_counted.cpp +++ /dev/null @@ -1,131 +0,0 @@ -// -// reference_counted.cpp -// ~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <boost/asio.hpp> -#include <boost/bind.hpp> -#include <boost/enable_shared_from_this.hpp> -#include <boost/shared_ptr.hpp> -#include <iostream> -#include <vector> - -using boost::asio::ip::tcp; - -// A reference-counted non-modifiable buffer class. -class shared_const_buffer -{ -public: - // Construct from a std::string. - explicit shared_const_buffer(const std::string& data) - : data_(new std::vector<char>(data.begin(), data.end())), - buffer_(boost::asio::buffer(*data_)) - { - } - - // Implement the ConstBufferSequence requirements. - typedef boost::asio::const_buffer value_type; - typedef const boost::asio::const_buffer* const_iterator; - const boost::asio::const_buffer* begin() const { return &buffer_; } - const boost::asio::const_buffer* end() const { return &buffer_ + 1; } - -private: - boost::shared_ptr<std::vector<char> > data_; - boost::asio::const_buffer buffer_; -}; - -class session - : public boost::enable_shared_from_this<session> -{ -public: - session(boost::asio::io_service& io_service) - : socket_(io_service) - { - } - - tcp::socket& socket() - { - return socket_; - } - - void start() - { - using namespace std; // For time_t, time and ctime. - time_t now = time(0); - shared_const_buffer buffer(ctime(&now)); - boost::asio::async_write(socket_, buffer, - boost::bind(&session::handle_write, shared_from_this())); - } - - void handle_write() - { - } - -private: - // The socket used to communicate with the client. - tcp::socket socket_; -}; - -typedef boost::shared_ptr<session> session_ptr; - -class server -{ -public: - server(boost::asio::io_service& io_service, short port) - : io_service_(io_service), - acceptor_(io_service, tcp::endpoint(tcp::v4(), port)) - { - session_ptr new_session(new session(io_service_)); - acceptor_.async_accept(new_session->socket(), - boost::bind(&server::handle_accept, this, new_session, - boost::asio::placeholders::error)); - } - - void handle_accept(session_ptr new_session, - const boost::system::error_code& error) - { - if (!error) - { - new_session->start(); - } - - new_session.reset(new session(io_service_)); - acceptor_.async_accept(new_session->socket(), - boost::bind(&server::handle_accept, this, new_session, - boost::asio::placeholders::error)); - } - -private: - boost::asio::io_service& io_service_; - tcp::acceptor acceptor_; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: reference_counted <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - using namespace std; // For atoi. - server s(io_service, atoi(argv[1])); - - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/chat/chat_client.cpp b/doc/html/boost_asio/example/cpp03/chat/chat_client.cpp deleted file mode 100644 index e52fc10eb1..0000000000 --- a/doc/html/boost_asio/example/cpp03/chat/chat_client.cpp +++ /dev/null @@ -1,177 +0,0 @@ -// -// chat_client.cpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstdlib> -#include <deque> -#include <iostream> -#include <boost/bind.hpp> -#include <boost/asio.hpp> -#include <boost/thread/thread.hpp> -#include "chat_message.hpp" - -using boost::asio::ip::tcp; - -typedef std::deque<chat_message> chat_message_queue; - -class chat_client -{ -public: - chat_client(boost::asio::io_service& io_service, - tcp::resolver::iterator endpoint_iterator) - : io_service_(io_service), - socket_(io_service) - { - boost::asio::async_connect(socket_, endpoint_iterator, - boost::bind(&chat_client::handle_connect, this, - boost::asio::placeholders::error)); - } - - void write(const chat_message& msg) - { - io_service_.post(boost::bind(&chat_client::do_write, this, msg)); - } - - void close() - { - io_service_.post(boost::bind(&chat_client::do_close, this)); - } - -private: - - void handle_connect(const boost::system::error_code& error) - { - if (!error) - { - boost::asio::async_read(socket_, - boost::asio::buffer(read_msg_.data(), chat_message::header_length), - boost::bind(&chat_client::handle_read_header, this, - boost::asio::placeholders::error)); - } - } - - void handle_read_header(const boost::system::error_code& error) - { - if (!error && read_msg_.decode_header()) - { - boost::asio::async_read(socket_, - boost::asio::buffer(read_msg_.body(), read_msg_.body_length()), - boost::bind(&chat_client::handle_read_body, this, - boost::asio::placeholders::error)); - } - else - { - do_close(); - } - } - - void handle_read_body(const boost::system::error_code& error) - { - if (!error) - { - std::cout.write(read_msg_.body(), read_msg_.body_length()); - std::cout << "\n"; - boost::asio::async_read(socket_, - boost::asio::buffer(read_msg_.data(), chat_message::header_length), - boost::bind(&chat_client::handle_read_header, this, - boost::asio::placeholders::error)); - } - else - { - do_close(); - } - } - - void do_write(chat_message msg) - { - bool write_in_progress = !write_msgs_.empty(); - write_msgs_.push_back(msg); - if (!write_in_progress) - { - boost::asio::async_write(socket_, - boost::asio::buffer(write_msgs_.front().data(), - write_msgs_.front().length()), - boost::bind(&chat_client::handle_write, this, - boost::asio::placeholders::error)); - } - } - - void handle_write(const boost::system::error_code& error) - { - if (!error) - { - write_msgs_.pop_front(); - if (!write_msgs_.empty()) - { - boost::asio::async_write(socket_, - boost::asio::buffer(write_msgs_.front().data(), - write_msgs_.front().length()), - boost::bind(&chat_client::handle_write, this, - boost::asio::placeholders::error)); - } - } - else - { - do_close(); - } - } - - void do_close() - { - socket_.close(); - } - -private: - boost::asio::io_service& io_service_; - tcp::socket socket_; - chat_message read_msg_; - chat_message_queue write_msgs_; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 3) - { - std::cerr << "Usage: chat_client <host> <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - tcp::resolver resolver(io_service); - tcp::resolver::query query(argv[1], argv[2]); - tcp::resolver::iterator iterator = resolver.resolve(query); - - chat_client c(io_service, iterator); - - boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service)); - - char line[chat_message::max_body_length + 1]; - while (std::cin.getline(line, chat_message::max_body_length + 1)) - { - using namespace std; // For strlen and memcpy. - chat_message msg; - msg.body_length(strlen(line)); - memcpy(msg.body(), line, msg.body_length()); - msg.encode_header(); - c.write(msg); - } - - c.close(); - t.join(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/chat/chat_message.hpp b/doc/html/boost_asio/example/cpp03/chat/chat_message.hpp deleted file mode 100644 index 8f592703b8..0000000000 --- a/doc/html/boost_asio/example/cpp03/chat/chat_message.hpp +++ /dev/null @@ -1,93 +0,0 @@ -// -// chat_message.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 CHAT_MESSAGE_HPP -#define CHAT_MESSAGE_HPP - -#include <cstdio> -#include <cstdlib> -#include <cstring> - -class chat_message -{ -public: - enum { header_length = 4 }; - enum { max_body_length = 512 }; - - chat_message() - : body_length_(0) - { - } - - const char* data() const - { - return data_; - } - - char* data() - { - return data_; - } - - size_t length() const - { - return header_length + body_length_; - } - - const char* body() const - { - return data_ + header_length; - } - - char* body() - { - return data_ + header_length; - } - - size_t body_length() const - { - return body_length_; - } - - void body_length(size_t new_length) - { - body_length_ = new_length; - if (body_length_ > max_body_length) - body_length_ = max_body_length; - } - - bool decode_header() - { - using namespace std; // For strncat and atoi. - char header[header_length + 1] = ""; - strncat(header, data_, header_length); - body_length_ = atoi(header); - if (body_length_ > max_body_length) - { - body_length_ = 0; - return false; - } - return true; - } - - void encode_header() - { - using namespace std; // For sprintf and memcpy. - char header[header_length + 1] = ""; - sprintf(header, "%4d", static_cast<int>(body_length_)); - memcpy(data_, header, header_length); - } - -private: - char data_[header_length + max_body_length]; - size_t body_length_; -}; - -#endif // CHAT_MESSAGE_HPP diff --git a/doc/html/boost_asio/example/cpp03/chat/chat_server.cpp b/doc/html/boost_asio/example/cpp03/chat/chat_server.cpp deleted file mode 100644 index 32c95c1f93..0000000000 --- a/doc/html/boost_asio/example/cpp03/chat/chat_server.cpp +++ /dev/null @@ -1,247 +0,0 @@ -// -// chat_server.cpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <algorithm> -#include <cstdlib> -#include <deque> -#include <iostream> -#include <list> -#include <set> -#include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> -#include <boost/asio.hpp> -#include "chat_message.hpp" - -using boost::asio::ip::tcp; - -//---------------------------------------------------------------------- - -typedef std::deque<chat_message> chat_message_queue; - -//---------------------------------------------------------------------- - -class chat_participant -{ -public: - virtual ~chat_participant() {} - virtual void deliver(const chat_message& msg) = 0; -}; - -typedef boost::shared_ptr<chat_participant> chat_participant_ptr; - -//---------------------------------------------------------------------- - -class chat_room -{ -public: - void join(chat_participant_ptr participant) - { - participants_.insert(participant); - std::for_each(recent_msgs_.begin(), recent_msgs_.end(), - boost::bind(&chat_participant::deliver, participant, _1)); - } - - void leave(chat_participant_ptr participant) - { - participants_.erase(participant); - } - - void deliver(const chat_message& msg) - { - recent_msgs_.push_back(msg); - while (recent_msgs_.size() > max_recent_msgs) - recent_msgs_.pop_front(); - - std::for_each(participants_.begin(), participants_.end(), - boost::bind(&chat_participant::deliver, _1, boost::ref(msg))); - } - -private: - std::set<chat_participant_ptr> participants_; - enum { max_recent_msgs = 100 }; - chat_message_queue recent_msgs_; -}; - -//---------------------------------------------------------------------- - -class chat_session - : public chat_participant, - public boost::enable_shared_from_this<chat_session> -{ -public: - chat_session(boost::asio::io_service& io_service, chat_room& room) - : socket_(io_service), - room_(room) - { - } - - tcp::socket& socket() - { - return socket_; - } - - void start() - { - room_.join(shared_from_this()); - boost::asio::async_read(socket_, - boost::asio::buffer(read_msg_.data(), chat_message::header_length), - boost::bind( - &chat_session::handle_read_header, shared_from_this(), - boost::asio::placeholders::error)); - } - - void deliver(const chat_message& msg) - { - bool write_in_progress = !write_msgs_.empty(); - write_msgs_.push_back(msg); - if (!write_in_progress) - { - boost::asio::async_write(socket_, - boost::asio::buffer(write_msgs_.front().data(), - write_msgs_.front().length()), - boost::bind(&chat_session::handle_write, shared_from_this(), - boost::asio::placeholders::error)); - } - } - - void handle_read_header(const boost::system::error_code& error) - { - if (!error && read_msg_.decode_header()) - { - boost::asio::async_read(socket_, - boost::asio::buffer(read_msg_.body(), read_msg_.body_length()), - boost::bind(&chat_session::handle_read_body, shared_from_this(), - boost::asio::placeholders::error)); - } - else - { - room_.leave(shared_from_this()); - } - } - - void handle_read_body(const boost::system::error_code& error) - { - if (!error) - { - room_.deliver(read_msg_); - boost::asio::async_read(socket_, - boost::asio::buffer(read_msg_.data(), chat_message::header_length), - boost::bind(&chat_session::handle_read_header, shared_from_this(), - boost::asio::placeholders::error)); - } - else - { - room_.leave(shared_from_this()); - } - } - - void handle_write(const boost::system::error_code& error) - { - if (!error) - { - write_msgs_.pop_front(); - if (!write_msgs_.empty()) - { - boost::asio::async_write(socket_, - boost::asio::buffer(write_msgs_.front().data(), - write_msgs_.front().length()), - boost::bind(&chat_session::handle_write, shared_from_this(), - boost::asio::placeholders::error)); - } - } - else - { - room_.leave(shared_from_this()); - } - } - -private: - tcp::socket socket_; - chat_room& room_; - chat_message read_msg_; - chat_message_queue write_msgs_; -}; - -typedef boost::shared_ptr<chat_session> chat_session_ptr; - -//---------------------------------------------------------------------- - -class chat_server -{ -public: - chat_server(boost::asio::io_service& io_service, - const tcp::endpoint& endpoint) - : io_service_(io_service), - acceptor_(io_service, endpoint) - { - start_accept(); - } - - void start_accept() - { - chat_session_ptr new_session(new chat_session(io_service_, room_)); - acceptor_.async_accept(new_session->socket(), - boost::bind(&chat_server::handle_accept, this, new_session, - boost::asio::placeholders::error)); - } - - void handle_accept(chat_session_ptr session, - const boost::system::error_code& error) - { - if (!error) - { - session->start(); - } - - start_accept(); - } - -private: - boost::asio::io_service& io_service_; - tcp::acceptor acceptor_; - chat_room room_; -}; - -typedef boost::shared_ptr<chat_server> chat_server_ptr; -typedef std::list<chat_server_ptr> chat_server_list; - -//---------------------------------------------------------------------- - -int main(int argc, char* argv[]) -{ - try - { - if (argc < 2) - { - std::cerr << "Usage: chat_server <port> [<port> ...]\n"; - return 1; - } - - boost::asio::io_service io_service; - - chat_server_list servers; - for (int i = 1; i < argc; ++i) - { - using namespace std; // For atoi. - tcp::endpoint endpoint(tcp::v4(), atoi(argv[i])); - chat_server_ptr server(new chat_server(io_service, endpoint)); - servers.push_back(server); - } - - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/chat/posix_chat_client.cpp b/doc/html/boost_asio/example/cpp03/chat/posix_chat_client.cpp deleted file mode 100644 index 2bf984995a..0000000000 --- a/doc/html/boost_asio/example/cpp03/chat/posix_chat_client.cpp +++ /dev/null @@ -1,205 +0,0 @@ -// -// posix_chat_client.cpp -// ~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstdlib> -#include <cstring> -#include <iostream> -#include <boost/array.hpp> -#include <boost/bind.hpp> -#include <boost/asio.hpp> -#include "chat_message.hpp" - -#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) - -using boost::asio::ip::tcp; -namespace posix = boost::asio::posix; - -class posix_chat_client -{ -public: - posix_chat_client(boost::asio::io_service& io_service, - tcp::resolver::iterator endpoint_iterator) - : socket_(io_service), - input_(io_service, ::dup(STDIN_FILENO)), - output_(io_service, ::dup(STDOUT_FILENO)), - input_buffer_(chat_message::max_body_length) - { - boost::asio::async_connect(socket_, endpoint_iterator, - boost::bind(&posix_chat_client::handle_connect, this, - boost::asio::placeholders::error)); - } - -private: - - void handle_connect(const boost::system::error_code& error) - { - if (!error) - { - // Read the fixed-length header of the next message from the server. - boost::asio::async_read(socket_, - boost::asio::buffer(read_msg_.data(), chat_message::header_length), - boost::bind(&posix_chat_client::handle_read_header, this, - boost::asio::placeholders::error)); - - // Read a line of input entered by the user. - boost::asio::async_read_until(input_, input_buffer_, '\n', - boost::bind(&posix_chat_client::handle_read_input, this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - } - - void handle_read_header(const boost::system::error_code& error) - { - if (!error && read_msg_.decode_header()) - { - // Read the variable-length body of the message from the server. - boost::asio::async_read(socket_, - boost::asio::buffer(read_msg_.body(), read_msg_.body_length()), - boost::bind(&posix_chat_client::handle_read_body, this, - boost::asio::placeholders::error)); - } - else - { - close(); - } - } - - void handle_read_body(const boost::system::error_code& error) - { - if (!error) - { - // Write out the message we just received, terminated by a newline. - static char eol[] = { '\n' }; - boost::array<boost::asio::const_buffer, 2> buffers = {{ - boost::asio::buffer(read_msg_.body(), read_msg_.body_length()), - boost::asio::buffer(eol) }}; - boost::asio::async_write(output_, buffers, - boost::bind(&posix_chat_client::handle_write_output, this, - boost::asio::placeholders::error)); - } - else - { - close(); - } - } - - void handle_write_output(const boost::system::error_code& error) - { - if (!error) - { - // Read the fixed-length header of the next message from the server. - boost::asio::async_read(socket_, - boost::asio::buffer(read_msg_.data(), chat_message::header_length), - boost::bind(&posix_chat_client::handle_read_header, this, - boost::asio::placeholders::error)); - } - else - { - close(); - } - } - - void handle_read_input(const boost::system::error_code& error, - std::size_t length) - { - if (!error) - { - // Write the message (minus the newline) to the server. - write_msg_.body_length(length - 1); - input_buffer_.sgetn(write_msg_.body(), length - 1); - input_buffer_.consume(1); // Remove newline from input. - write_msg_.encode_header(); - boost::asio::async_write(socket_, - boost::asio::buffer(write_msg_.data(), write_msg_.length()), - boost::bind(&posix_chat_client::handle_write, this, - boost::asio::placeholders::error)); - } - else if (error == boost::asio::error::not_found) - { - // Didn't get a newline. Send whatever we have. - write_msg_.body_length(input_buffer_.size()); - input_buffer_.sgetn(write_msg_.body(), input_buffer_.size()); - write_msg_.encode_header(); - boost::asio::async_write(socket_, - boost::asio::buffer(write_msg_.data(), write_msg_.length()), - boost::bind(&posix_chat_client::handle_write, this, - boost::asio::placeholders::error)); - } - else - { - close(); - } - } - - void handle_write(const boost::system::error_code& error) - { - if (!error) - { - // Read a line of input entered by the user. - boost::asio::async_read_until(input_, input_buffer_, '\n', - boost::bind(&posix_chat_client::handle_read_input, this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - else - { - close(); - } - } - - void close() - { - // Cancel all outstanding asynchronous operations. - socket_.close(); - input_.close(); - output_.close(); - } - -private: - tcp::socket socket_; - posix::stream_descriptor input_; - posix::stream_descriptor output_; - chat_message read_msg_; - chat_message write_msg_; - boost::asio::streambuf input_buffer_; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 3) - { - std::cerr << "Usage: posix_chat_client <host> <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - tcp::resolver resolver(io_service); - tcp::resolver::query query(argv[1], argv[2]); - tcp::resolver::iterator iterator = resolver.resolve(query); - - posix_chat_client c(io_service, iterator); - - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} - -#else // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) -int main() {} -#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) diff --git a/doc/html/boost_asio/example/cpp03/echo/async_tcp_echo_server.cpp b/doc/html/boost_asio/example/cpp03/echo/async_tcp_echo_server.cpp deleted file mode 100644 index e7221e795e..0000000000 --- a/doc/html/boost_asio/example/cpp03/echo/async_tcp_echo_server.cpp +++ /dev/null @@ -1,137 +0,0 @@ -// -// async_tcp_echo_server.cpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstdlib> -#include <iostream> -#include <boost/bind.hpp> -#include <boost/asio.hpp> - -using boost::asio::ip::tcp; - -class session -{ -public: - session(boost::asio::io_service& io_service) - : socket_(io_service) - { - } - - tcp::socket& socket() - { - return socket_; - } - - void start() - { - socket_.async_read_some(boost::asio::buffer(data_, max_length), - boost::bind(&session::handle_read, this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - -private: - void handle_read(const boost::system::error_code& error, - size_t bytes_transferred) - { - if (!error) - { - boost::asio::async_write(socket_, - boost::asio::buffer(data_, bytes_transferred), - boost::bind(&session::handle_write, this, - boost::asio::placeholders::error)); - } - else - { - delete this; - } - } - - void handle_write(const boost::system::error_code& error) - { - if (!error) - { - socket_.async_read_some(boost::asio::buffer(data_, max_length), - boost::bind(&session::handle_read, this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - else - { - delete this; - } - } - - tcp::socket socket_; - enum { max_length = 1024 }; - char data_[max_length]; -}; - -class server -{ -public: - server(boost::asio::io_service& io_service, short port) - : io_service_(io_service), - acceptor_(io_service, tcp::endpoint(tcp::v4(), port)) - { - start_accept(); - } - -private: - void start_accept() - { - session* new_session = new session(io_service_); - acceptor_.async_accept(new_session->socket(), - boost::bind(&server::handle_accept, this, new_session, - boost::asio::placeholders::error)); - } - - void handle_accept(session* new_session, - const boost::system::error_code& error) - { - if (!error) - { - new_session->start(); - } - else - { - delete new_session; - } - - start_accept(); - } - - boost::asio::io_service& io_service_; - tcp::acceptor acceptor_; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: async_tcp_echo_server <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - using namespace std; // For atoi. - server s(io_service, atoi(argv[1])); - - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/echo/async_udp_echo_server.cpp b/doc/html/boost_asio/example/cpp03/echo/async_udp_echo_server.cpp deleted file mode 100644 index 83791d2af4..0000000000 --- a/doc/html/boost_asio/example/cpp03/echo/async_udp_echo_server.cpp +++ /dev/null @@ -1,92 +0,0 @@ -// -// async_udp_echo_server.cpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstdlib> -#include <iostream> -#include <boost/bind.hpp> -#include <boost/asio.hpp> - -using boost::asio::ip::udp; - -class server -{ -public: - server(boost::asio::io_service& io_service, short port) - : socket_(io_service, udp::endpoint(udp::v4(), port)) - { - socket_.async_receive_from( - boost::asio::buffer(data_, max_length), sender_endpoint_, - boost::bind(&server::handle_receive_from, this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - - void handle_receive_from(const boost::system::error_code& error, - size_t bytes_recvd) - { - if (!error && bytes_recvd > 0) - { - socket_.async_send_to( - boost::asio::buffer(data_, bytes_recvd), sender_endpoint_, - boost::bind(&server::handle_send_to, this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - else - { - socket_.async_receive_from( - boost::asio::buffer(data_, max_length), sender_endpoint_, - boost::bind(&server::handle_receive_from, this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - } - - void handle_send_to(const boost::system::error_code& /*error*/, - size_t /*bytes_sent*/) - { - socket_.async_receive_from( - boost::asio::buffer(data_, max_length), sender_endpoint_, - boost::bind(&server::handle_receive_from, this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - -private: - udp::socket socket_; - udp::endpoint sender_endpoint_; - enum { max_length = 1024 }; - char data_[max_length]; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: async_udp_echo_server <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - using namespace std; // For atoi. - server s(io_service, atoi(argv[1])); - - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/echo/blocking_tcp_echo_client.cpp b/doc/html/boost_asio/example/cpp03/echo/blocking_tcp_echo_client.cpp deleted file mode 100644 index ab6d5f863e..0000000000 --- a/doc/html/boost_asio/example/cpp03/echo/blocking_tcp_echo_client.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// -// blocking_tcp_echo_client.cpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstdlib> -#include <cstring> -#include <iostream> -#include <boost/asio.hpp> - -using boost::asio::ip::tcp; - -enum { max_length = 1024 }; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 3) - { - std::cerr << "Usage: blocking_tcp_echo_client <host> <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - tcp::resolver resolver(io_service); - tcp::resolver::query query(tcp::v4(), argv[1], argv[2]); - tcp::resolver::iterator iterator = resolver.resolve(query); - - tcp::socket s(io_service); - boost::asio::connect(s, iterator); - - using namespace std; // For strlen. - std::cout << "Enter message: "; - char request[max_length]; - std::cin.getline(request, max_length); - size_t request_length = strlen(request); - boost::asio::write(s, boost::asio::buffer(request, request_length)); - - char reply[max_length]; - size_t reply_length = boost::asio::read(s, - boost::asio::buffer(reply, request_length)); - std::cout << "Reply is: "; - std::cout.write(reply, reply_length); - std::cout << "\n"; - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/echo/blocking_tcp_echo_server.cpp b/doc/html/boost_asio/example/cpp03/echo/blocking_tcp_echo_server.cpp deleted file mode 100644 index 0fc6a91ebb..0000000000 --- a/doc/html/boost_asio/example/cpp03/echo/blocking_tcp_echo_server.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// -// blocking_tcp_echo_server.cpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstdlib> -#include <iostream> -#include <boost/bind.hpp> -#include <boost/smart_ptr.hpp> -#include <boost/asio.hpp> -#include <boost/thread/thread.hpp> - -using boost::asio::ip::tcp; - -const int max_length = 1024; - -typedef boost::shared_ptr<tcp::socket> socket_ptr; - -void session(socket_ptr sock) -{ - try - { - for (;;) - { - char data[max_length]; - - boost::system::error_code error; - size_t length = sock->read_some(boost::asio::buffer(data), error); - if (error == boost::asio::error::eof) - break; // Connection closed cleanly by peer. - else if (error) - throw boost::system::system_error(error); // Some other error. - - boost::asio::write(*sock, boost::asio::buffer(data, length)); - } - } - catch (std::exception& e) - { - std::cerr << "Exception in thread: " << e.what() << "\n"; - } -} - -void server(boost::asio::io_service& io_service, unsigned short port) -{ - tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), port)); - for (;;) - { - socket_ptr sock(new tcp::socket(io_service)); - a.accept(*sock); - boost::thread t(boost::bind(session, sock)); - } -} - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: blocking_tcp_echo_server <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - using namespace std; // For atoi. - server(io_service, atoi(argv[1])); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/echo/blocking_udp_echo_client.cpp b/doc/html/boost_asio/example/cpp03/echo/blocking_udp_echo_client.cpp deleted file mode 100644 index 1906196831..0000000000 --- a/doc/html/boost_asio/example/cpp03/echo/blocking_udp_echo_client.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// -// blocking_udp_echo_client.cpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstdlib> -#include <cstring> -#include <iostream> -#include <boost/asio.hpp> - -using boost::asio::ip::udp; - -enum { max_length = 1024 }; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 3) - { - std::cerr << "Usage: blocking_udp_echo_client <host> <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - udp::socket s(io_service, udp::endpoint(udp::v4(), 0)); - - udp::resolver resolver(io_service); - udp::resolver::query query(udp::v4(), argv[1], argv[2]); - udp::resolver::iterator iterator = resolver.resolve(query); - - using namespace std; // For strlen. - std::cout << "Enter message: "; - char request[max_length]; - std::cin.getline(request, max_length); - size_t request_length = strlen(request); - s.send_to(boost::asio::buffer(request, request_length), *iterator); - - char reply[max_length]; - udp::endpoint sender_endpoint; - size_t reply_length = s.receive_from( - boost::asio::buffer(reply, max_length), sender_endpoint); - std::cout << "Reply is: "; - std::cout.write(reply, reply_length); - std::cout << "\n"; - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/echo/blocking_udp_echo_server.cpp b/doc/html/boost_asio/example/cpp03/echo/blocking_udp_echo_server.cpp deleted file mode 100644 index cc4e9fdb18..0000000000 --- a/doc/html/boost_asio/example/cpp03/echo/blocking_udp_echo_server.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// -// blocking_udp_echo_server.cpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstdlib> -#include <iostream> -#include <boost/asio.hpp> - -using boost::asio::ip::udp; - -enum { max_length = 1024 }; - -void server(boost::asio::io_service& io_service, unsigned short port) -{ - udp::socket sock(io_service, udp::endpoint(udp::v4(), port)); - for (;;) - { - char data[max_length]; - udp::endpoint sender_endpoint; - size_t length = sock.receive_from( - boost::asio::buffer(data, max_length), sender_endpoint); - sock.send_to(boost::asio::buffer(data, length), sender_endpoint); - } -} - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: blocking_udp_echo_server <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - using namespace std; // For atoi. - server(io_service, atoi(argv[1])); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/fork/daemon.cpp b/doc/html/boost_asio/example/cpp03/fork/daemon.cpp deleted file mode 100644 index 6f960ce228..0000000000 --- a/doc/html/boost_asio/example/cpp03/fork/daemon.cpp +++ /dev/null @@ -1,189 +0,0 @@ -// -// daemon.cpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <boost/asio/io_service.hpp> -#include <boost/asio/ip/udp.hpp> -#include <boost/asio/signal_set.hpp> -#include <boost/array.hpp> -#include <boost/bind.hpp> -#include <ctime> -#include <iostream> -#include <syslog.h> -#include <unistd.h> - -using boost::asio::ip::udp; - -class udp_daytime_server -{ -public: - udp_daytime_server(boost::asio::io_service& io_service) - : socket_(io_service, udp::endpoint(udp::v4(), 13)) - { - start_receive(); - } - -private: - void start_receive() - { - socket_.async_receive_from( - boost::asio::buffer(recv_buffer_), remote_endpoint_, - boost::bind(&udp_daytime_server::handle_receive, this, _1)); - } - - void handle_receive(const boost::system::error_code& ec) - { - if (!ec || ec == boost::asio::error::message_size) - { - using namespace std; // For time_t, time and ctime; - time_t now = time(0); - std::string message = ctime(&now); - - boost::system::error_code ignored_ec; - socket_.send_to(boost::asio::buffer(message), - remote_endpoint_, 0, ignored_ec); - } - - start_receive(); - } - - udp::socket socket_; - udp::endpoint remote_endpoint_; - boost::array<char, 1> recv_buffer_; -}; - -int main() -{ - try - { - boost::asio::io_service io_service; - - // Initialise the server before becoming a daemon. If the process is - // started from a shell, this means any errors will be reported back to the - // user. - udp_daytime_server server(io_service); - - // Register signal handlers so that the daemon may be shut down. You may - // also want to register for other signals, such as SIGHUP to trigger a - // re-read of a configuration file. - boost::asio::signal_set signals(io_service, SIGINT, SIGTERM); - signals.async_wait( - boost::bind(&boost::asio::io_service::stop, &io_service)); - - // Inform the io_service that we are about to become a daemon. The - // io_service cleans up any internal resources, such as threads, that may - // interfere with forking. - io_service.notify_fork(boost::asio::io_service::fork_prepare); - - // Fork the process and have the parent exit. If the process was started - // from a shell, this returns control to the user. Forking a new process is - // also a prerequisite for the subsequent call to setsid(). - if (pid_t pid = fork()) - { - if (pid > 0) - { - // We're in the parent process and need to exit. - // - // When the exit() function is used, the program terminates without - // invoking local variables' destructors. Only global variables are - // destroyed. As the io_service object is a local variable, this means - // we do not have to call: - // - // io_service.notify_fork(boost::asio::io_service::fork_parent); - // - // However, this line should be added before each call to exit() if - // using a global io_service object. An additional call: - // - // io_service.notify_fork(boost::asio::io_service::fork_prepare); - // - // should also precede the second fork(). - exit(0); - } - else - { - syslog(LOG_ERR | LOG_USER, "First fork failed: %m"); - return 1; - } - } - - // Make the process a new session leader. This detaches it from the - // terminal. - setsid(); - - // A process inherits its working directory from its parent. This could be - // on a mounted filesystem, which means that the running daemon would - // prevent this filesystem from being unmounted. Changing to the root - // directory avoids this problem. - chdir("/"); - - // The file mode creation mask is also inherited from the parent process. - // We don't want to restrict the permissions on files created by the - // daemon, so the mask is cleared. - umask(0); - - // A second fork ensures the process cannot acquire a controlling terminal. - if (pid_t pid = fork()) - { - if (pid > 0) - { - exit(0); - } - else - { - syslog(LOG_ERR | LOG_USER, "Second fork failed: %m"); - return 1; - } - } - - // Close the standard streams. This decouples the daemon from the terminal - // that started it. - close(0); - close(1); - close(2); - - // We don't want the daemon to have any standard input. - if (open("/dev/null", O_RDONLY) < 0) - { - syslog(LOG_ERR | LOG_USER, "Unable to open /dev/null: %m"); - return 1; - } - - // Send standard output to a log file. - const char* output = "/tmp/asio.daemon.out"; - const int flags = O_WRONLY | O_CREAT | O_APPEND; - const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; - if (open(output, flags, mode) < 0) - { - syslog(LOG_ERR | LOG_USER, "Unable to open output file %s: %m", output); - return 1; - } - - // Also send standard error to the same log file. - if (dup(1) < 0) - { - syslog(LOG_ERR | LOG_USER, "Unable to dup output descriptor: %m"); - return 1; - } - - // Inform the io_service that we have finished becoming a daemon. The - // io_service uses this opportunity to create any internal file descriptors - // that need to be private to the new process. - io_service.notify_fork(boost::asio::io_service::fork_child); - - // The io_service can now be used normally. - syslog(LOG_INFO | LOG_USER, "Daemon started"); - io_service.run(); - syslog(LOG_INFO | LOG_USER, "Daemon stopped"); - } - catch (std::exception& e) - { - syslog(LOG_ERR | LOG_USER, "Exception: %s", e.what()); - std::cerr << "Exception: " << e.what() << std::endl; - } -} diff --git a/doc/html/boost_asio/example/cpp03/fork/process_per_connection.cpp b/doc/html/boost_asio/example/cpp03/fork/process_per_connection.cpp deleted file mode 100644 index bd859c9f2a..0000000000 --- a/doc/html/boost_asio/example/cpp03/fork/process_per_connection.cpp +++ /dev/null @@ -1,160 +0,0 @@ -// -// process_per_connection.cpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <boost/asio/io_service.hpp> -#include <boost/asio/ip/tcp.hpp> -#include <boost/asio/signal_set.hpp> -#include <boost/asio/write.hpp> -#include <boost/array.hpp> -#include <boost/bind.hpp> -#include <cstdlib> -#include <iostream> -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> - -using boost::asio::ip::tcp; - -class server -{ -public: - server(boost::asio::io_service& io_service, unsigned short port) - : io_service_(io_service), - signal_(io_service, SIGCHLD), - acceptor_(io_service, tcp::endpoint(tcp::v4(), port)), - socket_(io_service) - { - start_signal_wait(); - start_accept(); - } - -private: - void start_signal_wait() - { - signal_.async_wait(boost::bind(&server::handle_signal_wait, this)); - } - - void handle_signal_wait() - { - // Only the parent process should check for this signal. We can determine - // whether we are in the parent by checking if the acceptor is still open. - if (acceptor_.is_open()) - { - // Reap completed child processes so that we don't end up with zombies. - int status = 0; - while (waitpid(-1, &status, WNOHANG) > 0) {} - - start_signal_wait(); - } - } - - void start_accept() - { - acceptor_.async_accept(socket_, - boost::bind(&server::handle_accept, this, _1)); - } - - void handle_accept(const boost::system::error_code& ec) - { - if (!ec) - { - // Inform the io_service that we are about to fork. The io_service cleans - // up any internal resources, such as threads, that may interfere with - // forking. - io_service_.notify_fork(boost::asio::io_service::fork_prepare); - - if (fork() == 0) - { - // Inform the io_service that the fork is finished and that this is the - // child process. The io_service uses this opportunity to create any - // internal file descriptors that must be private to the new process. - io_service_.notify_fork(boost::asio::io_service::fork_child); - - // The child won't be accepting new connections, so we can close the - // acceptor. It remains open in the parent. - acceptor_.close(); - - // The child process is not interested in processing the SIGCHLD signal. - signal_.cancel(); - - start_read(); - } - else - { - // Inform the io_service that the fork is finished (or failed) and that - // this is the parent process. The io_service uses this opportunity to - // recreate any internal resources that were cleaned up during - // preparation for the fork. - io_service_.notify_fork(boost::asio::io_service::fork_parent); - - socket_.close(); - start_accept(); - } - } - else - { - std::cerr << "Accept error: " << ec.message() << std::endl; - start_accept(); - } - } - - void start_read() - { - socket_.async_read_some(boost::asio::buffer(data_), - boost::bind(&server::handle_read, this, _1, _2)); - } - - void handle_read(const boost::system::error_code& ec, std::size_t length) - { - if (!ec) - start_write(length); - } - - void start_write(std::size_t length) - { - boost::asio::async_write(socket_, boost::asio::buffer(data_, length), - boost::bind(&server::handle_write, this, _1)); - } - - void handle_write(const boost::system::error_code& ec) - { - if (!ec) - start_read(); - } - - boost::asio::io_service& io_service_; - boost::asio::signal_set signal_; - tcp::acceptor acceptor_; - tcp::socket socket_; - boost::array<char, 1024> data_; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: process_per_connection <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - using namespace std; // For atoi. - server s(io_service, atoi(argv[1])); - - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << std::endl; - } -} diff --git a/doc/html/boost_asio/example/cpp03/http/client/async_client.cpp b/doc/html/boost_asio/example/cpp03/http/client/async_client.cpp deleted file mode 100644 index e1c2f13bea..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/client/async_client.cpp +++ /dev/null @@ -1,205 +0,0 @@ -// -// async_client.cpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <iostream> -#include <istream> -#include <ostream> -#include <string> -#include <boost/asio.hpp> -#include <boost/bind.hpp> - -using boost::asio::ip::tcp; - -class client -{ -public: - client(boost::asio::io_service& io_service, - const std::string& server, const std::string& path) - : resolver_(io_service), - socket_(io_service) - { - // Form the request. We specify the "Connection: close" header so that the - // server will close the socket after transmitting the response. This will - // allow us to treat all data up until the EOF as the content. - std::ostream request_stream(&request_); - request_stream << "GET " << path << " HTTP/1.0\r\n"; - request_stream << "Host: " << server << "\r\n"; - request_stream << "Accept: */*\r\n"; - request_stream << "Connection: close\r\n\r\n"; - - // Start an asynchronous resolve to translate the server and service names - // into a list of endpoints. - tcp::resolver::query query(server, "http"); - resolver_.async_resolve(query, - boost::bind(&client::handle_resolve, this, - boost::asio::placeholders::error, - boost::asio::placeholders::iterator)); - } - -private: - void handle_resolve(const boost::system::error_code& err, - tcp::resolver::iterator endpoint_iterator) - { - if (!err) - { - // Attempt a connection to each endpoint in the list until we - // successfully establish a connection. - boost::asio::async_connect(socket_, endpoint_iterator, - boost::bind(&client::handle_connect, this, - boost::asio::placeholders::error)); - } - else - { - std::cout << "Error: " << err.message() << "\n"; - } - } - - void handle_connect(const boost::system::error_code& err) - { - if (!err) - { - // The connection was successful. Send the request. - boost::asio::async_write(socket_, request_, - boost::bind(&client::handle_write_request, this, - boost::asio::placeholders::error)); - } - else - { - std::cout << "Error: " << err.message() << "\n"; - } - } - - void handle_write_request(const boost::system::error_code& err) - { - if (!err) - { - // Read the response status line. The response_ streambuf will - // automatically grow to accommodate the entire line. The growth may be - // limited by passing a maximum size to the streambuf constructor. - boost::asio::async_read_until(socket_, response_, "\r\n", - boost::bind(&client::handle_read_status_line, this, - boost::asio::placeholders::error)); - } - else - { - std::cout << "Error: " << err.message() << "\n"; - } - } - - void handle_read_status_line(const boost::system::error_code& err) - { - if (!err) - { - // Check that response is OK. - std::istream response_stream(&response_); - std::string http_version; - response_stream >> http_version; - unsigned int status_code; - response_stream >> status_code; - std::string status_message; - std::getline(response_stream, status_message); - if (!response_stream || http_version.substr(0, 5) != "HTTP/") - { - std::cout << "Invalid response\n"; - return; - } - if (status_code != 200) - { - std::cout << "Response returned with status code "; - std::cout << status_code << "\n"; - return; - } - - // Read the response headers, which are terminated by a blank line. - boost::asio::async_read_until(socket_, response_, "\r\n\r\n", - boost::bind(&client::handle_read_headers, this, - boost::asio::placeholders::error)); - } - else - { - std::cout << "Error: " << err << "\n"; - } - } - - void handle_read_headers(const boost::system::error_code& err) - { - if (!err) - { - // Process the response headers. - std::istream response_stream(&response_); - std::string header; - while (std::getline(response_stream, header) && header != "\r") - std::cout << header << "\n"; - std::cout << "\n"; - - // Write whatever content we already have to output. - if (response_.size() > 0) - std::cout << &response_; - - // Start reading remaining data until EOF. - boost::asio::async_read(socket_, response_, - boost::asio::transfer_at_least(1), - boost::bind(&client::handle_read_content, this, - boost::asio::placeholders::error)); - } - else - { - std::cout << "Error: " << err << "\n"; - } - } - - void handle_read_content(const boost::system::error_code& err) - { - if (!err) - { - // Write all of the data that has been read so far. - std::cout << &response_; - - // Continue reading remaining data until EOF. - boost::asio::async_read(socket_, response_, - boost::asio::transfer_at_least(1), - boost::bind(&client::handle_read_content, this, - boost::asio::placeholders::error)); - } - else if (err != boost::asio::error::eof) - { - std::cout << "Error: " << err << "\n"; - } - } - - tcp::resolver resolver_; - tcp::socket socket_; - boost::asio::streambuf request_; - boost::asio::streambuf response_; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 3) - { - std::cout << "Usage: async_client <server> <path>\n"; - std::cout << "Example:\n"; - std::cout << " async_client www.boost.org /LICENSE_1_0.txt\n"; - return 1; - } - - boost::asio::io_service io_service; - client c(io_service, argv[1], argv[2]); - io_service.run(); - } - catch (std::exception& e) - { - std::cout << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/http/client/sync_client.cpp b/doc/html/boost_asio/example/cpp03/http/client/sync_client.cpp deleted file mode 100644 index 605f439a11..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/client/sync_client.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// -// sync_client.cpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <iostream> -#include <istream> -#include <ostream> -#include <string> -#include <boost/asio.hpp> - -using boost::asio::ip::tcp; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 3) - { - std::cout << "Usage: sync_client <server> <path>\n"; - std::cout << "Example:\n"; - std::cout << " sync_client www.boost.org /LICENSE_1_0.txt\n"; - return 1; - } - - boost::asio::io_service io_service; - - // Get a list of endpoints corresponding to the server name. - tcp::resolver resolver(io_service); - tcp::resolver::query query(argv[1], "http"); - tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); - - // Try each endpoint until we successfully establish a connection. - tcp::socket socket(io_service); - boost::asio::connect(socket, endpoint_iterator); - - // Form the request. We specify the "Connection: close" header so that the - // server will close the socket after transmitting the response. This will - // allow us to treat all data up until the EOF as the content. - boost::asio::streambuf request; - std::ostream request_stream(&request); - request_stream << "GET " << argv[2] << " HTTP/1.0\r\n"; - request_stream << "Host: " << argv[1] << "\r\n"; - request_stream << "Accept: */*\r\n"; - request_stream << "Connection: close\r\n\r\n"; - - // Send the request. - boost::asio::write(socket, request); - - // Read the response status line. The response streambuf will automatically - // grow to accommodate the entire line. The growth may be limited by passing - // a maximum size to the streambuf constructor. - boost::asio::streambuf response; - boost::asio::read_until(socket, response, "\r\n"); - - // Check that response is OK. - std::istream response_stream(&response); - std::string http_version; - response_stream >> http_version; - unsigned int status_code; - response_stream >> status_code; - std::string status_message; - std::getline(response_stream, status_message); - if (!response_stream || http_version.substr(0, 5) != "HTTP/") - { - std::cout << "Invalid response\n"; - return 1; - } - if (status_code != 200) - { - std::cout << "Response returned with status code " << status_code << "\n"; - return 1; - } - - // Read the response headers, which are terminated by a blank line. - boost::asio::read_until(socket, response, "\r\n\r\n"); - - // Process the response headers. - std::string header; - while (std::getline(response_stream, header) && header != "\r") - std::cout << header << "\n"; - std::cout << "\n"; - - // Write whatever content we already have to output. - if (response.size() > 0) - std::cout << &response; - - // Read until EOF, writing data to output as we go. - boost::system::error_code error; - while (boost::asio::read(socket, response, - boost::asio::transfer_at_least(1), error)) - std::cout << &response; - if (error != boost::asio::error::eof) - throw boost::system::system_error(error); - } - catch (std::exception& e) - { - std::cout << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/http/server/connection.cpp b/doc/html/boost_asio/example/cpp03/http/server/connection.cpp deleted file mode 100644 index cf1d4a3b43..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server/connection.cpp +++ /dev/null @@ -1,99 +0,0 @@ -// -// connection.cpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "connection.hpp" -#include <vector> -#include <boost/bind.hpp> -#include "connection_manager.hpp" -#include "request_handler.hpp" - -namespace http { -namespace server { - -connection::connection(boost::asio::io_service& io_service, - connection_manager& manager, request_handler& handler) - : socket_(io_service), - connection_manager_(manager), - request_handler_(handler) -{ -} - -boost::asio::ip::tcp::socket& connection::socket() -{ - return socket_; -} - -void connection::start() -{ - socket_.async_read_some(boost::asio::buffer(buffer_), - boost::bind(&connection::handle_read, shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); -} - -void connection::stop() -{ - socket_.close(); -} - -void connection::handle_read(const boost::system::error_code& e, - std::size_t bytes_transferred) -{ - if (!e) - { - boost::tribool result; - boost::tie(result, boost::tuples::ignore) = request_parser_.parse( - request_, buffer_.data(), buffer_.data() + bytes_transferred); - - if (result) - { - request_handler_.handle_request(request_, reply_); - boost::asio::async_write(socket_, reply_.to_buffers(), - boost::bind(&connection::handle_write, shared_from_this(), - boost::asio::placeholders::error)); - } - else if (!result) - { - reply_ = reply::stock_reply(reply::bad_request); - boost::asio::async_write(socket_, reply_.to_buffers(), - boost::bind(&connection::handle_write, shared_from_this(), - boost::asio::placeholders::error)); - } - else - { - socket_.async_read_some(boost::asio::buffer(buffer_), - boost::bind(&connection::handle_read, shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - } - else if (e != boost::asio::error::operation_aborted) - { - connection_manager_.stop(shared_from_this()); - } -} - -void connection::handle_write(const boost::system::error_code& e) -{ - if (!e) - { - // Initiate graceful connection closure. - boost::system::error_code ignored_ec; - socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec); - } - - if (e != boost::asio::error::operation_aborted) - { - connection_manager_.stop(shared_from_this()); - } -} - -} // namespace server -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server/connection.hpp b/doc/html/boost_asio/example/cpp03/http/server/connection.hpp deleted file mode 100644 index 88ba0db8d4..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server/connection.hpp +++ /dev/null @@ -1,83 +0,0 @@ -// -// connection.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_CONNECTION_HPP -#define HTTP_CONNECTION_HPP - -#include <boost/asio.hpp> -#include <boost/array.hpp> -#include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> -#include "reply.hpp" -#include "request.hpp" -#include "request_handler.hpp" -#include "request_parser.hpp" - -namespace http { -namespace server { - -class connection_manager; - -/// Represents a single connection from a client. -class connection - : public boost::enable_shared_from_this<connection>, - private boost::noncopyable -{ -public: - /// Construct a connection with the given io_service. - explicit connection(boost::asio::io_service& io_service, - connection_manager& manager, request_handler& handler); - - /// Get the socket associated with the connection. - boost::asio::ip::tcp::socket& socket(); - - /// Start the first asynchronous operation for the connection. - void start(); - - /// Stop all asynchronous operations associated with the connection. - void stop(); - -private: - /// Handle completion of a read operation. - void handle_read(const boost::system::error_code& e, - std::size_t bytes_transferred); - - /// Handle completion of a write operation. - void handle_write(const boost::system::error_code& e); - - /// Socket for the connection. - boost::asio::ip::tcp::socket socket_; - - /// The manager for this connection. - connection_manager& connection_manager_; - - /// The handler used to process the incoming request. - request_handler& request_handler_; - - /// Buffer for incoming data. - boost::array<char, 8192> buffer_; - - /// The incoming request. - request request_; - - /// The parser for the incoming request. - request_parser request_parser_; - - /// The reply to be sent back to the client. - reply reply_; -}; - -typedef boost::shared_ptr<connection> connection_ptr; - -} // namespace server -} // namespace http - -#endif // HTTP_CONNECTION_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server/connection_manager.cpp b/doc/html/boost_asio/example/cpp03/http/server/connection_manager.cpp deleted file mode 100644 index 3b0bfb193d..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server/connection_manager.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// connection_manager.cpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "connection_manager.hpp" -#include <algorithm> -#include <boost/bind.hpp> - -namespace http { -namespace server { - -void connection_manager::start(connection_ptr c) -{ - connections_.insert(c); - c->start(); -} - -void connection_manager::stop(connection_ptr c) -{ - connections_.erase(c); - c->stop(); -} - -void connection_manager::stop_all() -{ - std::for_each(connections_.begin(), connections_.end(), - boost::bind(&connection::stop, _1)); - connections_.clear(); -} - -} // namespace server -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server/connection_manager.hpp b/doc/html/boost_asio/example/cpp03/http/server/connection_manager.hpp deleted file mode 100644 index 086801450e..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server/connection_manager.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// -// connection_manager.hpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_CONNECTION_MANAGER_HPP -#define HTTP_CONNECTION_MANAGER_HPP - -#include <set> -#include <boost/noncopyable.hpp> -#include "connection.hpp" - -namespace http { -namespace server { - -/// Manages open connections so that they may be cleanly stopped when the server -/// needs to shut down. -class connection_manager - : private boost::noncopyable -{ -public: - /// Add the specified connection to the manager and start it. - void start(connection_ptr c); - - /// Stop the specified connection. - void stop(connection_ptr c); - - /// Stop all connections. - void stop_all(); - -private: - /// The managed connections. - std::set<connection_ptr> connections_; -}; - -} // namespace server -} // namespace http - -#endif // HTTP_CONNECTION_MANAGER_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server/header.hpp b/doc/html/boost_asio/example/cpp03/http/server/header.hpp deleted file mode 100644 index 524097edc6..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server/header.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// -// header.hpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_HEADER_HPP -#define HTTP_HEADER_HPP - -#include <string> - -namespace http { -namespace server { - -struct header -{ - std::string name; - std::string value; -}; - -} // namespace server -} // namespace http - -#endif // HTTP_HEADER_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server/main.cpp b/doc/html/boost_asio/example/cpp03/http/server/main.cpp deleted file mode 100644 index a9d14bcb51..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server/main.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// -// main.cpp -// ~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <iostream> -#include <string> -#include <boost/asio.hpp> -#include <boost/bind.hpp> -#include "server.hpp" - -int main(int argc, char* argv[]) -{ - try - { - // Check command line arguments. - if (argc != 4) - { - std::cerr << "Usage: http_server <address> <port> <doc_root>\n"; - std::cerr << " For IPv4, try:\n"; - std::cerr << " receiver 0.0.0.0 80 .\n"; - std::cerr << " For IPv6, try:\n"; - std::cerr << " receiver 0::0 80 .\n"; - return 1; - } - - // Initialise the server. - http::server::server s(argv[1], argv[2], argv[3]); - - // Run the server until stopped. - s.run(); - } - catch (std::exception& e) - { - std::cerr << "exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/http/server/mime_types.cpp b/doc/html/boost_asio/example/cpp03/http/server/mime_types.cpp deleted file mode 100644 index 05ee50c089..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server/mime_types.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// mime_types.cpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "mime_types.hpp" - -namespace http { -namespace server { -namespace mime_types { - -struct mapping -{ - const char* extension; - const char* mime_type; -} mappings[] = -{ - { "gif", "image/gif" }, - { "htm", "text/html" }, - { "html", "text/html" }, - { "jpg", "image/jpeg" }, - { "png", "image/png" }, - { 0, 0 } // Marks end of list. -}; - -std::string extension_to_type(const std::string& extension) -{ - for (mapping* m = mappings; m->extension; ++m) - { - if (m->extension == extension) - { - return m->mime_type; - } - } - - return "text/plain"; -} - -} // namespace mime_types -} // namespace server -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server/mime_types.hpp b/doc/html/boost_asio/example/cpp03/http/server/mime_types.hpp deleted file mode 100644 index e5881f2e88..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server/mime_types.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// -// mime_types.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_MIME_TYPES_HPP -#define HTTP_MIME_TYPES_HPP - -#include <string> - -namespace http { -namespace server { -namespace mime_types { - -/// Convert a file extension into a MIME type. -std::string extension_to_type(const std::string& extension); - -} // namespace mime_types -} // namespace server -} // namespace http - -#endif // HTTP_MIME_TYPES_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server/reply.cpp b/doc/html/boost_asio/example/cpp03/http/server/reply.cpp deleted file mode 100644 index e9d06010b2..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server/reply.cpp +++ /dev/null @@ -1,256 +0,0 @@ -// -// reply.cpp -// ~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "reply.hpp" -#include <string> -#include <boost/lexical_cast.hpp> - -namespace http { -namespace server { - -namespace status_strings { - -const std::string ok = - "HTTP/1.0 200 OK\r\n"; -const std::string created = - "HTTP/1.0 201 Created\r\n"; -const std::string accepted = - "HTTP/1.0 202 Accepted\r\n"; -const std::string no_content = - "HTTP/1.0 204 No Content\r\n"; -const std::string multiple_choices = - "HTTP/1.0 300 Multiple Choices\r\n"; -const std::string moved_permanently = - "HTTP/1.0 301 Moved Permanently\r\n"; -const std::string moved_temporarily = - "HTTP/1.0 302 Moved Temporarily\r\n"; -const std::string not_modified = - "HTTP/1.0 304 Not Modified\r\n"; -const std::string bad_request = - "HTTP/1.0 400 Bad Request\r\n"; -const std::string unauthorized = - "HTTP/1.0 401 Unauthorized\r\n"; -const std::string forbidden = - "HTTP/1.0 403 Forbidden\r\n"; -const std::string not_found = - "HTTP/1.0 404 Not Found\r\n"; -const std::string internal_server_error = - "HTTP/1.0 500 Internal Server Error\r\n"; -const std::string not_implemented = - "HTTP/1.0 501 Not Implemented\r\n"; -const std::string bad_gateway = - "HTTP/1.0 502 Bad Gateway\r\n"; -const std::string service_unavailable = - "HTTP/1.0 503 Service Unavailable\r\n"; - -boost::asio::const_buffer to_buffer(reply::status_type status) -{ - switch (status) - { - case reply::ok: - return boost::asio::buffer(ok); - case reply::created: - return boost::asio::buffer(created); - case reply::accepted: - return boost::asio::buffer(accepted); - case reply::no_content: - return boost::asio::buffer(no_content); - case reply::multiple_choices: - return boost::asio::buffer(multiple_choices); - case reply::moved_permanently: - return boost::asio::buffer(moved_permanently); - case reply::moved_temporarily: - return boost::asio::buffer(moved_temporarily); - case reply::not_modified: - return boost::asio::buffer(not_modified); - case reply::bad_request: - return boost::asio::buffer(bad_request); - case reply::unauthorized: - return boost::asio::buffer(unauthorized); - case reply::forbidden: - return boost::asio::buffer(forbidden); - case reply::not_found: - return boost::asio::buffer(not_found); - case reply::internal_server_error: - return boost::asio::buffer(internal_server_error); - case reply::not_implemented: - return boost::asio::buffer(not_implemented); - case reply::bad_gateway: - return boost::asio::buffer(bad_gateway); - case reply::service_unavailable: - return boost::asio::buffer(service_unavailable); - default: - return boost::asio::buffer(internal_server_error); - } -} - -} // namespace status_strings - -namespace misc_strings { - -const char name_value_separator[] = { ':', ' ' }; -const char crlf[] = { '\r', '\n' }; - -} // namespace misc_strings - -std::vector<boost::asio::const_buffer> reply::to_buffers() -{ - std::vector<boost::asio::const_buffer> buffers; - buffers.push_back(status_strings::to_buffer(status)); - for (std::size_t i = 0; i < headers.size(); ++i) - { - header& h = headers[i]; - buffers.push_back(boost::asio::buffer(h.name)); - buffers.push_back(boost::asio::buffer(misc_strings::name_value_separator)); - buffers.push_back(boost::asio::buffer(h.value)); - buffers.push_back(boost::asio::buffer(misc_strings::crlf)); - } - buffers.push_back(boost::asio::buffer(misc_strings::crlf)); - buffers.push_back(boost::asio::buffer(content)); - return buffers; -} - -namespace stock_replies { - -const char ok[] = ""; -const char created[] = - "<html>" - "<head><title>Created</title></head>" - "<body><h1>201 Created</h1></body>" - "</html>"; -const char accepted[] = - "<html>" - "<head><title>Accepted</title></head>" - "<body><h1>202 Accepted</h1></body>" - "</html>"; -const char no_content[] = - "<html>" - "<head><title>No Content</title></head>" - "<body><h1>204 Content</h1></body>" - "</html>"; -const char multiple_choices[] = - "<html>" - "<head><title>Multiple Choices</title></head>" - "<body><h1>300 Multiple Choices</h1></body>" - "</html>"; -const char moved_permanently[] = - "<html>" - "<head><title>Moved Permanently</title></head>" - "<body><h1>301 Moved Permanently</h1></body>" - "</html>"; -const char moved_temporarily[] = - "<html>" - "<head><title>Moved Temporarily</title></head>" - "<body><h1>302 Moved Temporarily</h1></body>" - "</html>"; -const char not_modified[] = - "<html>" - "<head><title>Not Modified</title></head>" - "<body><h1>304 Not Modified</h1></body>" - "</html>"; -const char bad_request[] = - "<html>" - "<head><title>Bad Request</title></head>" - "<body><h1>400 Bad Request</h1></body>" - "</html>"; -const char unauthorized[] = - "<html>" - "<head><title>Unauthorized</title></head>" - "<body><h1>401 Unauthorized</h1></body>" - "</html>"; -const char forbidden[] = - "<html>" - "<head><title>Forbidden</title></head>" - "<body><h1>403 Forbidden</h1></body>" - "</html>"; -const char not_found[] = - "<html>" - "<head><title>Not Found</title></head>" - "<body><h1>404 Not Found</h1></body>" - "</html>"; -const char internal_server_error[] = - "<html>" - "<head><title>Internal Server Error</title></head>" - "<body><h1>500 Internal Server Error</h1></body>" - "</html>"; -const char not_implemented[] = - "<html>" - "<head><title>Not Implemented</title></head>" - "<body><h1>501 Not Implemented</h1></body>" - "</html>"; -const char bad_gateway[] = - "<html>" - "<head><title>Bad Gateway</title></head>" - "<body><h1>502 Bad Gateway</h1></body>" - "</html>"; -const char service_unavailable[] = - "<html>" - "<head><title>Service Unavailable</title></head>" - "<body><h1>503 Service Unavailable</h1></body>" - "</html>"; - -std::string to_string(reply::status_type status) -{ - switch (status) - { - case reply::ok: - return ok; - case reply::created: - return created; - case reply::accepted: - return accepted; - case reply::no_content: - return no_content; - case reply::multiple_choices: - return multiple_choices; - case reply::moved_permanently: - return moved_permanently; - case reply::moved_temporarily: - return moved_temporarily; - case reply::not_modified: - return not_modified; - case reply::bad_request: - return bad_request; - case reply::unauthorized: - return unauthorized; - case reply::forbidden: - return forbidden; - case reply::not_found: - return not_found; - case reply::internal_server_error: - return internal_server_error; - case reply::not_implemented: - return not_implemented; - case reply::bad_gateway: - return bad_gateway; - case reply::service_unavailable: - return service_unavailable; - default: - return internal_server_error; - } -} - -} // namespace stock_replies - -reply reply::stock_reply(reply::status_type status) -{ - reply rep; - rep.status = status; - rep.content = stock_replies::to_string(status); - rep.headers.resize(2); - rep.headers[0].name = "Content-Length"; - rep.headers[0].value = boost::lexical_cast<std::string>(rep.content.size()); - rep.headers[1].name = "Content-Type"; - rep.headers[1].value = "text/html"; - return rep; -} - -} // namespace server -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server/reply.hpp b/doc/html/boost_asio/example/cpp03/http/server/reply.hpp deleted file mode 100644 index f391121952..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server/reply.hpp +++ /dev/null @@ -1,64 +0,0 @@ -// -// reply.hpp -// ~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_REPLY_HPP -#define HTTP_REPLY_HPP - -#include <string> -#include <vector> -#include <boost/asio.hpp> -#include "header.hpp" - -namespace http { -namespace server { - -/// A reply to be sent to a client. -struct reply -{ - /// The status of the reply. - 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, - internal_server_error = 500, - not_implemented = 501, - bad_gateway = 502, - service_unavailable = 503 - } status; - - /// The headers to be included in the reply. - std::vector<header> headers; - - /// The content to be sent in the reply. - std::string content; - - /// Convert the reply into a vector of buffers. The buffers do not own the - /// underlying memory blocks, therefore the reply object must remain valid and - /// not be changed until the write operation has completed. - std::vector<boost::asio::const_buffer> to_buffers(); - - /// Get a stock reply. - static reply stock_reply(status_type status); -}; - -} // namespace server -} // namespace http - -#endif // HTTP_REPLY_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server/request.hpp b/doc/html/boost_asio/example/cpp03/http/server/request.hpp deleted file mode 100644 index 2a38f39e48..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server/request.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// -// request.hpp -// ~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_REQUEST_HPP -#define HTTP_REQUEST_HPP - -#include <string> -#include <vector> -#include "header.hpp" - -namespace http { -namespace server { - -/// A request received from a client. -struct request -{ - std::string method; - std::string uri; - int http_version_major; - int http_version_minor; - std::vector<header> headers; -}; - -} // namespace server -} // namespace http - -#endif // HTTP_REQUEST_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server/request_handler.cpp b/doc/html/boost_asio/example/cpp03/http/server/request_handler.cpp deleted file mode 100644 index e9cf1b0959..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server/request_handler.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// -// request_handler.cpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "request_handler.hpp" -#include <fstream> -#include <sstream> -#include <string> -#include <boost/lexical_cast.hpp> -#include "mime_types.hpp" -#include "reply.hpp" -#include "request.hpp" - -namespace http { -namespace server { - -request_handler::request_handler(const std::string& doc_root) - : doc_root_(doc_root) -{ -} - -void request_handler::handle_request(const request& req, reply& rep) -{ - // Decode url to path. - std::string request_path; - if (!url_decode(req.uri, request_path)) - { - rep = reply::stock_reply(reply::bad_request); - return; - } - - // Request path must be absolute and not contain "..". - if (request_path.empty() || request_path[0] != '/' - || request_path.find("..") != std::string::npos) - { - rep = reply::stock_reply(reply::bad_request); - return; - } - - // If path ends in slash (i.e. is a directory) then add "index.html". - if (request_path[request_path.size() - 1] == '/') - { - request_path += "index.html"; - } - - // Determine the file extension. - std::size_t last_slash_pos = request_path.find_last_of("/"); - std::size_t last_dot_pos = request_path.find_last_of("."); - std::string extension; - if (last_dot_pos != std::string::npos && last_dot_pos > last_slash_pos) - { - extension = request_path.substr(last_dot_pos + 1); - } - - // Open the file to send back. - std::string full_path = doc_root_ + request_path; - std::ifstream is(full_path.c_str(), std::ios::in | std::ios::binary); - if (!is) - { - rep = reply::stock_reply(reply::not_found); - return; - } - - // Fill out the reply to be sent to the client. - rep.status = reply::ok; - char buf[512]; - while (is.read(buf, sizeof(buf)).gcount() > 0) - rep.content.append(buf, is.gcount()); - rep.headers.resize(2); - rep.headers[0].name = "Content-Length"; - rep.headers[0].value = boost::lexical_cast<std::string>(rep.content.size()); - rep.headers[1].name = "Content-Type"; - rep.headers[1].value = mime_types::extension_to_type(extension); -} - -bool request_handler::url_decode(const std::string& in, std::string& out) -{ - out.clear(); - out.reserve(in.size()); - for (std::size_t i = 0; i < in.size(); ++i) - { - if (in[i] == '%') - { - if (i + 3 <= in.size()) - { - int value = 0; - std::istringstream is(in.substr(i + 1, 2)); - if (is >> std::hex >> value) - { - out += static_cast<char>(value); - i += 2; - } - else - { - return false; - } - } - else - { - return false; - } - } - else if (in[i] == '+') - { - out += ' '; - } - else - { - out += in[i]; - } - } - return true; -} - -} // namespace server -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server/request_handler.hpp b/doc/html/boost_asio/example/cpp03/http/server/request_handler.hpp deleted file mode 100644 index 40f187e033..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server/request_handler.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// request_handler.hpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_REQUEST_HANDLER_HPP -#define HTTP_REQUEST_HANDLER_HPP - -#include <string> -#include <boost/noncopyable.hpp> - -namespace http { -namespace server { - -struct reply; -struct request; - -/// The common handler for all incoming requests. -class request_handler - : private boost::noncopyable -{ -public: - /// Construct with a directory containing files to be served. - explicit request_handler(const std::string& doc_root); - - /// Handle a request and produce a reply. - void handle_request(const request& req, reply& rep); - -private: - /// The directory containing the files to be served. - std::string doc_root_; - - /// Perform URL-decoding on a string. Returns false if the encoding was - /// invalid. - static bool url_decode(const std::string& in, std::string& out); -}; - -} // namespace server -} // namespace http - -#endif // HTTP_REQUEST_HANDLER_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server/request_parser.cpp b/doc/html/boost_asio/example/cpp03/http/server/request_parser.cpp deleted file mode 100644 index 94598b816b..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server/request_parser.cpp +++ /dev/null @@ -1,315 +0,0 @@ -// -// request_parser.cpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "request_parser.hpp" -#include "request.hpp" - -namespace http { -namespace server { - -request_parser::request_parser() - : state_(method_start) -{ -} - -void request_parser::reset() -{ - state_ = method_start; -} - -boost::tribool request_parser::consume(request& req, char input) -{ - switch (state_) - { - case method_start: - if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return false; - } - else - { - state_ = method; - req.method.push_back(input); - return boost::indeterminate; - } - case method: - if (input == ' ') - { - state_ = uri; - return boost::indeterminate; - } - else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return false; - } - else - { - req.method.push_back(input); - return boost::indeterminate; - } - case uri: - if (input == ' ') - { - state_ = http_version_h; - return boost::indeterminate; - } - else if (is_ctl(input)) - { - return false; - } - else - { - req.uri.push_back(input); - return boost::indeterminate; - } - case http_version_h: - if (input == 'H') - { - state_ = http_version_t_1; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_t_1: - if (input == 'T') - { - state_ = http_version_t_2; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_t_2: - if (input == 'T') - { - state_ = http_version_p; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_p: - if (input == 'P') - { - state_ = http_version_slash; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_slash: - if (input == '/') - { - req.http_version_major = 0; - req.http_version_minor = 0; - state_ = http_version_major_start; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_major_start: - if (is_digit(input)) - { - req.http_version_major = req.http_version_major * 10 + input - '0'; - state_ = http_version_major; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_major: - if (input == '.') - { - state_ = http_version_minor_start; - return boost::indeterminate; - } - else if (is_digit(input)) - { - req.http_version_major = req.http_version_major * 10 + input - '0'; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_minor_start: - if (is_digit(input)) - { - req.http_version_minor = req.http_version_minor * 10 + input - '0'; - state_ = http_version_minor; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_minor: - if (input == '\r') - { - state_ = expecting_newline_1; - return boost::indeterminate; - } - else if (is_digit(input)) - { - req.http_version_minor = req.http_version_minor * 10 + input - '0'; - return boost::indeterminate; - } - else - { - return false; - } - case expecting_newline_1: - if (input == '\n') - { - state_ = header_line_start; - return boost::indeterminate; - } - else - { - return false; - } - case header_line_start: - if (input == '\r') - { - state_ = expecting_newline_3; - return boost::indeterminate; - } - else if (!req.headers.empty() && (input == ' ' || input == '\t')) - { - state_ = header_lws; - return boost::indeterminate; - } - else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return false; - } - else - { - req.headers.push_back(header()); - req.headers.back().name.push_back(input); - state_ = header_name; - return boost::indeterminate; - } - case header_lws: - if (input == '\r') - { - state_ = expecting_newline_2; - return boost::indeterminate; - } - else if (input == ' ' || input == '\t') - { - return boost::indeterminate; - } - else if (is_ctl(input)) - { - return false; - } - else - { - state_ = header_value; - req.headers.back().value.push_back(input); - return boost::indeterminate; - } - case header_name: - if (input == ':') - { - state_ = space_before_header_value; - return boost::indeterminate; - } - else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return false; - } - else - { - req.headers.back().name.push_back(input); - return boost::indeterminate; - } - case space_before_header_value: - if (input == ' ') - { - state_ = header_value; - return boost::indeterminate; - } - else - { - return false; - } - case header_value: - if (input == '\r') - { - state_ = expecting_newline_2; - return boost::indeterminate; - } - else if (is_ctl(input)) - { - return false; - } - else - { - req.headers.back().value.push_back(input); - return boost::indeterminate; - } - case expecting_newline_2: - if (input == '\n') - { - state_ = header_line_start; - return boost::indeterminate; - } - else - { - return false; - } - case expecting_newline_3: - return (input == '\n'); - default: - return false; - } -} - -bool request_parser::is_char(int c) -{ - return c >= 0 && c <= 127; -} - -bool request_parser::is_ctl(int c) -{ - return (c >= 0 && c <= 31) || (c == 127); -} - -bool request_parser::is_tspecial(int c) -{ - switch (c) - { - case '(': case ')': case '<': case '>': case '@': - case ',': case ';': case ':': case '\\': case '"': - case '/': case '[': case ']': case '?': case '=': - case '{': case '}': case ' ': case '\t': - return true; - default: - return false; - } -} - -bool request_parser::is_digit(int c) -{ - return c >= '0' && c <= '9'; -} - -} // namespace server -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server/request_parser.hpp b/doc/html/boost_asio/example/cpp03/http/server/request_parser.hpp deleted file mode 100644 index 9146779896..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server/request_parser.hpp +++ /dev/null @@ -1,95 +0,0 @@ -// -// request_parser.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_REQUEST_PARSER_HPP -#define HTTP_REQUEST_PARSER_HPP - -#include <boost/logic/tribool.hpp> -#include <boost/tuple/tuple.hpp> - -namespace http { -namespace server { - -struct request; - -/// Parser for incoming requests. -class request_parser -{ -public: - /// Construct ready to parse the request method. - request_parser(); - - /// Reset to initial parser state. - void reset(); - - /// Parse some data. The tribool return value is true when a complete request - /// has been parsed, false if the data is invalid, indeterminate when more - /// data is required. The InputIterator return value indicates how much of the - /// input has been consumed. - template <typename InputIterator> - boost::tuple<boost::tribool, InputIterator> parse(request& req, - InputIterator begin, InputIterator end) - { - while (begin != end) - { - boost::tribool result = consume(req, *begin++); - if (result || !result) - return boost::make_tuple(result, begin); - } - boost::tribool result = boost::indeterminate; - return boost::make_tuple(result, begin); - } - -private: - /// Handle the next character of input. - boost::tribool consume(request& req, char input); - - /// Check if a byte is an HTTP character. - static bool is_char(int c); - - /// Check if a byte is an HTTP control character. - static bool is_ctl(int c); - - /// Check if a byte is defined as an HTTP tspecial character. - static bool is_tspecial(int c); - - /// Check if a byte is a digit. - static bool is_digit(int c); - - /// The current state of the parser. - enum state - { - method_start, - method, - uri, - http_version_h, - http_version_t_1, - http_version_t_2, - http_version_p, - http_version_slash, - http_version_major_start, - http_version_major, - http_version_minor_start, - http_version_minor, - expecting_newline_1, - header_line_start, - header_lws, - header_name, - space_before_header_value, - header_value, - expecting_newline_2, - expecting_newline_3 - } state_; -}; - -} // namespace server -} // namespace http - -#endif // HTTP_REQUEST_PARSER_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server/server.cpp b/doc/html/boost_asio/example/cpp03/http/server/server.cpp deleted file mode 100644 index e93cefa652..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server/server.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// -// server.cpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "server.hpp" -#include <boost/bind.hpp> -#include <signal.h> - -namespace http { -namespace server { - -server::server(const std::string& address, const std::string& port, - const std::string& doc_root) - : io_service_(), - signals_(io_service_), - acceptor_(io_service_), - connection_manager_(), - new_connection_(), - request_handler_(doc_root) -{ - // Register to handle the signals that indicate when the server should exit. - // It is safe to register for the same signal multiple times in a program, - // provided all registration for the specified signal is made through Asio. - signals_.add(SIGINT); - signals_.add(SIGTERM); -#if defined(SIGQUIT) - signals_.add(SIGQUIT); -#endif // defined(SIGQUIT) - signals_.async_wait(boost::bind(&server::handle_stop, this)); - - // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR). - boost::asio::ip::tcp::resolver resolver(io_service_); - boost::asio::ip::tcp::resolver::query query(address, port); - boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query); - acceptor_.open(endpoint.protocol()); - acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); - acceptor_.bind(endpoint); - acceptor_.listen(); - - start_accept(); -} - -void server::run() -{ - // The io_service::run() call will block until all asynchronous operations - // have finished. While the server is running, there is always at least one - // asynchronous operation outstanding: the asynchronous accept call waiting - // for new incoming connections. - io_service_.run(); -} - -void server::start_accept() -{ - new_connection_.reset(new connection(io_service_, - connection_manager_, request_handler_)); - acceptor_.async_accept(new_connection_->socket(), - boost::bind(&server::handle_accept, this, - boost::asio::placeholders::error)); -} - -void server::handle_accept(const boost::system::error_code& e) -{ - // Check whether the server was stopped by a signal before this completion - // handler had a chance to run. - if (!acceptor_.is_open()) - { - return; - } - - if (!e) - { - connection_manager_.start(new_connection_); - } - - start_accept(); -} - -void server::handle_stop() -{ - // The server is stopped by cancelling all outstanding asynchronous - // operations. Once all operations have finished the io_service::run() call - // will exit. - acceptor_.close(); - connection_manager_.stop_all(); -} - -} // namespace server -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server/server.hpp b/doc/html/boost_asio/example/cpp03/http/server/server.hpp deleted file mode 100644 index 27eaede19d..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server/server.hpp +++ /dev/null @@ -1,69 +0,0 @@ -// -// server.hpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER_HPP -#define HTTP_SERVER_HPP - -#include <boost/asio.hpp> -#include <string> -#include <boost/noncopyable.hpp> -#include "connection.hpp" -#include "connection_manager.hpp" -#include "request_handler.hpp" - -namespace http { -namespace server { - -/// The top-level class of the HTTP server. -class server - : private boost::noncopyable -{ -public: - /// Construct the server to listen on the specified TCP address and port, and - /// serve up files from the given directory. - explicit server(const std::string& address, const std::string& port, - const std::string& doc_root); - - /// Run the server's io_service loop. - void run(); - -private: - /// Initiate an asynchronous accept operation. - void start_accept(); - - /// Handle completion of an asynchronous accept operation. - void handle_accept(const boost::system::error_code& e); - - /// Handle a request to stop the server. - void handle_stop(); - - /// The io_service used to perform asynchronous operations. - boost::asio::io_service io_service_; - - /// The signal_set is used to register for process termination notifications. - boost::asio::signal_set signals_; - - /// Acceptor used to listen for incoming connections. - boost::asio::ip::tcp::acceptor acceptor_; - - /// The connection manager which owns all live connections. - connection_manager connection_manager_; - - /// The next connection to be accepted. - connection_ptr new_connection_; - - /// The handler for all incoming requests. - request_handler request_handler_; -}; - -} // namespace server -} // namespace http - -#endif // HTTP_SERVER_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server2/connection.cpp b/doc/html/boost_asio/example/cpp03/http/server2/connection.cpp deleted file mode 100644 index bf7f3cad04..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server2/connection.cpp +++ /dev/null @@ -1,93 +0,0 @@ -// -// connection.cpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "connection.hpp" -#include <vector> -#include <boost/bind.hpp> -#include "request_handler.hpp" - -namespace http { -namespace server2 { - -connection::connection(boost::asio::io_service& io_service, - request_handler& handler) - : socket_(io_service), - request_handler_(handler) -{ -} - -boost::asio::ip::tcp::socket& connection::socket() -{ - return socket_; -} - -void connection::start() -{ - socket_.async_read_some(boost::asio::buffer(buffer_), - boost::bind(&connection::handle_read, shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); -} - -void connection::handle_read(const boost::system::error_code& e, - std::size_t bytes_transferred) -{ - if (!e) - { - boost::tribool result; - boost::tie(result, boost::tuples::ignore) = request_parser_.parse( - request_, buffer_.data(), buffer_.data() + bytes_transferred); - - if (result) - { - request_handler_.handle_request(request_, reply_); - boost::asio::async_write(socket_, reply_.to_buffers(), - boost::bind(&connection::handle_write, shared_from_this(), - boost::asio::placeholders::error)); - } - else if (!result) - { - reply_ = reply::stock_reply(reply::bad_request); - boost::asio::async_write(socket_, reply_.to_buffers(), - boost::bind(&connection::handle_write, shared_from_this(), - boost::asio::placeholders::error)); - } - else - { - socket_.async_read_some(boost::asio::buffer(buffer_), - boost::bind(&connection::handle_read, shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - } - - // If an error occurs then no new asynchronous operations are started. This - // means that all shared_ptr references to the connection object will - // disappear and the object will be destroyed automatically after this - // handler returns. The connection class's destructor closes the socket. -} - -void connection::handle_write(const boost::system::error_code& e) -{ - if (!e) - { - // Initiate graceful connection closure. - boost::system::error_code ignored_ec; - socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec); - } - - // No new asynchronous operations are started. This means that all shared_ptr - // references to the connection object will disappear and the object will be - // destroyed automatically after this handler returns. The connection class's - // destructor closes the socket. -} - -} // namespace server2 -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server2/connection.hpp b/doc/html/boost_asio/example/cpp03/http/server2/connection.hpp deleted file mode 100644 index 75f4fee306..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server2/connection.hpp +++ /dev/null @@ -1,75 +0,0 @@ -// -// connection.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER2_CONNECTION_HPP -#define HTTP_SERVER2_CONNECTION_HPP - -#include <boost/asio.hpp> -#include <boost/array.hpp> -#include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> -#include "reply.hpp" -#include "request.hpp" -#include "request_handler.hpp" -#include "request_parser.hpp" - -namespace http { -namespace server2 { - -/// Represents a single connection from a client. -class connection - : public boost::enable_shared_from_this<connection>, - private boost::noncopyable -{ -public: - /// Construct a connection with the given io_service. - explicit connection(boost::asio::io_service& io_service, - request_handler& handler); - - /// Get the socket associated with the connection. - boost::asio::ip::tcp::socket& socket(); - - /// Start the first asynchronous operation for the connection. - void start(); - -private: - /// Handle completion of a read operation. - void handle_read(const boost::system::error_code& e, - std::size_t bytes_transferred); - - /// Handle completion of a write operation. - void handle_write(const boost::system::error_code& e); - - /// Socket for the connection. - boost::asio::ip::tcp::socket socket_; - - /// The handler used to process the incoming request. - request_handler& request_handler_; - - /// Buffer for incoming data. - boost::array<char, 8192> buffer_; - - /// The incoming request. - request request_; - - /// The parser for the incoming request. - request_parser request_parser_; - - /// The reply to be sent back to the client. - reply reply_; -}; - -typedef boost::shared_ptr<connection> connection_ptr; - -} // namespace server2 -} // namespace http - -#endif // HTTP_SERVER2_CONNECTION_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server2/header.hpp b/doc/html/boost_asio/example/cpp03/http/server2/header.hpp deleted file mode 100644 index b0bde07a48..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server2/header.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// -// header.hpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER2_HEADER_HPP -#define HTTP_SERVER2_HEADER_HPP - -#include <string> - -namespace http { -namespace server2 { - -struct header -{ - std::string name; - std::string value; -}; - -} // namespace server2 -} // namespace http - -#endif // HTTP_SERVER2_HEADER_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server2/io_service_pool.cpp b/doc/html/boost_asio/example/cpp03/http/server2/io_service_pool.cpp deleted file mode 100644 index a4a9c02fc3..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server2/io_service_pool.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// -// io_service_pool.cpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "server.hpp" -#include <stdexcept> -#include <boost/thread/thread.hpp> -#include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> - -namespace http { -namespace server2 { - -io_service_pool::io_service_pool(std::size_t pool_size) - : next_io_service_(0) -{ - if (pool_size == 0) - throw std::runtime_error("io_service_pool size is 0"); - - // Give all the io_services work to do so that their run() functions will not - // exit until they are explicitly stopped. - for (std::size_t i = 0; i < pool_size; ++i) - { - io_service_ptr io_service(new boost::asio::io_service); - work_ptr work(new boost::asio::io_service::work(*io_service)); - io_services_.push_back(io_service); - work_.push_back(work); - } -} - -void io_service_pool::run() -{ - // Create a pool of threads to run all of the io_services. - std::vector<boost::shared_ptr<boost::thread> > threads; - for (std::size_t i = 0; i < io_services_.size(); ++i) - { - boost::shared_ptr<boost::thread> thread(new boost::thread( - boost::bind(&boost::asio::io_service::run, io_services_[i]))); - threads.push_back(thread); - } - - // Wait for all threads in the pool to exit. - for (std::size_t i = 0; i < threads.size(); ++i) - threads[i]->join(); -} - -void io_service_pool::stop() -{ - // Explicitly stop all io_services. - for (std::size_t i = 0; i < io_services_.size(); ++i) - io_services_[i]->stop(); -} - -boost::asio::io_service& io_service_pool::get_io_service() -{ - // Use a round-robin scheme to choose the next io_service to use. - boost::asio::io_service& io_service = *io_services_[next_io_service_]; - ++next_io_service_; - if (next_io_service_ == io_services_.size()) - next_io_service_ = 0; - return io_service; -} - -} // namespace server2 -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server2/io_service_pool.hpp b/doc/html/boost_asio/example/cpp03/http/server2/io_service_pool.hpp deleted file mode 100644 index b714f53022..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server2/io_service_pool.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// -// io_service_pool.hpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER2_IO_SERVICE_POOL_HPP -#define HTTP_SERVER2_IO_SERVICE_POOL_HPP - -#include <boost/asio.hpp> -#include <vector> -#include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> - -namespace http { -namespace server2 { - -/// A pool of io_service objects. -class io_service_pool - : private boost::noncopyable -{ -public: - /// Construct the io_service pool. - explicit io_service_pool(std::size_t pool_size); - - /// Run all io_service objects in the pool. - void run(); - - /// Stop all io_service objects in the pool. - void stop(); - - /// Get an io_service to use. - boost::asio::io_service& get_io_service(); - -private: - typedef boost::shared_ptr<boost::asio::io_service> io_service_ptr; - typedef boost::shared_ptr<boost::asio::io_service::work> work_ptr; - - /// The pool of io_services. - std::vector<io_service_ptr> io_services_; - - /// The work that keeps the io_services running. - std::vector<work_ptr> work_; - - /// The next io_service to use for a connection. - std::size_t next_io_service_; -}; - -} // namespace server2 -} // namespace http - -#endif // HTTP_SERVER2_IO_SERVICE_POOL_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server2/main.cpp b/doc/html/boost_asio/example/cpp03/http/server2/main.cpp deleted file mode 100644 index aff4b192b2..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server2/main.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// main.cpp -// ~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <iostream> -#include <string> -#include <boost/asio.hpp> -#include <boost/bind.hpp> -#include <boost/lexical_cast.hpp> -#include "server.hpp" - -int main(int argc, char* argv[]) -{ - try - { - // Check command line arguments. - if (argc != 5) - { - std::cerr << "Usage: http_server <address> <port> <threads> <doc_root>\n"; - std::cerr << " For IPv4, try:\n"; - std::cerr << " receiver 0.0.0.0 80 1 .\n"; - std::cerr << " For IPv6, try:\n"; - std::cerr << " receiver 0::0 80 1 .\n"; - return 1; - } - - // Initialise the server. - std::size_t num_threads = boost::lexical_cast<std::size_t>(argv[3]); - http::server2::server s(argv[1], argv[2], argv[4], num_threads); - - // Run the server until stopped. - s.run(); - } - catch (std::exception& e) - { - std::cerr << "exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/http/server2/mime_types.cpp b/doc/html/boost_asio/example/cpp03/http/server2/mime_types.cpp deleted file mode 100644 index 11a47a688a..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server2/mime_types.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// mime_types.cpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "mime_types.hpp" - -namespace http { -namespace server2 { -namespace mime_types { - -struct mapping -{ - const char* extension; - const char* mime_type; -} mappings[] = -{ - { "gif", "image/gif" }, - { "htm", "text/html" }, - { "html", "text/html" }, - { "jpg", "image/jpeg" }, - { "png", "image/png" }, - { 0, 0 } // Marks end of list. -}; - -std::string extension_to_type(const std::string& extension) -{ - for (mapping* m = mappings; m->extension; ++m) - { - if (m->extension == extension) - { - return m->mime_type; - } - } - - return "text/plain"; -} - -} // namespace mime_types -} // namespace server2 -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server2/mime_types.hpp b/doc/html/boost_asio/example/cpp03/http/server2/mime_types.hpp deleted file mode 100644 index e33c0e5c76..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server2/mime_types.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// -// mime_types.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER2_MIME_TYPES_HPP -#define HTTP_SERVER2_MIME_TYPES_HPP - -#include <string> - -namespace http { -namespace server2 { -namespace mime_types { - -/// Convert a file extension into a MIME type. -std::string extension_to_type(const std::string& extension); - -} // namespace mime_types -} // namespace server2 -} // namespace http - -#endif // HTTP_SERVER2_MIME_TYPES_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server2/reply.cpp b/doc/html/boost_asio/example/cpp03/http/server2/reply.cpp deleted file mode 100644 index 626808bc05..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server2/reply.cpp +++ /dev/null @@ -1,256 +0,0 @@ -// -// reply.cpp -// ~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "reply.hpp" -#include <string> -#include <boost/lexical_cast.hpp> - -namespace http { -namespace server2 { - -namespace status_strings { - -const std::string ok = - "HTTP/1.0 200 OK\r\n"; -const std::string created = - "HTTP/1.0 201 Created\r\n"; -const std::string accepted = - "HTTP/1.0 202 Accepted\r\n"; -const std::string no_content = - "HTTP/1.0 204 No Content\r\n"; -const std::string multiple_choices = - "HTTP/1.0 300 Multiple Choices\r\n"; -const std::string moved_permanently = - "HTTP/1.0 301 Moved Permanently\r\n"; -const std::string moved_temporarily = - "HTTP/1.0 302 Moved Temporarily\r\n"; -const std::string not_modified = - "HTTP/1.0 304 Not Modified\r\n"; -const std::string bad_request = - "HTTP/1.0 400 Bad Request\r\n"; -const std::string unauthorized = - "HTTP/1.0 401 Unauthorized\r\n"; -const std::string forbidden = - "HTTP/1.0 403 Forbidden\r\n"; -const std::string not_found = - "HTTP/1.0 404 Not Found\r\n"; -const std::string internal_server_error = - "HTTP/1.0 500 Internal Server Error\r\n"; -const std::string not_implemented = - "HTTP/1.0 501 Not Implemented\r\n"; -const std::string bad_gateway = - "HTTP/1.0 502 Bad Gateway\r\n"; -const std::string service_unavailable = - "HTTP/1.0 503 Service Unavailable\r\n"; - -boost::asio::const_buffer to_buffer(reply::status_type status) -{ - switch (status) - { - case reply::ok: - return boost::asio::buffer(ok); - case reply::created: - return boost::asio::buffer(created); - case reply::accepted: - return boost::asio::buffer(accepted); - case reply::no_content: - return boost::asio::buffer(no_content); - case reply::multiple_choices: - return boost::asio::buffer(multiple_choices); - case reply::moved_permanently: - return boost::asio::buffer(moved_permanently); - case reply::moved_temporarily: - return boost::asio::buffer(moved_temporarily); - case reply::not_modified: - return boost::asio::buffer(not_modified); - case reply::bad_request: - return boost::asio::buffer(bad_request); - case reply::unauthorized: - return boost::asio::buffer(unauthorized); - case reply::forbidden: - return boost::asio::buffer(forbidden); - case reply::not_found: - return boost::asio::buffer(not_found); - case reply::internal_server_error: - return boost::asio::buffer(internal_server_error); - case reply::not_implemented: - return boost::asio::buffer(not_implemented); - case reply::bad_gateway: - return boost::asio::buffer(bad_gateway); - case reply::service_unavailable: - return boost::asio::buffer(service_unavailable); - default: - return boost::asio::buffer(internal_server_error); - } -} - -} // namespace status_strings - -namespace misc_strings { - -const char name_value_separator[] = { ':', ' ' }; -const char crlf[] = { '\r', '\n' }; - -} // namespace misc_strings - -std::vector<boost::asio::const_buffer> reply::to_buffers() -{ - std::vector<boost::asio::const_buffer> buffers; - buffers.push_back(status_strings::to_buffer(status)); - for (std::size_t i = 0; i < headers.size(); ++i) - { - header& h = headers[i]; - buffers.push_back(boost::asio::buffer(h.name)); - buffers.push_back(boost::asio::buffer(misc_strings::name_value_separator)); - buffers.push_back(boost::asio::buffer(h.value)); - buffers.push_back(boost::asio::buffer(misc_strings::crlf)); - } - buffers.push_back(boost::asio::buffer(misc_strings::crlf)); - buffers.push_back(boost::asio::buffer(content)); - return buffers; -} - -namespace stock_replies { - -const char ok[] = ""; -const char created[] = - "<html>" - "<head><title>Created</title></head>" - "<body><h1>201 Created</h1></body>" - "</html>"; -const char accepted[] = - "<html>" - "<head><title>Accepted</title></head>" - "<body><h1>202 Accepted</h1></body>" - "</html>"; -const char no_content[] = - "<html>" - "<head><title>No Content</title></head>" - "<body><h1>204 Content</h1></body>" - "</html>"; -const char multiple_choices[] = - "<html>" - "<head><title>Multiple Choices</title></head>" - "<body><h1>300 Multiple Choices</h1></body>" - "</html>"; -const char moved_permanently[] = - "<html>" - "<head><title>Moved Permanently</title></head>" - "<body><h1>301 Moved Permanently</h1></body>" - "</html>"; -const char moved_temporarily[] = - "<html>" - "<head><title>Moved Temporarily</title></head>" - "<body><h1>302 Moved Temporarily</h1></body>" - "</html>"; -const char not_modified[] = - "<html>" - "<head><title>Not Modified</title></head>" - "<body><h1>304 Not Modified</h1></body>" - "</html>"; -const char bad_request[] = - "<html>" - "<head><title>Bad Request</title></head>" - "<body><h1>400 Bad Request</h1></body>" - "</html>"; -const char unauthorized[] = - "<html>" - "<head><title>Unauthorized</title></head>" - "<body><h1>401 Unauthorized</h1></body>" - "</html>"; -const char forbidden[] = - "<html>" - "<head><title>Forbidden</title></head>" - "<body><h1>403 Forbidden</h1></body>" - "</html>"; -const char not_found[] = - "<html>" - "<head><title>Not Found</title></head>" - "<body><h1>404 Not Found</h1></body>" - "</html>"; -const char internal_server_error[] = - "<html>" - "<head><title>Internal Server Error</title></head>" - "<body><h1>500 Internal Server Error</h1></body>" - "</html>"; -const char not_implemented[] = - "<html>" - "<head><title>Not Implemented</title></head>" - "<body><h1>501 Not Implemented</h1></body>" - "</html>"; -const char bad_gateway[] = - "<html>" - "<head><title>Bad Gateway</title></head>" - "<body><h1>502 Bad Gateway</h1></body>" - "</html>"; -const char service_unavailable[] = - "<html>" - "<head><title>Service Unavailable</title></head>" - "<body><h1>503 Service Unavailable</h1></body>" - "</html>"; - -std::string to_string(reply::status_type status) -{ - switch (status) - { - case reply::ok: - return ok; - case reply::created: - return created; - case reply::accepted: - return accepted; - case reply::no_content: - return no_content; - case reply::multiple_choices: - return multiple_choices; - case reply::moved_permanently: - return moved_permanently; - case reply::moved_temporarily: - return moved_temporarily; - case reply::not_modified: - return not_modified; - case reply::bad_request: - return bad_request; - case reply::unauthorized: - return unauthorized; - case reply::forbidden: - return forbidden; - case reply::not_found: - return not_found; - case reply::internal_server_error: - return internal_server_error; - case reply::not_implemented: - return not_implemented; - case reply::bad_gateway: - return bad_gateway; - case reply::service_unavailable: - return service_unavailable; - default: - return internal_server_error; - } -} - -} // namespace stock_replies - -reply reply::stock_reply(reply::status_type status) -{ - reply rep; - rep.status = status; - rep.content = stock_replies::to_string(status); - rep.headers.resize(2); - rep.headers[0].name = "Content-Length"; - rep.headers[0].value = boost::lexical_cast<std::string>(rep.content.size()); - rep.headers[1].name = "Content-Type"; - rep.headers[1].value = "text/html"; - return rep; -} - -} // namespace server2 -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server2/reply.hpp b/doc/html/boost_asio/example/cpp03/http/server2/reply.hpp deleted file mode 100644 index acb1534b90..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server2/reply.hpp +++ /dev/null @@ -1,64 +0,0 @@ -// -// reply.hpp -// ~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER2_REPLY_HPP -#define HTTP_SERVER2_REPLY_HPP - -#include <string> -#include <vector> -#include <boost/asio.hpp> -#include "header.hpp" - -namespace http { -namespace server2 { - -/// A reply to be sent to a client. -struct reply -{ - /// The status of the reply. - 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, - internal_server_error = 500, - not_implemented = 501, - bad_gateway = 502, - service_unavailable = 503 - } status; - - /// The headers to be included in the reply. - std::vector<header> headers; - - /// The content to be sent in the reply. - std::string content; - - /// Convert the reply into a vector of buffers. The buffers do not own the - /// underlying memory blocks, therefore the reply object must remain valid and - /// not be changed until the write operation has completed. - std::vector<boost::asio::const_buffer> to_buffers(); - - /// Get a stock reply. - static reply stock_reply(status_type status); -}; - -} // namespace server2 -} // namespace http - -#endif // HTTP_SERVER2_REPLY_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server2/request.hpp b/doc/html/boost_asio/example/cpp03/http/server2/request.hpp deleted file mode 100644 index 9e14fd2acf..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server2/request.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// -// request.hpp -// ~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER2_REQUEST_HPP -#define HTTP_SERVER2_REQUEST_HPP - -#include <string> -#include <vector> -#include "header.hpp" - -namespace http { -namespace server2 { - -/// A request received from a client. -struct request -{ - std::string method; - std::string uri; - int http_version_major; - int http_version_minor; - std::vector<header> headers; -}; - -} // namespace server2 -} // namespace http - -#endif // HTTP_SERVER2_REQUEST_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server2/request_handler.cpp b/doc/html/boost_asio/example/cpp03/http/server2/request_handler.cpp deleted file mode 100644 index 62a638c5a5..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server2/request_handler.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// -// request_handler.cpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "request_handler.hpp" -#include <fstream> -#include <sstream> -#include <string> -#include <boost/lexical_cast.hpp> -#include "mime_types.hpp" -#include "reply.hpp" -#include "request.hpp" - -namespace http { -namespace server2 { - -request_handler::request_handler(const std::string& doc_root) - : doc_root_(doc_root) -{ -} - -void request_handler::handle_request(const request& req, reply& rep) -{ - // Decode url to path. - std::string request_path; - if (!url_decode(req.uri, request_path)) - { - rep = reply::stock_reply(reply::bad_request); - return; - } - - // Request path must be absolute and not contain "..". - if (request_path.empty() || request_path[0] != '/' - || request_path.find("..") != std::string::npos) - { - rep = reply::stock_reply(reply::bad_request); - return; - } - - // If path ends in slash (i.e. is a directory) then add "index.html". - if (request_path[request_path.size() - 1] == '/') - { - request_path += "index.html"; - } - - // Determine the file extension. - std::size_t last_slash_pos = request_path.find_last_of("/"); - std::size_t last_dot_pos = request_path.find_last_of("."); - std::string extension; - if (last_dot_pos != std::string::npos && last_dot_pos > last_slash_pos) - { - extension = request_path.substr(last_dot_pos + 1); - } - - // Open the file to send back. - std::string full_path = doc_root_ + request_path; - std::ifstream is(full_path.c_str(), std::ios::in | std::ios::binary); - if (!is) - { - rep = reply::stock_reply(reply::not_found); - return; - } - - // Fill out the reply to be sent to the client. - rep.status = reply::ok; - char buf[512]; - while (is.read(buf, sizeof(buf)).gcount() > 0) - rep.content.append(buf, is.gcount()); - rep.headers.resize(2); - rep.headers[0].name = "Content-Length"; - rep.headers[0].value = boost::lexical_cast<std::string>(rep.content.size()); - rep.headers[1].name = "Content-Type"; - rep.headers[1].value = mime_types::extension_to_type(extension); -} - -bool request_handler::url_decode(const std::string& in, std::string& out) -{ - out.clear(); - out.reserve(in.size()); - for (std::size_t i = 0; i < in.size(); ++i) - { - if (in[i] == '%') - { - if (i + 3 <= in.size()) - { - int value = 0; - std::istringstream is(in.substr(i + 1, 2)); - if (is >> std::hex >> value) - { - out += static_cast<char>(value); - i += 2; - } - else - { - return false; - } - } - else - { - return false; - } - } - else if (in[i] == '+') - { - out += ' '; - } - else - { - out += in[i]; - } - } - return true; -} - -} // namespace server2 -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server2/request_handler.hpp b/doc/html/boost_asio/example/cpp03/http/server2/request_handler.hpp deleted file mode 100644 index 3addf7bdf5..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server2/request_handler.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// request_handler.hpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER2_REQUEST_HANDLER_HPP -#define HTTP_SERVER2_REQUEST_HANDLER_HPP - -#include <string> -#include <boost/noncopyable.hpp> - -namespace http { -namespace server2 { - -struct reply; -struct request; - -/// The common handler for all incoming requests. -class request_handler - : private boost::noncopyable -{ -public: - /// Construct with a directory containing files to be served. - explicit request_handler(const std::string& doc_root); - - /// Handle a request and produce a reply. - void handle_request(const request& req, reply& rep); - -private: - /// The directory containing the files to be served. - std::string doc_root_; - - /// Perform URL-decoding on a string. Returns false if the encoding was - /// invalid. - static bool url_decode(const std::string& in, std::string& out); -}; - -} // namespace server2 -} // namespace http - -#endif // HTTP_SERVER2_REQUEST_HANDLER_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server2/request_parser.cpp b/doc/html/boost_asio/example/cpp03/http/server2/request_parser.cpp deleted file mode 100644 index d31e5723ca..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server2/request_parser.cpp +++ /dev/null @@ -1,315 +0,0 @@ -// -// request_parser.cpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "request_parser.hpp" -#include "request.hpp" - -namespace http { -namespace server2 { - -request_parser::request_parser() - : state_(method_start) -{ -} - -void request_parser::reset() -{ - state_ = method_start; -} - -boost::tribool request_parser::consume(request& req, char input) -{ - switch (state_) - { - case method_start: - if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return false; - } - else - { - state_ = method; - req.method.push_back(input); - return boost::indeterminate; - } - case method: - if (input == ' ') - { - state_ = uri; - return boost::indeterminate; - } - else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return false; - } - else - { - req.method.push_back(input); - return boost::indeterminate; - } - case uri: - if (input == ' ') - { - state_ = http_version_h; - return boost::indeterminate; - } - else if (is_ctl(input)) - { - return false; - } - else - { - req.uri.push_back(input); - return boost::indeterminate; - } - case http_version_h: - if (input == 'H') - { - state_ = http_version_t_1; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_t_1: - if (input == 'T') - { - state_ = http_version_t_2; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_t_2: - if (input == 'T') - { - state_ = http_version_p; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_p: - if (input == 'P') - { - state_ = http_version_slash; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_slash: - if (input == '/') - { - req.http_version_major = 0; - req.http_version_minor = 0; - state_ = http_version_major_start; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_major_start: - if (is_digit(input)) - { - req.http_version_major = req.http_version_major * 10 + input - '0'; - state_ = http_version_major; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_major: - if (input == '.') - { - state_ = http_version_minor_start; - return boost::indeterminate; - } - else if (is_digit(input)) - { - req.http_version_major = req.http_version_major * 10 + input - '0'; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_minor_start: - if (is_digit(input)) - { - req.http_version_minor = req.http_version_minor * 10 + input - '0'; - state_ = http_version_minor; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_minor: - if (input == '\r') - { - state_ = expecting_newline_1; - return boost::indeterminate; - } - else if (is_digit(input)) - { - req.http_version_minor = req.http_version_minor * 10 + input - '0'; - return boost::indeterminate; - } - else - { - return false; - } - case expecting_newline_1: - if (input == '\n') - { - state_ = header_line_start; - return boost::indeterminate; - } - else - { - return false; - } - case header_line_start: - if (input == '\r') - { - state_ = expecting_newline_3; - return boost::indeterminate; - } - else if (!req.headers.empty() && (input == ' ' || input == '\t')) - { - state_ = header_lws; - return boost::indeterminate; - } - else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return false; - } - else - { - req.headers.push_back(header()); - req.headers.back().name.push_back(input); - state_ = header_name; - return boost::indeterminate; - } - case header_lws: - if (input == '\r') - { - state_ = expecting_newline_2; - return boost::indeterminate; - } - else if (input == ' ' || input == '\t') - { - return boost::indeterminate; - } - else if (is_ctl(input)) - { - return false; - } - else - { - state_ = header_value; - req.headers.back().value.push_back(input); - return boost::indeterminate; - } - case header_name: - if (input == ':') - { - state_ = space_before_header_value; - return boost::indeterminate; - } - else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return false; - } - else - { - req.headers.back().name.push_back(input); - return boost::indeterminate; - } - case space_before_header_value: - if (input == ' ') - { - state_ = header_value; - return boost::indeterminate; - } - else - { - return false; - } - case header_value: - if (input == '\r') - { - state_ = expecting_newline_2; - return boost::indeterminate; - } - else if (is_ctl(input)) - { - return false; - } - else - { - req.headers.back().value.push_back(input); - return boost::indeterminate; - } - case expecting_newline_2: - if (input == '\n') - { - state_ = header_line_start; - return boost::indeterminate; - } - else - { - return false; - } - case expecting_newline_3: - return (input == '\n'); - default: - return false; - } -} - -bool request_parser::is_char(int c) -{ - return c >= 0 && c <= 127; -} - -bool request_parser::is_ctl(int c) -{ - return (c >= 0 && c <= 31) || (c == 127); -} - -bool request_parser::is_tspecial(int c) -{ - switch (c) - { - case '(': case ')': case '<': case '>': case '@': - case ',': case ';': case ':': case '\\': case '"': - case '/': case '[': case ']': case '?': case '=': - case '{': case '}': case ' ': case '\t': - return true; - default: - return false; - } -} - -bool request_parser::is_digit(int c) -{ - return c >= '0' && c <= '9'; -} - -} // namespace server2 -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server2/request_parser.hpp b/doc/html/boost_asio/example/cpp03/http/server2/request_parser.hpp deleted file mode 100644 index 0426326746..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server2/request_parser.hpp +++ /dev/null @@ -1,95 +0,0 @@ -// -// request_parser.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER2_REQUEST_PARSER_HPP -#define HTTP_SERVER2_REQUEST_PARSER_HPP - -#include <boost/logic/tribool.hpp> -#include <boost/tuple/tuple.hpp> - -namespace http { -namespace server2 { - -struct request; - -/// Parser for incoming requests. -class request_parser -{ -public: - /// Construct ready to parse the request method. - request_parser(); - - /// Reset to initial parser state. - void reset(); - - /// Parse some data. The tribool return value is true when a complete request - /// has been parsed, false if the data is invalid, indeterminate when more - /// data is required. The InputIterator return value indicates how much of the - /// input has been consumed. - template <typename InputIterator> - boost::tuple<boost::tribool, InputIterator> parse(request& req, - InputIterator begin, InputIterator end) - { - while (begin != end) - { - boost::tribool result = consume(req, *begin++); - if (result || !result) - return boost::make_tuple(result, begin); - } - boost::tribool result = boost::indeterminate; - return boost::make_tuple(result, begin); - } - -private: - /// Handle the next character of input. - boost::tribool consume(request& req, char input); - - /// Check if a byte is an HTTP character. - static bool is_char(int c); - - /// Check if a byte is an HTTP control character. - static bool is_ctl(int c); - - /// Check if a byte is defined as an HTTP tspecial character. - static bool is_tspecial(int c); - - /// Check if a byte is a digit. - static bool is_digit(int c); - - /// The current state of the parser. - enum state - { - method_start, - method, - uri, - http_version_h, - http_version_t_1, - http_version_t_2, - http_version_p, - http_version_slash, - http_version_major_start, - http_version_major, - http_version_minor_start, - http_version_minor, - expecting_newline_1, - header_line_start, - header_lws, - header_name, - space_before_header_value, - header_value, - expecting_newline_2, - expecting_newline_3 - } state_; -}; - -} // namespace server2 -} // namespace http - -#endif // HTTP_SERVER2_REQUEST_PARSER_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server2/server.cpp b/doc/html/boost_asio/example/cpp03/http/server2/server.cpp deleted file mode 100644 index bacc9218bd..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server2/server.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// -// server.cpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "server.hpp" -#include <boost/bind.hpp> - -namespace http { -namespace server2 { - -server::server(const std::string& address, const std::string& port, - const std::string& doc_root, std::size_t io_service_pool_size) - : io_service_pool_(io_service_pool_size), - signals_(io_service_pool_.get_io_service()), - acceptor_(io_service_pool_.get_io_service()), - new_connection_(), - request_handler_(doc_root) -{ - // Register to handle the signals that indicate when the server should exit. - // It is safe to register for the same signal multiple times in a program, - // provided all registration for the specified signal is made through Asio. - signals_.add(SIGINT); - signals_.add(SIGTERM); -#if defined(SIGQUIT) - signals_.add(SIGQUIT); -#endif // defined(SIGQUIT) - signals_.async_wait(boost::bind(&server::handle_stop, this)); - - // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR). - boost::asio::ip::tcp::resolver resolver(acceptor_.get_io_service()); - boost::asio::ip::tcp::resolver::query query(address, port); - boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query); - acceptor_.open(endpoint.protocol()); - acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); - acceptor_.bind(endpoint); - acceptor_.listen(); - - start_accept(); -} - -void server::run() -{ - io_service_pool_.run(); -} - -void server::start_accept() -{ - new_connection_.reset(new connection( - io_service_pool_.get_io_service(), request_handler_)); - acceptor_.async_accept(new_connection_->socket(), - boost::bind(&server::handle_accept, this, - boost::asio::placeholders::error)); -} - -void server::handle_accept(const boost::system::error_code& e) -{ - if (!e) - { - new_connection_->start(); - } - - start_accept(); -} - -void server::handle_stop() -{ - io_service_pool_.stop(); -} - -} // namespace server2 -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server2/server.hpp b/doc/html/boost_asio/example/cpp03/http/server2/server.hpp deleted file mode 100644 index 3b4a1d95f5..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server2/server.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// server.hpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER2_SERVER_HPP -#define HTTP_SERVER2_SERVER_HPP - -#include <boost/asio.hpp> -#include <string> -#include <vector> -#include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> -#include "connection.hpp" -#include "io_service_pool.hpp" -#include "request_handler.hpp" - -namespace http { -namespace server2 { - -/// The top-level class of the HTTP server. -class server - : private boost::noncopyable -{ -public: - /// Construct the server to listen on the specified TCP address and port, and - /// serve up files from the given directory. - explicit server(const std::string& address, const std::string& port, - const std::string& doc_root, std::size_t io_service_pool_size); - - /// Run the server's io_service loop. - void run(); - -private: - /// Initiate an asynchronous accept operation. - void start_accept(); - - /// Handle completion of an asynchronous accept operation. - void handle_accept(const boost::system::error_code& e); - - /// Handle a request to stop the server. - void handle_stop(); - - /// The pool of io_service objects used to perform asynchronous operations. - io_service_pool io_service_pool_; - - /// The signal_set is used to register for process termination notifications. - boost::asio::signal_set signals_; - - /// Acceptor used to listen for incoming connections. - boost::asio::ip::tcp::acceptor acceptor_; - - /// The next connection to be accepted. - connection_ptr new_connection_; - - /// The handler for all incoming requests. - request_handler request_handler_; -}; - -} // namespace server2 -} // namespace http - -#endif // HTTP_SERVER2_SERVER_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server3/connection.cpp b/doc/html/boost_asio/example/cpp03/http/server3/connection.cpp deleted file mode 100644 index 6ec24d1ed4..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server3/connection.cpp +++ /dev/null @@ -1,98 +0,0 @@ -// -// connection.cpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "connection.hpp" -#include <vector> -#include <boost/bind.hpp> -#include "request_handler.hpp" - -namespace http { -namespace server3 { - -connection::connection(boost::asio::io_service& io_service, - request_handler& handler) - : strand_(io_service), - socket_(io_service), - request_handler_(handler) -{ -} - -boost::asio::ip::tcp::socket& connection::socket() -{ - return socket_; -} - -void connection::start() -{ - socket_.async_read_some(boost::asio::buffer(buffer_), - strand_.wrap( - boost::bind(&connection::handle_read, shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); -} - -void connection::handle_read(const boost::system::error_code& e, - std::size_t bytes_transferred) -{ - if (!e) - { - boost::tribool result; - boost::tie(result, boost::tuples::ignore) = request_parser_.parse( - request_, buffer_.data(), buffer_.data() + bytes_transferred); - - if (result) - { - request_handler_.handle_request(request_, reply_); - boost::asio::async_write(socket_, reply_.to_buffers(), - strand_.wrap( - boost::bind(&connection::handle_write, shared_from_this(), - boost::asio::placeholders::error))); - } - else if (!result) - { - reply_ = reply::stock_reply(reply::bad_request); - boost::asio::async_write(socket_, reply_.to_buffers(), - strand_.wrap( - boost::bind(&connection::handle_write, shared_from_this(), - boost::asio::placeholders::error))); - } - else - { - socket_.async_read_some(boost::asio::buffer(buffer_), - strand_.wrap( - boost::bind(&connection::handle_read, shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); - } - } - - // If an error occurs then no new asynchronous operations are started. This - // means that all shared_ptr references to the connection object will - // disappear and the object will be destroyed automatically after this - // handler returns. The connection class's destructor closes the socket. -} - -void connection::handle_write(const boost::system::error_code& e) -{ - if (!e) - { - // Initiate graceful connection closure. - boost::system::error_code ignored_ec; - socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec); - } - - // No new asynchronous operations are started. This means that all shared_ptr - // references to the connection object will disappear and the object will be - // destroyed automatically after this handler returns. The connection class's - // destructor closes the socket. -} - -} // namespace server3 -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server3/connection.hpp b/doc/html/boost_asio/example/cpp03/http/server3/connection.hpp deleted file mode 100644 index 113852652f..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server3/connection.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// -// connection.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER3_CONNECTION_HPP -#define HTTP_SERVER3_CONNECTION_HPP - -#include <boost/asio.hpp> -#include <boost/array.hpp> -#include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> -#include "reply.hpp" -#include "request.hpp" -#include "request_handler.hpp" -#include "request_parser.hpp" - -namespace http { -namespace server3 { - -/// Represents a single connection from a client. -class connection - : public boost::enable_shared_from_this<connection>, - private boost::noncopyable -{ -public: - /// Construct a connection with the given io_service. - explicit connection(boost::asio::io_service& io_service, - request_handler& handler); - - /// Get the socket associated with the connection. - boost::asio::ip::tcp::socket& socket(); - - /// Start the first asynchronous operation for the connection. - void start(); - -private: - /// Handle completion of a read operation. - void handle_read(const boost::system::error_code& e, - std::size_t bytes_transferred); - - /// Handle completion of a write operation. - void handle_write(const boost::system::error_code& e); - - /// Strand to ensure the connection's handlers are not called concurrently. - boost::asio::io_service::strand strand_; - - /// Socket for the connection. - boost::asio::ip::tcp::socket socket_; - - /// The handler used to process the incoming request. - request_handler& request_handler_; - - /// Buffer for incoming data. - boost::array<char, 8192> buffer_; - - /// The incoming request. - request request_; - - /// The parser for the incoming request. - request_parser request_parser_; - - /// The reply to be sent back to the client. - reply reply_; -}; - -typedef boost::shared_ptr<connection> connection_ptr; - -} // namespace server3 -} // namespace http - -#endif // HTTP_SERVER3_CONNECTION_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server3/header.hpp b/doc/html/boost_asio/example/cpp03/http/server3/header.hpp deleted file mode 100644 index 004efb631b..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server3/header.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// -// header.hpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER3_HEADER_HPP -#define HTTP_SERVER3_HEADER_HPP - -#include <string> - -namespace http { -namespace server3 { - -struct header -{ - std::string name; - std::string value; -}; - -} // namespace server3 -} // namespace http - -#endif // HTTP_SERVER3_HEADER_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server3/main.cpp b/doc/html/boost_asio/example/cpp03/http/server3/main.cpp deleted file mode 100644 index 998b295500..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server3/main.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// main.cpp -// ~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <iostream> -#include <string> -#include <boost/asio.hpp> -#include <boost/bind.hpp> -#include <boost/lexical_cast.hpp> -#include "server.hpp" - -int main(int argc, char* argv[]) -{ - try - { - // Check command line arguments. - if (argc != 5) - { - std::cerr << "Usage: http_server <address> <port> <threads> <doc_root>\n"; - std::cerr << " For IPv4, try:\n"; - std::cerr << " receiver 0.0.0.0 80 1 .\n"; - std::cerr << " For IPv6, try:\n"; - std::cerr << " receiver 0::0 80 1 .\n"; - return 1; - } - - // Initialise the server. - std::size_t num_threads = boost::lexical_cast<std::size_t>(argv[3]); - http::server3::server s(argv[1], argv[2], argv[4], num_threads); - - // Run the server until stopped. - s.run(); - } - catch (std::exception& e) - { - std::cerr << "exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/http/server3/mime_types.cpp b/doc/html/boost_asio/example/cpp03/http/server3/mime_types.cpp deleted file mode 100644 index ee84fb94c6..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server3/mime_types.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// mime_types.cpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "mime_types.hpp" - -namespace http { -namespace server3 { -namespace mime_types { - -struct mapping -{ - const char* extension; - const char* mime_type; -} mappings[] = -{ - { "gif", "image/gif" }, - { "htm", "text/html" }, - { "html", "text/html" }, - { "jpg", "image/jpeg" }, - { "png", "image/png" }, - { 0, 0 } // Marks end of list. -}; - -std::string extension_to_type(const std::string& extension) -{ - for (mapping* m = mappings; m->extension; ++m) - { - if (m->extension == extension) - { - return m->mime_type; - } - } - - return "text/plain"; -} - -} // namespace mime_types -} // namespace server3 -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server3/mime_types.hpp b/doc/html/boost_asio/example/cpp03/http/server3/mime_types.hpp deleted file mode 100644 index 79453121b6..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server3/mime_types.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// -// mime_types.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER3_MIME_TYPES_HPP -#define HTTP_SERVER3_MIME_TYPES_HPP - -#include <string> - -namespace http { -namespace server3 { -namespace mime_types { - -/// Convert a file extension into a MIME type. -std::string extension_to_type(const std::string& extension); - -} // namespace mime_types -} // namespace server3 -} // namespace http - -#endif // HTTP_SERVER3_MIME_TYPES_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server3/reply.cpp b/doc/html/boost_asio/example/cpp03/http/server3/reply.cpp deleted file mode 100644 index 66a67c617b..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server3/reply.cpp +++ /dev/null @@ -1,256 +0,0 @@ -// -// reply.cpp -// ~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "reply.hpp" -#include <string> -#include <boost/lexical_cast.hpp> - -namespace http { -namespace server3 { - -namespace status_strings { - -const std::string ok = - "HTTP/1.0 200 OK\r\n"; -const std::string created = - "HTTP/1.0 201 Created\r\n"; -const std::string accepted = - "HTTP/1.0 202 Accepted\r\n"; -const std::string no_content = - "HTTP/1.0 204 No Content\r\n"; -const std::string multiple_choices = - "HTTP/1.0 300 Multiple Choices\r\n"; -const std::string moved_permanently = - "HTTP/1.0 301 Moved Permanently\r\n"; -const std::string moved_temporarily = - "HTTP/1.0 302 Moved Temporarily\r\n"; -const std::string not_modified = - "HTTP/1.0 304 Not Modified\r\n"; -const std::string bad_request = - "HTTP/1.0 400 Bad Request\r\n"; -const std::string unauthorized = - "HTTP/1.0 401 Unauthorized\r\n"; -const std::string forbidden = - "HTTP/1.0 403 Forbidden\r\n"; -const std::string not_found = - "HTTP/1.0 404 Not Found\r\n"; -const std::string internal_server_error = - "HTTP/1.0 500 Internal Server Error\r\n"; -const std::string not_implemented = - "HTTP/1.0 501 Not Implemented\r\n"; -const std::string bad_gateway = - "HTTP/1.0 502 Bad Gateway\r\n"; -const std::string service_unavailable = - "HTTP/1.0 503 Service Unavailable\r\n"; - -boost::asio::const_buffer to_buffer(reply::status_type status) -{ - switch (status) - { - case reply::ok: - return boost::asio::buffer(ok); - case reply::created: - return boost::asio::buffer(created); - case reply::accepted: - return boost::asio::buffer(accepted); - case reply::no_content: - return boost::asio::buffer(no_content); - case reply::multiple_choices: - return boost::asio::buffer(multiple_choices); - case reply::moved_permanently: - return boost::asio::buffer(moved_permanently); - case reply::moved_temporarily: - return boost::asio::buffer(moved_temporarily); - case reply::not_modified: - return boost::asio::buffer(not_modified); - case reply::bad_request: - return boost::asio::buffer(bad_request); - case reply::unauthorized: - return boost::asio::buffer(unauthorized); - case reply::forbidden: - return boost::asio::buffer(forbidden); - case reply::not_found: - return boost::asio::buffer(not_found); - case reply::internal_server_error: - return boost::asio::buffer(internal_server_error); - case reply::not_implemented: - return boost::asio::buffer(not_implemented); - case reply::bad_gateway: - return boost::asio::buffer(bad_gateway); - case reply::service_unavailable: - return boost::asio::buffer(service_unavailable); - default: - return boost::asio::buffer(internal_server_error); - } -} - -} // namespace status_strings - -namespace misc_strings { - -const char name_value_separator[] = { ':', ' ' }; -const char crlf[] = { '\r', '\n' }; - -} // namespace misc_strings - -std::vector<boost::asio::const_buffer> reply::to_buffers() -{ - std::vector<boost::asio::const_buffer> buffers; - buffers.push_back(status_strings::to_buffer(status)); - for (std::size_t i = 0; i < headers.size(); ++i) - { - header& h = headers[i]; - buffers.push_back(boost::asio::buffer(h.name)); - buffers.push_back(boost::asio::buffer(misc_strings::name_value_separator)); - buffers.push_back(boost::asio::buffer(h.value)); - buffers.push_back(boost::asio::buffer(misc_strings::crlf)); - } - buffers.push_back(boost::asio::buffer(misc_strings::crlf)); - buffers.push_back(boost::asio::buffer(content)); - return buffers; -} - -namespace stock_replies { - -const char ok[] = ""; -const char created[] = - "<html>" - "<head><title>Created</title></head>" - "<body><h1>201 Created</h1></body>" - "</html>"; -const char accepted[] = - "<html>" - "<head><title>Accepted</title></head>" - "<body><h1>202 Accepted</h1></body>" - "</html>"; -const char no_content[] = - "<html>" - "<head><title>No Content</title></head>" - "<body><h1>204 Content</h1></body>" - "</html>"; -const char multiple_choices[] = - "<html>" - "<head><title>Multiple Choices</title></head>" - "<body><h1>300 Multiple Choices</h1></body>" - "</html>"; -const char moved_permanently[] = - "<html>" - "<head><title>Moved Permanently</title></head>" - "<body><h1>301 Moved Permanently</h1></body>" - "</html>"; -const char moved_temporarily[] = - "<html>" - "<head><title>Moved Temporarily</title></head>" - "<body><h1>302 Moved Temporarily</h1></body>" - "</html>"; -const char not_modified[] = - "<html>" - "<head><title>Not Modified</title></head>" - "<body><h1>304 Not Modified</h1></body>" - "</html>"; -const char bad_request[] = - "<html>" - "<head><title>Bad Request</title></head>" - "<body><h1>400 Bad Request</h1></body>" - "</html>"; -const char unauthorized[] = - "<html>" - "<head><title>Unauthorized</title></head>" - "<body><h1>401 Unauthorized</h1></body>" - "</html>"; -const char forbidden[] = - "<html>" - "<head><title>Forbidden</title></head>" - "<body><h1>403 Forbidden</h1></body>" - "</html>"; -const char not_found[] = - "<html>" - "<head><title>Not Found</title></head>" - "<body><h1>404 Not Found</h1></body>" - "</html>"; -const char internal_server_error[] = - "<html>" - "<head><title>Internal Server Error</title></head>" - "<body><h1>500 Internal Server Error</h1></body>" - "</html>"; -const char not_implemented[] = - "<html>" - "<head><title>Not Implemented</title></head>" - "<body><h1>501 Not Implemented</h1></body>" - "</html>"; -const char bad_gateway[] = - "<html>" - "<head><title>Bad Gateway</title></head>" - "<body><h1>502 Bad Gateway</h1></body>" - "</html>"; -const char service_unavailable[] = - "<html>" - "<head><title>Service Unavailable</title></head>" - "<body><h1>503 Service Unavailable</h1></body>" - "</html>"; - -std::string to_string(reply::status_type status) -{ - switch (status) - { - case reply::ok: - return ok; - case reply::created: - return created; - case reply::accepted: - return accepted; - case reply::no_content: - return no_content; - case reply::multiple_choices: - return multiple_choices; - case reply::moved_permanently: - return moved_permanently; - case reply::moved_temporarily: - return moved_temporarily; - case reply::not_modified: - return not_modified; - case reply::bad_request: - return bad_request; - case reply::unauthorized: - return unauthorized; - case reply::forbidden: - return forbidden; - case reply::not_found: - return not_found; - case reply::internal_server_error: - return internal_server_error; - case reply::not_implemented: - return not_implemented; - case reply::bad_gateway: - return bad_gateway; - case reply::service_unavailable: - return service_unavailable; - default: - return internal_server_error; - } -} - -} // namespace stock_replies - -reply reply::stock_reply(reply::status_type status) -{ - reply rep; - rep.status = status; - rep.content = stock_replies::to_string(status); - rep.headers.resize(2); - rep.headers[0].name = "Content-Length"; - rep.headers[0].value = boost::lexical_cast<std::string>(rep.content.size()); - rep.headers[1].name = "Content-Type"; - rep.headers[1].value = "text/html"; - return rep; -} - -} // namespace server3 -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server3/reply.hpp b/doc/html/boost_asio/example/cpp03/http/server3/reply.hpp deleted file mode 100644 index 43ad1688b1..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server3/reply.hpp +++ /dev/null @@ -1,64 +0,0 @@ -// -// reply.hpp -// ~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER3_REPLY_HPP -#define HTTP_SERVER3_REPLY_HPP - -#include <string> -#include <vector> -#include <boost/asio.hpp> -#include "header.hpp" - -namespace http { -namespace server3 { - -/// A reply to be sent to a client. -struct reply -{ - /// The status of the reply. - 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, - internal_server_error = 500, - not_implemented = 501, - bad_gateway = 502, - service_unavailable = 503 - } status; - - /// The headers to be included in the reply. - std::vector<header> headers; - - /// The content to be sent in the reply. - std::string content; - - /// Convert the reply into a vector of buffers. The buffers do not own the - /// underlying memory blocks, therefore the reply object must remain valid and - /// not be changed until the write operation has completed. - std::vector<boost::asio::const_buffer> to_buffers(); - - /// Get a stock reply. - static reply stock_reply(status_type status); -}; - -} // namespace server3 -} // namespace http - -#endif // HTTP_SERVER3_REPLY_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server3/request.hpp b/doc/html/boost_asio/example/cpp03/http/server3/request.hpp deleted file mode 100644 index 8b1eef75d0..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server3/request.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// -// request.hpp -// ~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER3_REQUEST_HPP -#define HTTP_SERVER3_REQUEST_HPP - -#include <string> -#include <vector> -#include "header.hpp" - -namespace http { -namespace server3 { - -/// A request received from a client. -struct request -{ - std::string method; - std::string uri; - int http_version_major; - int http_version_minor; - std::vector<header> headers; -}; - -} // namespace server3 -} // namespace http - -#endif // HTTP_SERVER3_REQUEST_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server3/request_handler.cpp b/doc/html/boost_asio/example/cpp03/http/server3/request_handler.cpp deleted file mode 100644 index ffa4ac971e..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server3/request_handler.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// -// request_handler.cpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "request_handler.hpp" -#include <fstream> -#include <sstream> -#include <string> -#include <boost/lexical_cast.hpp> -#include "mime_types.hpp" -#include "reply.hpp" -#include "request.hpp" - -namespace http { -namespace server3 { - -request_handler::request_handler(const std::string& doc_root) - : doc_root_(doc_root) -{ -} - -void request_handler::handle_request(const request& req, reply& rep) -{ - // Decode url to path. - std::string request_path; - if (!url_decode(req.uri, request_path)) - { - rep = reply::stock_reply(reply::bad_request); - return; - } - - // Request path must be absolute and not contain "..". - if (request_path.empty() || request_path[0] != '/' - || request_path.find("..") != std::string::npos) - { - rep = reply::stock_reply(reply::bad_request); - return; - } - - // If path ends in slash (i.e. is a directory) then add "index.html". - if (request_path[request_path.size() - 1] == '/') - { - request_path += "index.html"; - } - - // Determine the file extension. - std::size_t last_slash_pos = request_path.find_last_of("/"); - std::size_t last_dot_pos = request_path.find_last_of("."); - std::string extension; - if (last_dot_pos != std::string::npos && last_dot_pos > last_slash_pos) - { - extension = request_path.substr(last_dot_pos + 1); - } - - // Open the file to send back. - std::string full_path = doc_root_ + request_path; - std::ifstream is(full_path.c_str(), std::ios::in | std::ios::binary); - if (!is) - { - rep = reply::stock_reply(reply::not_found); - return; - } - - // Fill out the reply to be sent to the client. - rep.status = reply::ok; - char buf[512]; - while (is.read(buf, sizeof(buf)).gcount() > 0) - rep.content.append(buf, is.gcount()); - rep.headers.resize(2); - rep.headers[0].name = "Content-Length"; - rep.headers[0].value = boost::lexical_cast<std::string>(rep.content.size()); - rep.headers[1].name = "Content-Type"; - rep.headers[1].value = mime_types::extension_to_type(extension); -} - -bool request_handler::url_decode(const std::string& in, std::string& out) -{ - out.clear(); - out.reserve(in.size()); - for (std::size_t i = 0; i < in.size(); ++i) - { - if (in[i] == '%') - { - if (i + 3 <= in.size()) - { - int value = 0; - std::istringstream is(in.substr(i + 1, 2)); - if (is >> std::hex >> value) - { - out += static_cast<char>(value); - i += 2; - } - else - { - return false; - } - } - else - { - return false; - } - } - else if (in[i] == '+') - { - out += ' '; - } - else - { - out += in[i]; - } - } - return true; -} - -} // namespace server3 -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server3/request_handler.hpp b/doc/html/boost_asio/example/cpp03/http/server3/request_handler.hpp deleted file mode 100644 index c635a01196..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server3/request_handler.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// request_handler.hpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER3_REQUEST_HANDLER_HPP -#define HTTP_SERVER3_REQUEST_HANDLER_HPP - -#include <string> -#include <boost/noncopyable.hpp> - -namespace http { -namespace server3 { - -struct reply; -struct request; - -/// The common handler for all incoming requests. -class request_handler - : private boost::noncopyable -{ -public: - /// Construct with a directory containing files to be served. - explicit request_handler(const std::string& doc_root); - - /// Handle a request and produce a reply. - void handle_request(const request& req, reply& rep); - -private: - /// The directory containing the files to be served. - std::string doc_root_; - - /// Perform URL-decoding on a string. Returns false if the encoding was - /// invalid. - static bool url_decode(const std::string& in, std::string& out); -}; - -} // namespace server3 -} // namespace http - -#endif // HTTP_SERVER3_REQUEST_HANDLER_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server3/request_parser.cpp b/doc/html/boost_asio/example/cpp03/http/server3/request_parser.cpp deleted file mode 100644 index 8ab2ca9a99..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server3/request_parser.cpp +++ /dev/null @@ -1,315 +0,0 @@ -// -// request_parser.cpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "request_parser.hpp" -#include "request.hpp" - -namespace http { -namespace server3 { - -request_parser::request_parser() - : state_(method_start) -{ -} - -void request_parser::reset() -{ - state_ = method_start; -} - -boost::tribool request_parser::consume(request& req, char input) -{ - switch (state_) - { - case method_start: - if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return false; - } - else - { - state_ = method; - req.method.push_back(input); - return boost::indeterminate; - } - case method: - if (input == ' ') - { - state_ = uri; - return boost::indeterminate; - } - else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return false; - } - else - { - req.method.push_back(input); - return boost::indeterminate; - } - case uri: - if (input == ' ') - { - state_ = http_version_h; - return boost::indeterminate; - } - else if (is_ctl(input)) - { - return false; - } - else - { - req.uri.push_back(input); - return boost::indeterminate; - } - case http_version_h: - if (input == 'H') - { - state_ = http_version_t_1; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_t_1: - if (input == 'T') - { - state_ = http_version_t_2; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_t_2: - if (input == 'T') - { - state_ = http_version_p; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_p: - if (input == 'P') - { - state_ = http_version_slash; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_slash: - if (input == '/') - { - req.http_version_major = 0; - req.http_version_minor = 0; - state_ = http_version_major_start; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_major_start: - if (is_digit(input)) - { - req.http_version_major = req.http_version_major * 10 + input - '0'; - state_ = http_version_major; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_major: - if (input == '.') - { - state_ = http_version_minor_start; - return boost::indeterminate; - } - else if (is_digit(input)) - { - req.http_version_major = req.http_version_major * 10 + input - '0'; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_minor_start: - if (is_digit(input)) - { - req.http_version_minor = req.http_version_minor * 10 + input - '0'; - state_ = http_version_minor; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_minor: - if (input == '\r') - { - state_ = expecting_newline_1; - return boost::indeterminate; - } - else if (is_digit(input)) - { - req.http_version_minor = req.http_version_minor * 10 + input - '0'; - return boost::indeterminate; - } - else - { - return false; - } - case expecting_newline_1: - if (input == '\n') - { - state_ = header_line_start; - return boost::indeterminate; - } - else - { - return false; - } - case header_line_start: - if (input == '\r') - { - state_ = expecting_newline_3; - return boost::indeterminate; - } - else if (!req.headers.empty() && (input == ' ' || input == '\t')) - { - state_ = header_lws; - return boost::indeterminate; - } - else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return false; - } - else - { - req.headers.push_back(header()); - req.headers.back().name.push_back(input); - state_ = header_name; - return boost::indeterminate; - } - case header_lws: - if (input == '\r') - { - state_ = expecting_newline_2; - return boost::indeterminate; - } - else if (input == ' ' || input == '\t') - { - return boost::indeterminate; - } - else if (is_ctl(input)) - { - return false; - } - else - { - state_ = header_value; - req.headers.back().value.push_back(input); - return boost::indeterminate; - } - case header_name: - if (input == ':') - { - state_ = space_before_header_value; - return boost::indeterminate; - } - else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return false; - } - else - { - req.headers.back().name.push_back(input); - return boost::indeterminate; - } - case space_before_header_value: - if (input == ' ') - { - state_ = header_value; - return boost::indeterminate; - } - else - { - return false; - } - case header_value: - if (input == '\r') - { - state_ = expecting_newline_2; - return boost::indeterminate; - } - else if (is_ctl(input)) - { - return false; - } - else - { - req.headers.back().value.push_back(input); - return boost::indeterminate; - } - case expecting_newline_2: - if (input == '\n') - { - state_ = header_line_start; - return boost::indeterminate; - } - else - { - return false; - } - case expecting_newline_3: - return (input == '\n'); - default: - return false; - } -} - -bool request_parser::is_char(int c) -{ - return c >= 0 && c <= 127; -} - -bool request_parser::is_ctl(int c) -{ - return (c >= 0 && c <= 31) || (c == 127); -} - -bool request_parser::is_tspecial(int c) -{ - switch (c) - { - case '(': case ')': case '<': case '>': case '@': - case ',': case ';': case ':': case '\\': case '"': - case '/': case '[': case ']': case '?': case '=': - case '{': case '}': case ' ': case '\t': - return true; - default: - return false; - } -} - -bool request_parser::is_digit(int c) -{ - return c >= '0' && c <= '9'; -} - -} // namespace server3 -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server3/request_parser.hpp b/doc/html/boost_asio/example/cpp03/http/server3/request_parser.hpp deleted file mode 100644 index 0795b27bdc..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server3/request_parser.hpp +++ /dev/null @@ -1,95 +0,0 @@ -// -// request_parser.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER3_REQUEST_PARSER_HPP -#define HTTP_SERVER3_REQUEST_PARSER_HPP - -#include <boost/logic/tribool.hpp> -#include <boost/tuple/tuple.hpp> - -namespace http { -namespace server3 { - -struct request; - -/// Parser for incoming requests. -class request_parser -{ -public: - /// Construct ready to parse the request method. - request_parser(); - - /// Reset to initial parser state. - void reset(); - - /// Parse some data. The tribool return value is true when a complete request - /// has been parsed, false if the data is invalid, indeterminate when more - /// data is required. The InputIterator return value indicates how much of the - /// input has been consumed. - template <typename InputIterator> - boost::tuple<boost::tribool, InputIterator> parse(request& req, - InputIterator begin, InputIterator end) - { - while (begin != end) - { - boost::tribool result = consume(req, *begin++); - if (result || !result) - return boost::make_tuple(result, begin); - } - boost::tribool result = boost::indeterminate; - return boost::make_tuple(result, begin); - } - -private: - /// Handle the next character of input. - boost::tribool consume(request& req, char input); - - /// Check if a byte is an HTTP character. - static bool is_char(int c); - - /// Check if a byte is an HTTP control character. - static bool is_ctl(int c); - - /// Check if a byte is defined as an HTTP tspecial character. - static bool is_tspecial(int c); - - /// Check if a byte is a digit. - static bool is_digit(int c); - - /// The current state of the parser. - enum state - { - method_start, - method, - uri, - http_version_h, - http_version_t_1, - http_version_t_2, - http_version_p, - http_version_slash, - http_version_major_start, - http_version_major, - http_version_minor_start, - http_version_minor, - expecting_newline_1, - header_line_start, - header_lws, - header_name, - space_before_header_value, - header_value, - expecting_newline_2, - expecting_newline_3 - } state_; -}; - -} // namespace server3 -} // namespace http - -#endif // HTTP_SERVER3_REQUEST_PARSER_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server3/server.cpp b/doc/html/boost_asio/example/cpp03/http/server3/server.cpp deleted file mode 100644 index 09d8e27bd1..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server3/server.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// -// server.cpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "server.hpp" -#include <boost/thread/thread.hpp> -#include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> -#include <vector> - -namespace http { -namespace server3 { - -server::server(const std::string& address, const std::string& port, - const std::string& doc_root, std::size_t thread_pool_size) - : thread_pool_size_(thread_pool_size), - signals_(io_service_), - acceptor_(io_service_), - new_connection_(), - request_handler_(doc_root) -{ - // Register to handle the signals that indicate when the server should exit. - // It is safe to register for the same signal multiple times in a program, - // provided all registration for the specified signal is made through Asio. - signals_.add(SIGINT); - signals_.add(SIGTERM); -#if defined(SIGQUIT) - signals_.add(SIGQUIT); -#endif // defined(SIGQUIT) - signals_.async_wait(boost::bind(&server::handle_stop, this)); - - // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR). - boost::asio::ip::tcp::resolver resolver(io_service_); - boost::asio::ip::tcp::resolver::query query(address, port); - boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query); - acceptor_.open(endpoint.protocol()); - acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); - acceptor_.bind(endpoint); - acceptor_.listen(); - - start_accept(); -} - -void server::run() -{ - // Create a pool of threads to run all of the io_services. - std::vector<boost::shared_ptr<boost::thread> > threads; - for (std::size_t i = 0; i < thread_pool_size_; ++i) - { - boost::shared_ptr<boost::thread> thread(new boost::thread( - boost::bind(&boost::asio::io_service::run, &io_service_))); - threads.push_back(thread); - } - - // Wait for all threads in the pool to exit. - for (std::size_t i = 0; i < threads.size(); ++i) - threads[i]->join(); -} - -void server::start_accept() -{ - new_connection_.reset(new connection(io_service_, request_handler_)); - acceptor_.async_accept(new_connection_->socket(), - boost::bind(&server::handle_accept, this, - boost::asio::placeholders::error)); -} - -void server::handle_accept(const boost::system::error_code& e) -{ - if (!e) - { - new_connection_->start(); - } - - start_accept(); -} - -void server::handle_stop() -{ - io_service_.stop(); -} - -} // namespace server3 -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server3/server.hpp b/doc/html/boost_asio/example/cpp03/http/server3/server.hpp deleted file mode 100644 index 333efd1c3a..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server3/server.hpp +++ /dev/null @@ -1,70 +0,0 @@ -// -// server.hpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER3_SERVER_HPP -#define HTTP_SERVER3_SERVER_HPP - -#include <boost/asio.hpp> -#include <string> -#include <vector> -#include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> -#include "connection.hpp" -#include "request_handler.hpp" - -namespace http { -namespace server3 { - -/// The top-level class of the HTTP server. -class server - : private boost::noncopyable -{ -public: - /// Construct the server to listen on the specified TCP address and port, and - /// serve up files from the given directory. - explicit server(const std::string& address, const std::string& port, - const std::string& doc_root, std::size_t thread_pool_size); - - /// Run the server's io_service loop. - void run(); - -private: - /// Initiate an asynchronous accept operation. - void start_accept(); - - /// Handle completion of an asynchronous accept operation. - void handle_accept(const boost::system::error_code& e); - - /// Handle a request to stop the server. - void handle_stop(); - - /// The number of threads that will call io_service::run(). - std::size_t thread_pool_size_; - - /// The io_service used to perform asynchronous operations. - boost::asio::io_service io_service_; - - /// The signal_set is used to register for process termination notifications. - boost::asio::signal_set signals_; - - /// Acceptor used to listen for incoming connections. - boost::asio::ip::tcp::acceptor acceptor_; - - /// The next connection to be accepted. - connection_ptr new_connection_; - - /// The handler for all incoming requests. - request_handler request_handler_; -}; - -} // namespace server3 -} // namespace http - -#endif // HTTP_SERVER3_SERVER_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server4/file_handler.cpp b/doc/html/boost_asio/example/cpp03/http/server4/file_handler.cpp deleted file mode 100644 index ece057e4f0..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server4/file_handler.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// -// file_handler.cpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "file_handler.hpp" -#include <fstream> -#include <sstream> -#include <string> -#include <boost/lexical_cast.hpp> -#include "mime_types.hpp" -#include "reply.hpp" -#include "request.hpp" - -namespace http { -namespace server4 { - -file_handler::file_handler(const std::string& doc_root) - : doc_root_(doc_root) -{ -} - -void file_handler::operator()(const request& req, reply& rep) -{ - // Decode url to path. - std::string request_path; - if (!url_decode(req.uri, request_path)) - { - rep = reply::stock_reply(reply::bad_request); - return; - } - - // Request path must be absolute and not contain "..". - if (request_path.empty() || request_path[0] != '/' - || request_path.find("..") != std::string::npos) - { - rep = reply::stock_reply(reply::bad_request); - return; - } - - // If path ends in slash (i.e. is a directory) then add "index.html". - if (request_path[request_path.size() - 1] == '/') - { - request_path += "index.html"; - } - - // Determine the file extension. - std::size_t last_slash_pos = request_path.find_last_of("/"); - std::size_t last_dot_pos = request_path.find_last_of("."); - std::string extension; - if (last_dot_pos != std::string::npos && last_dot_pos > last_slash_pos) - { - extension = request_path.substr(last_dot_pos + 1); - } - - // Open the file to send back. - std::string full_path = doc_root_ + request_path; - std::ifstream is(full_path.c_str(), std::ios::in | std::ios::binary); - if (!is) - { - rep = reply::stock_reply(reply::not_found); - return; - } - - // Fill out the reply to be sent to the client. - rep.status = reply::ok; - char buf[512]; - while (is.read(buf, sizeof(buf)).gcount() > 0) - rep.content.append(buf, is.gcount()); - rep.headers.resize(2); - rep.headers[0].name = "Content-Length"; - rep.headers[0].value = boost::lexical_cast<std::string>(rep.content.size()); - rep.headers[1].name = "Content-Type"; - rep.headers[1].value = mime_types::extension_to_type(extension); -} - -bool file_handler::url_decode(const std::string& in, std::string& out) -{ - out.clear(); - out.reserve(in.size()); - for (std::size_t i = 0; i < in.size(); ++i) - { - if (in[i] == '%') - { - if (i + 3 <= in.size()) - { - int value = 0; - std::istringstream is(in.substr(i + 1, 2)); - if (is >> std::hex >> value) - { - out += static_cast<char>(value); - i += 2; - } - else - { - return false; - } - } - else - { - return false; - } - } - else if (in[i] == '+') - { - out += ' '; - } - else - { - out += in[i]; - } - } - return true; -} - -} // namespace server4 -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server4/file_handler.hpp b/doc/html/boost_asio/example/cpp03/http/server4/file_handler.hpp deleted file mode 100644 index c4f3da21b6..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server4/file_handler.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// -// file_handler.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER4_FILE_HANDLER_HPP -#define HTTP_SERVER4_FILE_HANDLER_HPP - -#include <string> - -namespace http { -namespace server4 { - -struct reply; -struct request; - -/// The common handler for all incoming requests. -class file_handler -{ -public: - /// Construct with a directory containing files to be served. - explicit file_handler(const std::string& doc_root); - - /// Handle a request and produce a reply. - void operator()(const request& req, reply& rep); - -private: - /// The directory containing the files to be served. - std::string doc_root_; - - /// Perform URL-decoding on a string. Returns false if the encoding was - /// invalid. - static bool url_decode(const std::string& in, std::string& out); -}; - -} // namespace server4 -} // namespace http - -#endif // HTTP_SERVER4_FILE_HANDLER_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server4/header.hpp b/doc/html/boost_asio/example/cpp03/http/server4/header.hpp deleted file mode 100644 index acf62906ff..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server4/header.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// -// header.hpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER4_HEADER_HPP -#define HTTP_SERVER4_HEADER_HPP - -#include <string> - -namespace http { -namespace server4 { - -struct header -{ - std::string name; - std::string value; -}; - -} // namespace server4 -} // namespace http - -#endif // HTTP_SERVER4_HEADER_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server4/main.cpp b/doc/html/boost_asio/example/cpp03/http/server4/main.cpp deleted file mode 100644 index 11c54ef227..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server4/main.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// -// main.cpp -// ~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <iostream> -#include <boost/asio.hpp> -#include <boost/bind.hpp> -#include <signal.h> -#include "server.hpp" -#include "file_handler.hpp" - -int main(int argc, char* argv[]) -{ - try - { - // Check command line arguments. - if (argc != 4) - { - std::cerr << "Usage: http_server <address> <port> <doc_root>\n"; - std::cerr << " For IPv4, try:\n"; - std::cerr << " receiver 0.0.0.0 80 .\n"; - std::cerr << " For IPv6, try:\n"; - std::cerr << " receiver 0::0 80 .\n"; - return 1; - } - - boost::asio::io_service io_service; - - // Launch the initial server coroutine. - http::server4::server(io_service, argv[1], argv[2], - http::server4::file_handler(argv[3]))(); - - // Wait for signals indicating time to shut down. - boost::asio::signal_set signals(io_service); - signals.add(SIGINT); - signals.add(SIGTERM); -#if defined(SIGQUIT) - signals.add(SIGQUIT); -#endif // defined(SIGQUIT) - signals.async_wait(boost::bind( - &boost::asio::io_service::stop, &io_service)); - - // Run the server. - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/http/server4/mime_types.cpp b/doc/html/boost_asio/example/cpp03/http/server4/mime_types.cpp deleted file mode 100644 index 85b9ec519a..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server4/mime_types.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// mime_types.cpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "mime_types.hpp" - -namespace http { -namespace server4 { -namespace mime_types { - -struct mapping -{ - const char* extension; - const char* mime_type; -} mappings[] = -{ - { "gif", "image/gif" }, - { "htm", "text/html" }, - { "html", "text/html" }, - { "jpg", "image/jpeg" }, - { "png", "image/png" }, - { 0, 0 } // Marks end of list. -}; - -std::string extension_to_type(const std::string& extension) -{ - for (mapping* m = mappings; m->extension; ++m) - { - if (m->extension == extension) - { - return m->mime_type; - } - } - - return "text/plain"; -} - -} // namespace mime_types -} // namespace server4 -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server4/mime_types.hpp b/doc/html/boost_asio/example/cpp03/http/server4/mime_types.hpp deleted file mode 100644 index b2c3b08b7c..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server4/mime_types.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// -// mime_types.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER4_MIME_TYPES_HPP -#define HTTP_SERVER4_MIME_TYPES_HPP - -#include <string> - -namespace http { -namespace server4 { -namespace mime_types { - -/// Convert a file extension into a MIME type. -std::string extension_to_type(const std::string& extension); - -} // namespace mime_types -} // namespace server4 -} // namespace http - -#endif // HTTP_SERVER4_MIME_TYPES_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server4/reply.cpp b/doc/html/boost_asio/example/cpp03/http/server4/reply.cpp deleted file mode 100644 index f976b28100..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server4/reply.cpp +++ /dev/null @@ -1,256 +0,0 @@ -// -// reply.cpp -// ~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "reply.hpp" -#include <string> -#include <boost/lexical_cast.hpp> - -namespace http { -namespace server4 { - -namespace status_strings { - -const std::string ok = - "HTTP/1.0 200 OK\r\n"; -const std::string created = - "HTTP/1.0 201 Created\r\n"; -const std::string accepted = - "HTTP/1.0 202 Accepted\r\n"; -const std::string no_content = - "HTTP/1.0 204 No Content\r\n"; -const std::string multiple_choices = - "HTTP/1.0 300 Multiple Choices\r\n"; -const std::string moved_permanently = - "HTTP/1.0 301 Moved Permanently\r\n"; -const std::string moved_temporarily = - "HTTP/1.0 302 Moved Temporarily\r\n"; -const std::string not_modified = - "HTTP/1.0 304 Not Modified\r\n"; -const std::string bad_request = - "HTTP/1.0 400 Bad Request\r\n"; -const std::string unauthorized = - "HTTP/1.0 401 Unauthorized\r\n"; -const std::string forbidden = - "HTTP/1.0 403 Forbidden\r\n"; -const std::string not_found = - "HTTP/1.0 404 Not Found\r\n"; -const std::string internal_server_error = - "HTTP/1.0 500 Internal Server Error\r\n"; -const std::string not_implemented = - "HTTP/1.0 501 Not Implemented\r\n"; -const std::string bad_gateway = - "HTTP/1.0 502 Bad Gateway\r\n"; -const std::string service_unavailable = - "HTTP/1.0 503 Service Unavailable\r\n"; - -boost::asio::const_buffer to_buffer(reply::status_type status) -{ - switch (status) - { - case reply::ok: - return boost::asio::buffer(ok); - case reply::created: - return boost::asio::buffer(created); - case reply::accepted: - return boost::asio::buffer(accepted); - case reply::no_content: - return boost::asio::buffer(no_content); - case reply::multiple_choices: - return boost::asio::buffer(multiple_choices); - case reply::moved_permanently: - return boost::asio::buffer(moved_permanently); - case reply::moved_temporarily: - return boost::asio::buffer(moved_temporarily); - case reply::not_modified: - return boost::asio::buffer(not_modified); - case reply::bad_request: - return boost::asio::buffer(bad_request); - case reply::unauthorized: - return boost::asio::buffer(unauthorized); - case reply::forbidden: - return boost::asio::buffer(forbidden); - case reply::not_found: - return boost::asio::buffer(not_found); - case reply::internal_server_error: - return boost::asio::buffer(internal_server_error); - case reply::not_implemented: - return boost::asio::buffer(not_implemented); - case reply::bad_gateway: - return boost::asio::buffer(bad_gateway); - case reply::service_unavailable: - return boost::asio::buffer(service_unavailable); - default: - return boost::asio::buffer(internal_server_error); - } -} - -} // namespace status_strings - -namespace misc_strings { - -const char name_value_separator[] = { ':', ' ' }; -const char crlf[] = { '\r', '\n' }; - -} // namespace misc_strings - -std::vector<boost::asio::const_buffer> reply::to_buffers() -{ - std::vector<boost::asio::const_buffer> buffers; - buffers.push_back(status_strings::to_buffer(status)); - for (std::size_t i = 0; i < headers.size(); ++i) - { - header& h = headers[i]; - buffers.push_back(boost::asio::buffer(h.name)); - buffers.push_back(boost::asio::buffer(misc_strings::name_value_separator)); - buffers.push_back(boost::asio::buffer(h.value)); - buffers.push_back(boost::asio::buffer(misc_strings::crlf)); - } - buffers.push_back(boost::asio::buffer(misc_strings::crlf)); - buffers.push_back(boost::asio::buffer(content)); - return buffers; -} - -namespace stock_replies { - -const char ok[] = ""; -const char created[] = - "<html>" - "<head><title>Created</title></head>" - "<body><h1>201 Created</h1></body>" - "</html>"; -const char accepted[] = - "<html>" - "<head><title>Accepted</title></head>" - "<body><h1>202 Accepted</h1></body>" - "</html>"; -const char no_content[] = - "<html>" - "<head><title>No Content</title></head>" - "<body><h1>204 Content</h1></body>" - "</html>"; -const char multiple_choices[] = - "<html>" - "<head><title>Multiple Choices</title></head>" - "<body><h1>300 Multiple Choices</h1></body>" - "</html>"; -const char moved_permanently[] = - "<html>" - "<head><title>Moved Permanently</title></head>" - "<body><h1>301 Moved Permanently</h1></body>" - "</html>"; -const char moved_temporarily[] = - "<html>" - "<head><title>Moved Temporarily</title></head>" - "<body><h1>302 Moved Temporarily</h1></body>" - "</html>"; -const char not_modified[] = - "<html>" - "<head><title>Not Modified</title></head>" - "<body><h1>304 Not Modified</h1></body>" - "</html>"; -const char bad_request[] = - "<html>" - "<head><title>Bad Request</title></head>" - "<body><h1>400 Bad Request</h1></body>" - "</html>"; -const char unauthorized[] = - "<html>" - "<head><title>Unauthorized</title></head>" - "<body><h1>401 Unauthorized</h1></body>" - "</html>"; -const char forbidden[] = - "<html>" - "<head><title>Forbidden</title></head>" - "<body><h1>403 Forbidden</h1></body>" - "</html>"; -const char not_found[] = - "<html>" - "<head><title>Not Found</title></head>" - "<body><h1>404 Not Found</h1></body>" - "</html>"; -const char internal_server_error[] = - "<html>" - "<head><title>Internal Server Error</title></head>" - "<body><h1>500 Internal Server Error</h1></body>" - "</html>"; -const char not_implemented[] = - "<html>" - "<head><title>Not Implemented</title></head>" - "<body><h1>501 Not Implemented</h1></body>" - "</html>"; -const char bad_gateway[] = - "<html>" - "<head><title>Bad Gateway</title></head>" - "<body><h1>502 Bad Gateway</h1></body>" - "</html>"; -const char service_unavailable[] = - "<html>" - "<head><title>Service Unavailable</title></head>" - "<body><h1>503 Service Unavailable</h1></body>" - "</html>"; - -std::string to_string(reply::status_type status) -{ - switch (status) - { - case reply::ok: - return ok; - case reply::created: - return created; - case reply::accepted: - return accepted; - case reply::no_content: - return no_content; - case reply::multiple_choices: - return multiple_choices; - case reply::moved_permanently: - return moved_permanently; - case reply::moved_temporarily: - return moved_temporarily; - case reply::not_modified: - return not_modified; - case reply::bad_request: - return bad_request; - case reply::unauthorized: - return unauthorized; - case reply::forbidden: - return forbidden; - case reply::not_found: - return not_found; - case reply::internal_server_error: - return internal_server_error; - case reply::not_implemented: - return not_implemented; - case reply::bad_gateway: - return bad_gateway; - case reply::service_unavailable: - return service_unavailable; - default: - return internal_server_error; - } -} - -} // namespace stock_replies - -reply reply::stock_reply(reply::status_type status) -{ - reply rep; - rep.status = status; - rep.content = stock_replies::to_string(status); - rep.headers.resize(2); - rep.headers[0].name = "Content-Length"; - rep.headers[0].value = boost::lexical_cast<std::string>(rep.content.size()); - rep.headers[1].name = "Content-Type"; - rep.headers[1].value = "text/html"; - return rep; -} - -} // namespace server4 -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server4/reply.hpp b/doc/html/boost_asio/example/cpp03/http/server4/reply.hpp deleted file mode 100644 index 4cca2a45fc..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server4/reply.hpp +++ /dev/null @@ -1,64 +0,0 @@ -// -// reply.hpp -// ~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER4_REPLY_HPP -#define HTTP_SERVER4_REPLY_HPP - -#include <string> -#include <vector> -#include <boost/asio.hpp> -#include "header.hpp" - -namespace http { -namespace server4 { - -/// A reply to be sent to a client. -struct reply -{ - /// The status of the reply. - 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, - internal_server_error = 500, - not_implemented = 501, - bad_gateway = 502, - service_unavailable = 503 - } status; - - /// The headers to be included in the reply. - std::vector<header> headers; - - /// The content to be sent in the reply. - std::string content; - - /// Convert the reply into a vector of buffers. The buffers do not own the - /// underlying memory blocks, therefore the reply object must remain valid and - /// not be changed until the write operation has completed. - std::vector<boost::asio::const_buffer> to_buffers(); - - /// Get a stock reply. - static reply stock_reply(status_type status); -}; - -} // namespace server4 -} // namespace http - -#endif // HTTP_SERVER4_REPLY_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server4/request.hpp b/doc/html/boost_asio/example/cpp03/http/server4/request.hpp deleted file mode 100644 index bf4ffe10dd..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server4/request.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// request.hpp -// ~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER4_REQUEST_HPP -#define HTTP_SERVER4_REQUEST_HPP - -#include <string> -#include <vector> -#include "header.hpp" - -namespace http { -namespace server4 { - -/// A request received from a client. -struct request -{ - /// The request method, e.g. "GET", "POST". - std::string method; - - /// The requested URI, such as a path to a file. - std::string uri; - - /// Major version number, usually 1. - int http_version_major; - - /// Minor version number, usually 0 or 1. - int http_version_minor; - - /// The headers included with the request. - std::vector<header> headers; - - /// The optional content sent with the request. - std::string content; -}; - -} // namespace server4 -} // namespace http - -#endif // HTTP_SERVER4_REQUEST_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server4/request_parser.cpp b/doc/html/boost_asio/example/cpp03/http/server4/request_parser.cpp deleted file mode 100644 index 50a35d50b2..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server4/request_parser.cpp +++ /dev/null @@ -1,226 +0,0 @@ -// -// request_parser.cpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "request_parser.hpp" -#include <algorithm> -#include <cctype> -#include <boost/lexical_cast.hpp> -#include "request.hpp" - -namespace http { -namespace server4 { - -// Enable the pseudo-keywords reenter, yield and fork. -#include <boost/asio/yield.hpp> - -std::string request_parser::content_length_name_ = "Content-Length"; - -boost::tribool request_parser::consume(request& req, char c) -{ - reenter (this) - { - req.method.clear(); - req.uri.clear(); - req.http_version_major = 0; - req.http_version_minor = 0; - req.headers.clear(); - req.content.clear(); - content_length_ = 0; - - // Request method. - while (is_char(c) && !is_ctl(c) && !is_tspecial(c) && c != ' ') - { - req.method.push_back(c); - yield return boost::indeterminate; - } - if (req.method.empty()) - return false; - - // Space. - if (c != ' ') return false; - yield return boost::indeterminate; - - // URI. - while (!is_ctl(c) && c != ' ') - { - req.uri.push_back(c); - yield return boost::indeterminate; - } - if (req.uri.empty()) return false; - - // Space. - if (c != ' ') return false; - yield return boost::indeterminate; - - // HTTP protocol identifier. - if (c != 'H') return false; - yield return boost::indeterminate; - if (c != 'T') return false; - yield return boost::indeterminate; - if (c != 'T') return false; - yield return boost::indeterminate; - if (c != 'P') return false; - yield return boost::indeterminate; - - // Slash. - if (c != '/') return false; - yield return boost::indeterminate; - - // Major version number. - if (!is_digit(c)) return false; - while (is_digit(c)) - { - req.http_version_major = req.http_version_major * 10 + c - '0'; - yield return boost::indeterminate; - } - - // Dot. - if (c != '.') return false; - yield return boost::indeterminate; - - // Minor version number. - if (!is_digit(c)) return false; - while (is_digit(c)) - { - req.http_version_minor = req.http_version_minor * 10 + c - '0'; - yield return boost::indeterminate; - } - - // CRLF. - if (c != '\r') return false; - yield return boost::indeterminate; - if (c != '\n') return false; - yield return boost::indeterminate; - - // Headers. - while ((is_char(c) && !is_ctl(c) && !is_tspecial(c) && c != '\r') - || (c == ' ' || c == '\t')) - { - if (c == ' ' || c == '\t') - { - // Leading whitespace. Must be continuation of previous header's value. - if (req.headers.empty()) return false; - while (c == ' ' || c == '\t') - yield return boost::indeterminate; - } - else - { - // Start the next header. - req.headers.push_back(header()); - - // Header name. - while (is_char(c) && !is_ctl(c) && !is_tspecial(c) && c != ':') - { - req.headers.back().name.push_back(c); - yield return boost::indeterminate; - } - - // Colon and space separates the header name from the header value. - if (c != ':') return false; - yield return boost::indeterminate; - if (c != ' ') return false; - yield return boost::indeterminate; - } - - // Header value. - while (is_char(c) && !is_ctl(c) && c != '\r') - { - req.headers.back().value.push_back(c); - yield return boost::indeterminate; - } - - // CRLF. - if (c != '\r') return false; - yield return boost::indeterminate; - if (c != '\n') return false; - yield return boost::indeterminate; - } - - // CRLF. - if (c != '\r') return false; - yield return boost::indeterminate; - if (c != '\n') return false; - - // Check for optional Content-Length header. - for (std::size_t i = 0; i < req.headers.size(); ++i) - { - if (headers_equal(req.headers[i].name, content_length_name_)) - { - try - { - content_length_ = - boost::lexical_cast<std::size_t>(req.headers[i].value); - } - catch (boost::bad_lexical_cast&) - { - return false; - } - } - } - - // Content. - while (req.content.size() < content_length_) - { - yield return boost::indeterminate; - req.content.push_back(c); - } - } - - return true; -} - -// Disable the pseudo-keywords reenter, yield and fork. -#include <boost/asio/unyield.hpp> - -bool request_parser::is_char(int c) -{ - return c >= 0 && c <= 127; -} - -bool request_parser::is_ctl(int c) -{ - return (c >= 0 && c <= 31) || (c == 127); -} - -bool request_parser::is_tspecial(int c) -{ - switch (c) - { - case '(': case ')': case '<': case '>': case '@': - case ',': case ';': case ':': case '\\': case '"': - case '/': case '[': case ']': case '?': case '=': - case '{': case '}': case ' ': case '\t': - return true; - default: - return false; - } -} - -bool request_parser::is_digit(int c) -{ - return c >= '0' && c <= '9'; -} - -bool request_parser::tolower_compare(char a, char b) -{ - return std::tolower(a) == std::tolower(b); -} - -bool request_parser::headers_equal(const std::string& a, const std::string& b) -{ - if (a.length() != b.length()) - return false; - - return std::equal(a.begin(), a.end(), b.begin(), - &request_parser::tolower_compare); -} - -} // namespace server4 -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server4/request_parser.hpp b/doc/html/boost_asio/example/cpp03/http/server4/request_parser.hpp deleted file mode 100644 index 981b3ad11e..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server4/request_parser.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// -// request_parser.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER4_REQUEST_PARSER_HPP -#define HTTP_SERVER4_REQUEST_PARSER_HPP - -#include <string> -#include <boost/logic/tribool.hpp> -#include <boost/tuple/tuple.hpp> -#include <boost/asio/coroutine.hpp> - -namespace http { -namespace server4 { - -struct request; - -/// Parser for incoming requests. -class request_parser : boost::asio::coroutine -{ -public: - /// Parse some data. The tribool return value is true when a complete request - /// has been parsed, false if the data is invalid, indeterminate when more - /// data is required. The InputIterator return value indicates how much of the - /// input has been consumed. - template <typename InputIterator> - boost::tuple<boost::tribool, InputIterator> parse(request& req, - InputIterator begin, InputIterator end) - { - while (begin != end) - { - boost::tribool result = consume(req, *begin++); - if (result || !result) - return boost::make_tuple(result, begin); - } - boost::tribool result = boost::indeterminate; - return boost::make_tuple(result, begin); - } - -private: - /// The name of the content length header. - static std::string content_length_name_; - - /// Content length as decoded from headers. Defaults to 0. - std::size_t content_length_; - - /// Handle the next character of input. - boost::tribool consume(request& req, char input); - - /// Check if a byte is an HTTP character. - static bool is_char(int c); - - /// Check if a byte is an HTTP control character. - static bool is_ctl(int c); - - /// Check if a byte is defined as an HTTP tspecial character. - static bool is_tspecial(int c); - - /// Check if a byte is a digit. - static bool is_digit(int c); - - /// Check if two characters are equal, without regard to case. - static bool tolower_compare(char a, char b); - - /// Check whether the two request header names match. - bool headers_equal(const std::string& a, const std::string& b); -}; - -} // namespace server4 -} // namespace http - -#endif // HTTP_SERVER4_REQUEST_PARSER_HPP diff --git a/doc/html/boost_asio/example/cpp03/http/server4/server.cpp b/doc/html/boost_asio/example/cpp03/http/server4/server.cpp deleted file mode 100644 index 3006a32ca9..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server4/server.cpp +++ /dev/null @@ -1,121 +0,0 @@ -// -// server.cpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "server.hpp" -#include "request.hpp" -#include "reply.hpp" - -namespace http { -namespace server4 { - -server::server(boost::asio::io_service& io_service, - const std::string& address, const std::string& port, - boost::function<void(const request&, reply&)> request_handler) - : request_handler_(request_handler) -{ - tcp::resolver resolver(io_service); - tcp::resolver::query query(address, port); - acceptor_.reset(new tcp::acceptor(io_service, *resolver.resolve(query))); -} - -// Enable the pseudo-keywords reenter, yield and fork. -#include <boost/asio/yield.hpp> - -void server::operator()(boost::system::error_code ec, std::size_t length) -{ - // In this example we keep the error handling code in one place by - // hoisting it outside the coroutine. An alternative approach would be to - // check the value of ec after each yield for an asynchronous operation. - if (!ec) - { - // On reentering a coroutine, control jumps to the location of the last - // yield or fork. The argument to the "reenter" pseudo-keyword can be a - // pointer or reference to an object of type coroutine. - reenter (this) - { - // Loop to accept incoming connections. - do - { - // Create a new socket for the next incoming connection. - socket_.reset(new tcp::socket(acceptor_->get_io_service())); - - // Accept a new connection. The "yield" pseudo-keyword saves the current - // line number and exits the coroutine's "reenter" block. We use the - // server coroutine as the completion handler for the async_accept - // operation. When the asynchronous operation completes, the io_service - // invokes the function call operator, we "reenter" the coroutine, and - // then control resumes at the following line. - yield acceptor_->async_accept(*socket_, *this); - - // We "fork" by cloning a new server coroutine to handle the connection. - // After forking we have a parent coroutine and a child coroutine. Both - // parent and child continue execution at the following line. They can - // be distinguished using the functions coroutine::is_parent() and - // coroutine::is_child(). - fork server(*this)(); - - // The parent continues looping to accept the next incoming connection. - // The child exits the loop and processes the connection. - } while (is_parent()); - - // Create the objects needed to receive a request on the connection. - buffer_.reset(new boost::array<char, 8192>); - request_.reset(new request); - - // Loop until a complete request (or an invalid one) has been received. - do - { - // Receive some more data. When control resumes at the following line, - // the ec and length parameters reflect the result of the asynchronous - // operation. - yield socket_->async_read_some(boost::asio::buffer(*buffer_), *this); - - // Parse the data we just received. - boost::tie(valid_request_, boost::tuples::ignore) - = request_parser_.parse(*request_, - buffer_->data(), buffer_->data() + length); - - // An indeterminate result means we need more data, so keep looping. - } while (boost::indeterminate(valid_request_)); - - // Create the reply object that will be sent back to the client. - reply_.reset(new reply); - - if (valid_request_) - { - // A valid request was received. Call the user-supplied function object - // to process the request and compose a reply. - request_handler_(*request_, *reply_); - } - else - { - // The request was invalid. - *reply_ = reply::stock_reply(reply::bad_request); - } - - // Send the reply back to the client. - yield boost::asio::async_write(*socket_, reply_->to_buffers(), *this); - - // Initiate graceful connection closure. - socket_->shutdown(tcp::socket::shutdown_both, ec); - } - } - - // If an error occurs then the coroutine is not reentered. Consequently, no - // new asynchronous operations are started. This means that all shared_ptr - // references will disappear and the resources associated with the coroutine - // will be destroyed automatically after this function call returns. -} - -// Disable the pseudo-keywords reenter, yield and fork. -#include <boost/asio/unyield.hpp> - -} // namespace server4 -} // namespace http diff --git a/doc/html/boost_asio/example/cpp03/http/server4/server.hpp b/doc/html/boost_asio/example/cpp03/http/server4/server.hpp deleted file mode 100644 index b8d428ebcf..0000000000 --- a/doc/html/boost_asio/example/cpp03/http/server4/server.hpp +++ /dev/null @@ -1,73 +0,0 @@ -// -// server.hpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER4_SERVER_HPP -#define HTTP_SERVER4_SERVER_HPP - -#include <boost/asio.hpp> -#include <string> -#include <boost/array.hpp> -#include <boost/function.hpp> -#include <boost/shared_ptr.hpp> -#include "request_parser.hpp" - -namespace http { -namespace server4 { - -struct request; -struct reply; - -/// The top-level coroutine of the HTTP server. -class server : boost::asio::coroutine -{ -public: - /// Construct the server to listen on the specified TCP address and port, and - /// serve up files from the given directory. - explicit server(boost::asio::io_service& io_service, - const std::string& address, const std::string& port, - boost::function<void(const request&, reply&)> request_handler); - - /// Perform work associated with the server. - void operator()( - boost::system::error_code ec = boost::system::error_code(), - std::size_t length = 0); - -private: - typedef boost::asio::ip::tcp tcp; - - /// The user-supplied handler for all incoming requests. - boost::function<void(const request&, reply&)> request_handler_; - - /// Acceptor used to listen for incoming connections. - boost::shared_ptr<tcp::acceptor> acceptor_; - - /// The current connection from a client. - boost::shared_ptr<tcp::socket> socket_; - - /// Buffer for incoming data. - boost::shared_ptr<boost::array<char, 8192> > buffer_; - - /// The incoming request. - boost::shared_ptr<request> request_; - - /// Whether the request is valid or not. - boost::tribool valid_request_; - - /// The parser for the incoming request. - request_parser request_parser_; - - /// The reply to be sent back to the client. - boost::shared_ptr<reply> reply_; -}; - -} // namespace server4 -} // namespace http - -#endif // HTTP_SERVER4_SERVER_HPP diff --git a/doc/html/boost_asio/example/cpp03/icmp/icmp_header.hpp b/doc/html/boost_asio/example/cpp03/icmp/icmp_header.hpp deleted file mode 100644 index 2e4d789302..0000000000 --- a/doc/html/boost_asio/example/cpp03/icmp/icmp_header.hpp +++ /dev/null @@ -1,94 +0,0 @@ -// -// icmp_header.hpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 ICMP_HEADER_HPP -#define ICMP_HEADER_HPP - -#include <istream> -#include <ostream> -#include <algorithm> - -// ICMP header for both IPv4 and IPv6. -// -// The wire format of an ICMP header is: -// -// 0 8 16 31 -// +---------------+---------------+------------------------------+ --- -// | | | | ^ -// | type | code | checksum | | -// | | | | | -// +---------------+---------------+------------------------------+ 8 bytes -// | | | | -// | identifier | sequence number | | -// | | | v -// +-------------------------------+------------------------------+ --- - -class icmp_header -{ -public: - enum { echo_reply = 0, destination_unreachable = 3, source_quench = 4, - redirect = 5, echo_request = 8, time_exceeded = 11, parameter_problem = 12, - timestamp_request = 13, timestamp_reply = 14, info_request = 15, - info_reply = 16, address_request = 17, address_reply = 18 }; - - icmp_header() { std::fill(rep_, rep_ + sizeof(rep_), 0); } - - unsigned char type() const { return rep_[0]; } - unsigned char code() const { return rep_[1]; } - unsigned short checksum() const { return decode(2, 3); } - unsigned short identifier() const { return decode(4, 5); } - unsigned short sequence_number() const { return decode(6, 7); } - - void type(unsigned char n) { rep_[0] = n; } - void code(unsigned char n) { rep_[1] = n; } - void checksum(unsigned short n) { encode(2, 3, n); } - void identifier(unsigned short n) { encode(4, 5, n); } - void sequence_number(unsigned short n) { encode(6, 7, n); } - - friend std::istream& operator>>(std::istream& is, icmp_header& header) - { return is.read(reinterpret_cast<char*>(header.rep_), 8); } - - friend std::ostream& operator<<(std::ostream& os, const icmp_header& header) - { return os.write(reinterpret_cast<const char*>(header.rep_), 8); } - -private: - unsigned short decode(int a, int b) const - { return (rep_[a] << 8) + rep_[b]; } - - void encode(int a, int b, unsigned short n) - { - rep_[a] = static_cast<unsigned char>(n >> 8); - rep_[b] = static_cast<unsigned char>(n & 0xFF); - } - - unsigned char rep_[8]; -}; - -template <typename Iterator> -void compute_checksum(icmp_header& header, - Iterator body_begin, Iterator body_end) -{ - unsigned int sum = (header.type() << 8) + header.code() - + header.identifier() + header.sequence_number(); - - Iterator body_iter = body_begin; - while (body_iter != body_end) - { - sum += (static_cast<unsigned char>(*body_iter++) << 8); - if (body_iter != body_end) - sum += static_cast<unsigned char>(*body_iter++); - } - - sum = (sum >> 16) + (sum & 0xFFFF); - sum += (sum >> 16); - header.checksum(static_cast<unsigned short>(~sum)); -} - -#endif // ICMP_HEADER_HPP diff --git a/doc/html/boost_asio/example/cpp03/icmp/ipv4_header.hpp b/doc/html/boost_asio/example/cpp03/icmp/ipv4_header.hpp deleted file mode 100644 index b406f2b28e..0000000000 --- a/doc/html/boost_asio/example/cpp03/icmp/ipv4_header.hpp +++ /dev/null @@ -1,102 +0,0 @@ -// -// ipv4_header.hpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 IPV4_HEADER_HPP -#define IPV4_HEADER_HPP - -#include <algorithm> -#include <boost/asio/ip/address_v4.hpp> - -// Packet header for IPv4. -// -// The wire format of an IPv4 header is: -// -// 0 8 16 31 -// +-------+-------+---------------+------------------------------+ --- -// | | | | | ^ -// |version|header | type of | total length in bytes | | -// | (4) | length| service | | | -// +-------+-------+---------------+-+-+-+------------------------+ | -// | | | | | | | -// | identification |0|D|M| fragment offset | | -// | | |F|F| | | -// +---------------+---------------+-+-+-+------------------------+ | -// | | | | | -// | time to live | protocol | header checksum | 20 bytes -// | | | | | -// +---------------+---------------+------------------------------+ | -// | | | -// | source IPv4 address | | -// | | | -// +--------------------------------------------------------------+ | -// | | | -// | destination IPv4 address | | -// | | v -// +--------------------------------------------------------------+ --- -// | | ^ -// | | | -// / options (if any) / 0 - 40 -// / / bytes -// | | | -// | | v -// +--------------------------------------------------------------+ --- - -class ipv4_header -{ -public: - ipv4_header() { std::fill(rep_, rep_ + sizeof(rep_), 0); } - - unsigned char version() const { return (rep_[0] >> 4) & 0xF; } - unsigned short header_length() const { return (rep_[0] & 0xF) * 4; } - unsigned char type_of_service() const { return rep_[1]; } - unsigned short total_length() const { return decode(2, 3); } - unsigned short identification() const { return decode(4, 5); } - bool dont_fragment() const { return (rep_[6] & 0x40) != 0; } - bool more_fragments() const { return (rep_[6] & 0x20) != 0; } - unsigned short fragment_offset() const { return decode(6, 7) & 0x1FFF; } - unsigned int time_to_live() const { return rep_[8]; } - unsigned char protocol() const { return rep_[9]; } - unsigned short header_checksum() const { return decode(10, 11); } - - boost::asio::ip::address_v4 source_address() const - { - boost::asio::ip::address_v4::bytes_type bytes - = { { rep_[12], rep_[13], rep_[14], rep_[15] } }; - return boost::asio::ip::address_v4(bytes); - } - - boost::asio::ip::address_v4 destination_address() const - { - boost::asio::ip::address_v4::bytes_type bytes - = { { rep_[16], rep_[17], rep_[18], rep_[19] } }; - return boost::asio::ip::address_v4(bytes); - } - - friend std::istream& operator>>(std::istream& is, ipv4_header& header) - { - is.read(reinterpret_cast<char*>(header.rep_), 20); - if (header.version() != 4) - is.setstate(std::ios::failbit); - std::streamsize options_length = header.header_length() - 20; - if (options_length < 0 || options_length > 40) - is.setstate(std::ios::failbit); - else - is.read(reinterpret_cast<char*>(header.rep_) + 20, options_length); - return is; - } - -private: - unsigned short decode(int a, int b) const - { return (rep_[a] << 8) + rep_[b]; } - - unsigned char rep_[60]; -}; - -#endif // IPV4_HEADER_HPP diff --git a/doc/html/boost_asio/example/cpp03/icmp/ping.cpp b/doc/html/boost_asio/example/cpp03/icmp/ping.cpp deleted file mode 100644 index bed6b55073..0000000000 --- a/doc/html/boost_asio/example/cpp03/icmp/ping.cpp +++ /dev/null @@ -1,162 +0,0 @@ -// -// ping.cpp -// ~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <boost/asio.hpp> -#include <boost/bind.hpp> -#include <istream> -#include <iostream> -#include <ostream> - -#include "icmp_header.hpp" -#include "ipv4_header.hpp" - -using boost::asio::ip::icmp; -using boost::asio::deadline_timer; -namespace posix_time = boost::posix_time; - -class pinger -{ -public: - pinger(boost::asio::io_service& io_service, const char* destination) - : resolver_(io_service), socket_(io_service, icmp::v4()), - timer_(io_service), sequence_number_(0), num_replies_(0) - { - icmp::resolver::query query(icmp::v4(), destination, ""); - destination_ = *resolver_.resolve(query); - - start_send(); - start_receive(); - } - -private: - void start_send() - { - std::string body("\"Hello!\" from Asio ping."); - - // Create an ICMP header for an echo request. - icmp_header echo_request; - echo_request.type(icmp_header::echo_request); - echo_request.code(0); - echo_request.identifier(get_identifier()); - echo_request.sequence_number(++sequence_number_); - compute_checksum(echo_request, body.begin(), body.end()); - - // Encode the request packet. - boost::asio::streambuf request_buffer; - std::ostream os(&request_buffer); - os << echo_request << body; - - // Send the request. - time_sent_ = posix_time::microsec_clock::universal_time(); - socket_.send_to(request_buffer.data(), destination_); - - // Wait up to five seconds for a reply. - num_replies_ = 0; - timer_.expires_at(time_sent_ + posix_time::seconds(5)); - timer_.async_wait(boost::bind(&pinger::handle_timeout, this)); - } - - void handle_timeout() - { - if (num_replies_ == 0) - std::cout << "Request timed out" << std::endl; - - // Requests must be sent no less than one second apart. - timer_.expires_at(time_sent_ + posix_time::seconds(1)); - timer_.async_wait(boost::bind(&pinger::start_send, this)); - } - - void start_receive() - { - // Discard any data already in the buffer. - reply_buffer_.consume(reply_buffer_.size()); - - // Wait for a reply. We prepare the buffer to receive up to 64KB. - socket_.async_receive(reply_buffer_.prepare(65536), - boost::bind(&pinger::handle_receive, this, _2)); - } - - void handle_receive(std::size_t length) - { - // The actual number of bytes received is committed to the buffer so that we - // can extract it using a std::istream object. - reply_buffer_.commit(length); - - // Decode the reply packet. - std::istream is(&reply_buffer_); - ipv4_header ipv4_hdr; - icmp_header icmp_hdr; - is >> ipv4_hdr >> icmp_hdr; - - // We can receive all ICMP packets received by the host, so we need to - // filter out only the echo replies that match the our identifier and - // expected sequence number. - if (is && icmp_hdr.type() == icmp_header::echo_reply - && icmp_hdr.identifier() == get_identifier() - && icmp_hdr.sequence_number() == sequence_number_) - { - // If this is the first reply, interrupt the five second timeout. - if (num_replies_++ == 0) - timer_.cancel(); - - // Print out some information about the reply packet. - posix_time::ptime now = posix_time::microsec_clock::universal_time(); - std::cout << length - ipv4_hdr.header_length() - << " bytes from " << ipv4_hdr.source_address() - << ": icmp_seq=" << icmp_hdr.sequence_number() - << ", ttl=" << ipv4_hdr.time_to_live() - << ", time=" << (now - time_sent_).total_milliseconds() << " ms" - << std::endl; - } - - start_receive(); - } - - static unsigned short get_identifier() - { -#if defined(BOOST_ASIO_WINDOWS) - return static_cast<unsigned short>(::GetCurrentProcessId()); -#else - return static_cast<unsigned short>(::getpid()); -#endif - } - - icmp::resolver resolver_; - icmp::endpoint destination_; - icmp::socket socket_; - deadline_timer timer_; - unsigned short sequence_number_; - posix_time::ptime time_sent_; - boost::asio::streambuf reply_buffer_; - std::size_t num_replies_; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: ping <host>" << std::endl; -#if !defined(BOOST_ASIO_WINDOWS) - std::cerr << "(You may need to run this program as root.)" << std::endl; -#endif - return 1; - } - - boost::asio::io_service io_service; - pinger p(io_service, argv[1]); - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << std::endl; - } -} diff --git a/doc/html/boost_asio/example/cpp03/invocation/prioritised_handlers.cpp b/doc/html/boost_asio/example/cpp03/invocation/prioritised_handlers.cpp deleted file mode 100644 index 01011d5578..0000000000 --- a/doc/html/boost_asio/example/cpp03/invocation/prioritised_handlers.cpp +++ /dev/null @@ -1,162 +0,0 @@ -// -// prioritised_handlers.cpp -// ~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <boost/asio.hpp> -#include <boost/function.hpp> -#include <iostream> -#include <queue> - -using boost::asio::ip::tcp; - -class handler_priority_queue -{ -public: - void add(int priority, boost::function<void()> function) - { - handlers_.push(queued_handler(priority, function)); - } - - void execute_all() - { - while (!handlers_.empty()) - { - queued_handler handler = handlers_.top(); - handler.execute(); - handlers_.pop(); - } - } - - // A generic wrapper class for handlers to allow the invocation to be hooked. - template <typename Handler> - class wrapped_handler - { - public: - wrapped_handler(handler_priority_queue& q, int p, Handler h) - : queue_(q), priority_(p), handler_(h) - { - } - - void operator()() - { - handler_(); - } - - template <typename Arg1> - void operator()(Arg1 arg1) - { - handler_(arg1); - } - - template <typename Arg1, typename Arg2> - void operator()(Arg1 arg1, Arg2 arg2) - { - handler_(arg1, arg2); - } - - //private: - handler_priority_queue& queue_; - int priority_; - Handler handler_; - }; - - template <typename Handler> - wrapped_handler<Handler> wrap(int priority, Handler handler) - { - return wrapped_handler<Handler>(*this, priority, handler); - } - -private: - class queued_handler - { - public: - queued_handler(int p, boost::function<void()> f) - : priority_(p), function_(f) - { - } - - void execute() - { - function_(); - } - - friend bool operator<(const queued_handler& a, - const queued_handler& b) - { - return a.priority_ < b.priority_; - } - - private: - int priority_; - boost::function<void()> function_; - }; - - std::priority_queue<queued_handler> handlers_; -}; - -// Custom invocation hook for wrapped handlers. -template <typename Function, typename Handler> -void asio_handler_invoke(Function f, - handler_priority_queue::wrapped_handler<Handler>* h) -{ - h->queue_.add(h->priority_, f); -} - -//---------------------------------------------------------------------- - -void high_priority_handler(const boost::system::error_code& /*ec*/) -{ - std::cout << "High priority handler\n"; -} - -void middle_priority_handler(const boost::system::error_code& /*ec*/) -{ - std::cout << "Middle priority handler\n"; -} - -void low_priority_handler() -{ - std::cout << "Low priority handler\n"; -} - -int main() -{ - boost::asio::io_service io_service; - - handler_priority_queue pri_queue; - - // Post a completion handler to be run immediately. - io_service.post(pri_queue.wrap(0, low_priority_handler)); - - // Start an asynchronous accept that will complete immediately. - tcp::endpoint endpoint(boost::asio::ip::address_v4::loopback(), 0); - tcp::acceptor acceptor(io_service, endpoint); - tcp::socket server_socket(io_service); - acceptor.async_accept(server_socket, - pri_queue.wrap(100, high_priority_handler)); - tcp::socket client_socket(io_service); - client_socket.connect(acceptor.local_endpoint()); - - // Set a deadline timer to expire immediately. - boost::asio::deadline_timer timer(io_service); - timer.expires_at(boost::posix_time::neg_infin); - timer.async_wait(pri_queue.wrap(42, middle_priority_handler)); - - while (io_service.run_one()) - { - // The custom invocation hook adds the handlers to the priority queue - // rather than executing them from within the poll_one() call. - while (io_service.poll_one()) - ; - - pri_queue.execute_all(); - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/iostreams/daytime_client.cpp b/doc/html/boost_asio/example/cpp03/iostreams/daytime_client.cpp deleted file mode 100644 index 6eef76d013..0000000000 --- a/doc/html/boost_asio/example/cpp03/iostreams/daytime_client.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// -// daytime_client.cpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <iostream> -#include <string> -#include <boost/asio.hpp> - -using boost::asio::ip::tcp; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: daytime_client <host>" << std::endl; - return 1; - } - - tcp::iostream s(argv[1], "daytime"); - if (!s) - { - std::cout << "Unable to connect: " << s.error().message() << std::endl; - return 1; - } - - std::string line; - std::getline(s, line); - std::cout << line << std::endl; - } - catch (std::exception& e) - { - std::cout << "Exception: " << e.what() << std::endl; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/iostreams/daytime_server.cpp b/doc/html/boost_asio/example/cpp03/iostreams/daytime_server.cpp deleted file mode 100644 index 409a511381..0000000000 --- a/doc/html/boost_asio/example/cpp03/iostreams/daytime_server.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// -// daytime_server.cpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <ctime> -#include <iostream> -#include <string> -#include <boost/asio.hpp> - -using boost::asio::ip::tcp; - -std::string make_daytime_string() -{ - using namespace std; // For time_t, time and ctime; - time_t now = time(0); - return ctime(&now); -} - -int main() -{ - try - { - boost::asio::io_service io_service; - - tcp::endpoint endpoint(tcp::v4(), 13); - tcp::acceptor acceptor(io_service, endpoint); - - for (;;) - { - tcp::iostream stream; - boost::system::error_code ec; - acceptor.accept(*stream.rdbuf(), ec); - if (!ec) - { - stream << make_daytime_string(); - } - } - } - catch (std::exception& e) - { - std::cerr << e.what() << std::endl; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/iostreams/http_client.cpp b/doc/html/boost_asio/example/cpp03/iostreams/http_client.cpp deleted file mode 100644 index 41319b5d52..0000000000 --- a/doc/html/boost_asio/example/cpp03/iostreams/http_client.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// -// sync_client.cpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <iostream> -#include <istream> -#include <ostream> -#include <string> -#include <boost/asio/ip/tcp.hpp> - -using boost::asio::ip::tcp; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 3) - { - std::cout << "Usage: http_client <server> <path>\n"; - std::cout << "Example:\n"; - std::cout << " http_client www.boost.org /LICENSE_1_0.txt\n"; - return 1; - } - - boost::asio::ip::tcp::iostream s; - - // The entire sequence of I/O operations must complete within 60 seconds. - // If an expiry occurs, the socket is automatically closed and the stream - // becomes bad. - s.expires_from_now(boost::posix_time::seconds(60)); - - // Establish a connection to the server. - s.connect(argv[1], "http"); - if (!s) - { - std::cout << "Unable to connect: " << s.error().message() << "\n"; - return 1; - } - - // Send the request. We specify the "Connection: close" header so that the - // server will close the socket after transmitting the response. This will - // allow us to treat all data up until the EOF as the content. - s << "GET " << argv[2] << " HTTP/1.0\r\n"; - s << "Host: " << argv[1] << "\r\n"; - s << "Accept: */*\r\n"; - s << "Connection: close\r\n\r\n"; - - // By default, the stream is tied with itself. This means that the stream - // automatically flush the buffered output before attempting a read. It is - // not necessary not explicitly flush the stream at this point. - - // Check that response is OK. - std::string http_version; - s >> http_version; - unsigned int status_code; - s >> status_code; - std::string status_message; - std::getline(s, status_message); - if (!s || http_version.substr(0, 5) != "HTTP/") - { - std::cout << "Invalid response\n"; - return 1; - } - if (status_code != 200) - { - std::cout << "Response returned with status code " << status_code << "\n"; - return 1; - } - - // Process the response headers, which are terminated by a blank line. - std::string header; - while (std::getline(s, header) && header != "\r") - std::cout << header << "\n"; - std::cout << "\n"; - - // Write the remaining data to output. - std::cout << s.rdbuf(); - } - catch (std::exception& e) - { - std::cout << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/local/connect_pair.cpp b/doc/html/boost_asio/example/cpp03/local/connect_pair.cpp deleted file mode 100644 index f78d6aa8f4..0000000000 --- a/doc/html/boost_asio/example/cpp03/local/connect_pair.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// -// connect_pair.cpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <iostream> -#include <string> -#include <cctype> -#include <boost/asio.hpp> -#include <boost/thread/thread.hpp> -#include <boost/array.hpp> -#include <boost/bind.hpp> - -#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) - -using boost::asio::local::stream_protocol; - -class uppercase_filter -{ -public: - uppercase_filter(boost::asio::io_service& io_service) - : socket_(io_service) - { - } - - stream_protocol::socket& socket() - { - return socket_; - } - - void start() - { - // Wait for request. - socket_.async_read_some(boost::asio::buffer(data_), - boost::bind(&uppercase_filter::handle_read, - this, boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - -private: - void handle_read(const boost::system::error_code& ec, std::size_t size) - { - if (!ec) - { - // Compute result. - for (std::size_t i = 0; i < size; ++i) - data_[i] = std::toupper(data_[i]); - - // Send result. - boost::asio::async_write(socket_, boost::asio::buffer(data_, size), - boost::bind(&uppercase_filter::handle_write, - this, boost::asio::placeholders::error)); - } - else - { - throw boost::system::system_error(ec); - } - } - - void handle_write(const boost::system::error_code& ec) - { - if (!ec) - { - // Wait for request. - socket_.async_read_some(boost::asio::buffer(data_), - boost::bind(&uppercase_filter::handle_read, - this, boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - else - { - throw boost::system::system_error(ec); - } - } - - stream_protocol::socket socket_; - boost::array<char, 512> data_; -}; - -void run(boost::asio::io_service* io_service) -{ - try - { - io_service->run(); - } - catch (std::exception& e) - { - std::cerr << "Exception in thread: " << e.what() << "\n"; - std::exit(1); - } -} - -int main() -{ - try - { - boost::asio::io_service io_service; - - // Create filter and establish a connection to it. - uppercase_filter filter(io_service); - stream_protocol::socket socket(io_service); - boost::asio::local::connect_pair(socket, filter.socket()); - filter.start(); - - // The io_service runs in a background thread to perform filtering. - boost::thread thread(boost::bind(run, &io_service)); - - for (;;) - { - // Collect request from user. - std::cout << "Enter a string: "; - std::string request; - std::getline(std::cin, request); - - // Send request to filter. - boost::asio::write(socket, boost::asio::buffer(request)); - - // Wait for reply from filter. - std::vector<char> reply(request.size()); - boost::asio::read(socket, boost::asio::buffer(reply)); - - // Show reply to user. - std::cout << "Result: "; - std::cout.write(&reply[0], request.size()); - std::cout << std::endl; - } - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - std::exit(1); - } -} - -#else // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) -# error Local sockets not available on this platform. -#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) diff --git a/doc/html/boost_asio/example/cpp03/local/iostream_client.cpp b/doc/html/boost_asio/example/cpp03/local/iostream_client.cpp deleted file mode 100644 index fe69898be8..0000000000 --- a/doc/html/boost_asio/example/cpp03/local/iostream_client.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// stream_client.cpp -// ~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstring> -#include <iostream> -#include <boost/asio.hpp> - -#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) - -using boost::asio::local::stream_protocol; - -enum { max_length = 1024 }; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: iostream_client <file>\n"; - return 1; - } - - stream_protocol::endpoint ep(argv[1]); - stream_protocol::iostream s(ep); - if (!s) - { - std::cerr << "Unable to connect: " << s.error().message() << std::endl; - return 1; - } - - using namespace std; // For strlen. - std::cout << "Enter message: "; - char request[max_length]; - std::cin.getline(request, max_length); - size_t length = strlen(request); - s << request; - - char reply[max_length]; - s.read(reply, length); - std::cout << "Reply is: "; - std::cout.write(reply, length); - std::cout << "\n"; - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} - -#else // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) -# error Local sockets not available on this platform. -#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) diff --git a/doc/html/boost_asio/example/cpp03/local/stream_client.cpp b/doc/html/boost_asio/example/cpp03/local/stream_client.cpp deleted file mode 100644 index 373309803a..0000000000 --- a/doc/html/boost_asio/example/cpp03/local/stream_client.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// -// stream_client.cpp -// ~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstdlib> -#include <cstring> -#include <iostream> -#include <boost/asio.hpp> - -#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) - -using boost::asio::local::stream_protocol; - -enum { max_length = 1024 }; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: stream_client <file>\n"; - return 1; - } - - boost::asio::io_service io_service; - - stream_protocol::socket s(io_service); - s.connect(stream_protocol::endpoint(argv[1])); - - using namespace std; // For strlen. - std::cout << "Enter message: "; - char request[max_length]; - std::cin.getline(request, max_length); - size_t request_length = strlen(request); - boost::asio::write(s, boost::asio::buffer(request, request_length)); - - char reply[max_length]; - size_t reply_length = boost::asio::read(s, - boost::asio::buffer(reply, request_length)); - std::cout << "Reply is: "; - std::cout.write(reply, reply_length); - std::cout << "\n"; - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} - -#else // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) -# error Local sockets not available on this platform. -#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) diff --git a/doc/html/boost_asio/example/cpp03/local/stream_server.cpp b/doc/html/boost_asio/example/cpp03/local/stream_server.cpp deleted file mode 100644 index 0cb75abc74..0000000000 --- a/doc/html/boost_asio/example/cpp03/local/stream_server.cpp +++ /dev/null @@ -1,141 +0,0 @@ -// -// stream_server.cpp -// ~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstdio> -#include <iostream> -#include <boost/array.hpp> -#include <boost/bind.hpp> -#include <boost/enable_shared_from_this.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/asio.hpp> - -#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) - -using boost::asio::local::stream_protocol; - -class session - : public boost::enable_shared_from_this<session> -{ -public: - session(boost::asio::io_service& io_service) - : socket_(io_service) - { - } - - stream_protocol::socket& socket() - { - return socket_; - } - - void start() - { - socket_.async_read_some(boost::asio::buffer(data_), - boost::bind(&session::handle_read, - shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - - void handle_read(const boost::system::error_code& error, - size_t bytes_transferred) - { - if (!error) - { - boost::asio::async_write(socket_, - boost::asio::buffer(data_, bytes_transferred), - boost::bind(&session::handle_write, - shared_from_this(), - boost::asio::placeholders::error)); - } - } - - void handle_write(const boost::system::error_code& error) - { - if (!error) - { - socket_.async_read_some(boost::asio::buffer(data_), - boost::bind(&session::handle_read, - shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - } - -private: - // The socket used to communicate with the client. - stream_protocol::socket socket_; - - // Buffer used to store data received from the client. - boost::array<char, 1024> data_; -}; - -typedef boost::shared_ptr<session> session_ptr; - -class server -{ -public: - server(boost::asio::io_service& io_service, const std::string& file) - : io_service_(io_service), - acceptor_(io_service, stream_protocol::endpoint(file)) - { - session_ptr new_session(new session(io_service_)); - acceptor_.async_accept(new_session->socket(), - boost::bind(&server::handle_accept, this, new_session, - boost::asio::placeholders::error)); - } - - void handle_accept(session_ptr new_session, - const boost::system::error_code& error) - { - if (!error) - { - new_session->start(); - } - - new_session.reset(new session(io_service_)); - acceptor_.async_accept(new_session->socket(), - boost::bind(&server::handle_accept, this, new_session, - boost::asio::placeholders::error)); - } - -private: - boost::asio::io_service& io_service_; - stream_protocol::acceptor acceptor_; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: stream_server <file>\n"; - std::cerr << "*** WARNING: existing file is removed ***\n"; - return 1; - } - - boost::asio::io_service io_service; - - std::remove(argv[1]); - server s(io_service, argv[1]); - - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} - -#else // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) -# error Local sockets not available on this platform. -#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) diff --git a/doc/html/boost_asio/example/cpp03/multicast/receiver.cpp b/doc/html/boost_asio/example/cpp03/multicast/receiver.cpp deleted file mode 100644 index 1de4feae5f..0000000000 --- a/doc/html/boost_asio/example/cpp03/multicast/receiver.cpp +++ /dev/null @@ -1,93 +0,0 @@ -// -// receiver.cpp -// ~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <iostream> -#include <string> -#include <boost/asio.hpp> -#include "boost/bind.hpp" - -const short multicast_port = 30001; - -class receiver -{ -public: - receiver(boost::asio::io_service& io_service, - const boost::asio::ip::address& listen_address, - const boost::asio::ip::address& multicast_address) - : socket_(io_service) - { - // Create the socket so that multiple may be bound to the same address. - boost::asio::ip::udp::endpoint listen_endpoint( - listen_address, multicast_port); - socket_.open(listen_endpoint.protocol()); - socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true)); - socket_.bind(listen_endpoint); - - // Join the multicast group. - socket_.set_option( - boost::asio::ip::multicast::join_group(multicast_address)); - - socket_.async_receive_from( - boost::asio::buffer(data_, max_length), sender_endpoint_, - boost::bind(&receiver::handle_receive_from, this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - - void handle_receive_from(const boost::system::error_code& error, - size_t bytes_recvd) - { - if (!error) - { - std::cout.write(data_, bytes_recvd); - std::cout << std::endl; - - socket_.async_receive_from( - boost::asio::buffer(data_, max_length), sender_endpoint_, - boost::bind(&receiver::handle_receive_from, this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - } - -private: - boost::asio::ip::udp::socket socket_; - boost::asio::ip::udp::endpoint sender_endpoint_; - enum { max_length = 1024 }; - char data_[max_length]; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 3) - { - std::cerr << "Usage: receiver <listen_address> <multicast_address>\n"; - std::cerr << " For IPv4, try:\n"; - std::cerr << " receiver 0.0.0.0 239.255.0.1\n"; - std::cerr << " For IPv6, try:\n"; - std::cerr << " receiver 0::0 ff31::8000:1234\n"; - return 1; - } - - boost::asio::io_service io_service; - receiver r(io_service, - boost::asio::ip::address::from_string(argv[1]), - boost::asio::ip::address::from_string(argv[2])); - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/multicast/sender.cpp b/doc/html/boost_asio/example/cpp03/multicast/sender.cpp deleted file mode 100644 index dc47c15709..0000000000 --- a/doc/html/boost_asio/example/cpp03/multicast/sender.cpp +++ /dev/null @@ -1,99 +0,0 @@ -// -// sender.cpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <iostream> -#include <sstream> -#include <string> -#include <boost/asio.hpp> -#include "boost/bind.hpp" -#include "boost/date_time/posix_time/posix_time_types.hpp" - -const short multicast_port = 30001; -const int max_message_count = 10; - -class sender -{ -public: - sender(boost::asio::io_service& io_service, - const boost::asio::ip::address& multicast_address) - : endpoint_(multicast_address, multicast_port), - socket_(io_service, endpoint_.protocol()), - timer_(io_service), - message_count_(0) - { - std::ostringstream os; - os << "Message " << message_count_++; - message_ = os.str(); - - socket_.async_send_to( - boost::asio::buffer(message_), endpoint_, - boost::bind(&sender::handle_send_to, this, - boost::asio::placeholders::error)); - } - - void handle_send_to(const boost::system::error_code& error) - { - if (!error && message_count_ < max_message_count) - { - timer_.expires_from_now(boost::posix_time::seconds(1)); - timer_.async_wait( - boost::bind(&sender::handle_timeout, this, - boost::asio::placeholders::error)); - } - } - - void handle_timeout(const boost::system::error_code& error) - { - if (!error) - { - std::ostringstream os; - os << "Message " << message_count_++; - message_ = os.str(); - - socket_.async_send_to( - boost::asio::buffer(message_), endpoint_, - boost::bind(&sender::handle_send_to, this, - boost::asio::placeholders::error)); - } - } - -private: - boost::asio::ip::udp::endpoint endpoint_; - boost::asio::ip::udp::socket socket_; - boost::asio::deadline_timer timer_; - int message_count_; - std::string message_; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: sender <multicast_address>\n"; - std::cerr << " For IPv4, try:\n"; - std::cerr << " sender 239.255.0.1\n"; - std::cerr << " For IPv6, try:\n"; - std::cerr << " sender ff31::8000:1234\n"; - return 1; - } - - boost::asio::io_service io_service; - sender s(io_service, boost::asio::ip::address::from_string(argv[1])); - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/nonblocking/third_party_lib.cpp b/doc/html/boost_asio/example/cpp03/nonblocking/third_party_lib.cpp deleted file mode 100644 index 137899f7c6..0000000000 --- a/doc/html/boost_asio/example/cpp03/nonblocking/third_party_lib.cpp +++ /dev/null @@ -1,242 +0,0 @@ -// -// third_party_lib.cpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <boost/asio.hpp> -#include <boost/array.hpp> -#include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> -#include <iostream> - -using boost::asio::ip::tcp; - -namespace third_party_lib { - -// Simulation of a third party library that wants to perform read and write -// operations directly on a socket. It needs to be polled to determine whether -// it requires a read or write operation, and notified when the socket is ready -// for reading or writing. -class session -{ -public: - session(tcp::socket& socket) - : socket_(socket), - state_(reading) - { - } - - // Returns true if the third party library wants to be notified when the - // socket is ready for reading. - bool want_read() const - { - return state_ == reading; - } - - // Notify that third party library that it should perform its read operation. - void do_read(boost::system::error_code& ec) - { - if (std::size_t len = socket_.read_some(boost::asio::buffer(data_), ec)) - { - write_buffer_ = boost::asio::buffer(data_, len); - state_ = writing; - } - } - - // Returns true if the third party library wants to be notified when the - // socket is ready for writing. - bool want_write() const - { - return state_ == writing; - } - - // Notify that third party library that it should perform its write operation. - void do_write(boost::system::error_code& ec) - { - if (std::size_t len = socket_.write_some( - boost::asio::buffer(write_buffer_), ec)) - { - write_buffer_ = write_buffer_ + len; - state_ = boost::asio::buffer_size(write_buffer_) > 0 ? writing : reading; - } - } - -private: - tcp::socket& socket_; - enum { reading, writing } state_; - boost::array<char, 128> data_; - boost::asio::const_buffer write_buffer_; -}; - -} // namespace third_party_lib - -// The glue between asio's sockets and the third party library. -class connection - : public boost::enable_shared_from_this<connection> -{ -public: - typedef boost::shared_ptr<connection> pointer; - - static pointer create(boost::asio::io_service& io_service) - { - return pointer(new connection(io_service)); - } - - tcp::socket& socket() - { - return socket_; - } - - void start() - { - // Put the socket into non-blocking mode. - socket_.non_blocking(true); - - start_operations(); - } - -private: - connection(boost::asio::io_service& io_service) - : socket_(io_service), - session_impl_(socket_), - read_in_progress_(false), - write_in_progress_(false) - { - } - - void start_operations() - { - // Start a read operation if the third party library wants one. - if (session_impl_.want_read() && !read_in_progress_) - { - read_in_progress_ = true; - socket_.async_read_some( - boost::asio::null_buffers(), - boost::bind(&connection::handle_read, - shared_from_this(), - boost::asio::placeholders::error)); - } - - // Start a write operation if the third party library wants one. - if (session_impl_.want_write() && !write_in_progress_) - { - write_in_progress_ = true; - socket_.async_write_some( - boost::asio::null_buffers(), - boost::bind(&connection::handle_write, - shared_from_this(), - boost::asio::placeholders::error)); - } - } - - void handle_read(boost::system::error_code ec) - { - read_in_progress_ = false; - - // Notify third party library that it can perform a read. - if (!ec) - session_impl_.do_read(ec); - - // The third party library successfully performed a read on the socket. - // Start new read or write operations based on what it now wants. - if (!ec || ec == boost::asio::error::would_block) - start_operations(); - - // Otherwise, an error occurred. Closing the socket cancels any outstanding - // asynchronous read or write operations. The connection object will be - // destroyed automatically once those outstanding operations complete. - else - socket_.close(); - } - - void handle_write(boost::system::error_code ec) - { - write_in_progress_ = false; - - // Notify third party library that it can perform a write. - if (!ec) - session_impl_.do_write(ec); - - // The third party library successfully performed a write on the socket. - // Start new read or write operations based on what it now wants. - if (!ec || ec == boost::asio::error::would_block) - start_operations(); - - // Otherwise, an error occurred. Closing the socket cancels any outstanding - // asynchronous read or write operations. The connection object will be - // destroyed automatically once those outstanding operations complete. - else - socket_.close(); - } - -private: - tcp::socket socket_; - third_party_lib::session session_impl_; - bool read_in_progress_; - bool write_in_progress_; -}; - -class server -{ -public: - server(boost::asio::io_service& io_service, unsigned short port) - : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)) - { - start_accept(); - } - -private: - void start_accept() - { - connection::pointer new_connection = - connection::create(acceptor_.get_io_service()); - - acceptor_.async_accept(new_connection->socket(), - boost::bind(&server::handle_accept, this, new_connection, - boost::asio::placeholders::error)); - } - - void handle_accept(connection::pointer new_connection, - const boost::system::error_code& error) - { - if (!error) - { - new_connection->start(); - } - - start_accept(); - } - - tcp::acceptor acceptor_; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: third_party_lib <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - using namespace std; // For atoi. - server s(io_service, atoi(argv[1])); - - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/porthopper/client.cpp b/doc/html/boost_asio/example/cpp03/porthopper/client.cpp deleted file mode 100644 index 5fc27ba087..0000000000 --- a/doc/html/boost_asio/example/cpp03/porthopper/client.cpp +++ /dev/null @@ -1,193 +0,0 @@ -// -// client.cpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <boost/asio.hpp> -#include <boost/lambda/lambda.hpp> -#include <boost/lambda/bind.hpp> -#include <boost/lambda/if.hpp> -#include <boost/shared_ptr.hpp> -#include <algorithm> -#include <cstdlib> -#include <exception> -#include <iostream> -#include <string> -#include "protocol.hpp" - -using namespace boost; -using boost::asio::ip::tcp; -using boost::asio::ip::udp; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 3) - { - std::cerr << "Usage: client <host> <port>\n"; - return 1; - } - using namespace std; // For atoi. - std::string host_name = argv[1]; - std::string port = argv[2]; - - boost::asio::io_service io_service; - - // Determine the location of the server. - tcp::resolver resolver(io_service); - tcp::resolver::query query(host_name, port); - tcp::endpoint remote_endpoint = *resolver.resolve(query); - - // Establish the control connection to the server. - tcp::socket control_socket(io_service); - control_socket.connect(remote_endpoint); - - // Create a datagram socket to receive data from the server. - boost::shared_ptr<udp::socket> data_socket( - new udp::socket(io_service, udp::endpoint(udp::v4(), 0))); - - // Determine what port we will receive data on. - udp::endpoint data_endpoint = data_socket->local_endpoint(); - - // Ask the server to start sending us data. - control_request start = control_request::start(data_endpoint.port()); - boost::asio::write(control_socket, start.to_buffers()); - - unsigned long last_frame_number = 0; - for (;;) - { - // Receive 50 messages on the current data socket. - for (int i = 0; i < 50; ++i) - { - // Receive a frame from the server. - frame f; - data_socket->receive(f.to_buffers(), 0); - if (f.number() > last_frame_number) - { - last_frame_number = f.number(); - std::cout << "\n" << f.payload(); - } - } - - // Time to switch to a new socket. To ensure seamless handover we will - // continue to receive packets using the old socket until data arrives on - // the new one. - std::cout << " Starting renegotiation"; - - // Create the new data socket. - boost::shared_ptr<udp::socket> new_data_socket( - new udp::socket(io_service, udp::endpoint(udp::v4(), 0))); - - // Determine the new port we will use to receive data. - udp::endpoint new_data_endpoint = new_data_socket->local_endpoint(); - - // Ask the server to switch over to the new port. - control_request change = control_request::change( - data_endpoint.port(), new_data_endpoint.port()); - boost::system::error_code control_result; - boost::asio::async_write(control_socket, change.to_buffers(), - ( - lambda::var(control_result) = lambda::_1 - )); - - // Try to receive a frame from the server on the new data socket. If we - // successfully receive a frame on this new data socket we can consider - // the renegotation complete. In that case we will close the old data - // socket, which will cause any outstanding receive operation on it to be - // cancelled. - frame f1; - boost::system::error_code new_data_socket_result; - new_data_socket->async_receive(f1.to_buffers(), - ( - // Note: lambda::_1 is the first argument to the callback handler, - // which in this case is the error code for the operation. - lambda::var(new_data_socket_result) = lambda::_1, - lambda::if_(!lambda::_1) - [ - // We have successfully received a frame on the new data socket, - // so we can close the old data socket. This will cancel any - // outstanding receive operation on the old data socket. - lambda::var(data_socket) = boost::shared_ptr<udp::socket>() - ] - )); - - // This loop will continue until we have successfully completed the - // renegotiation (i.e. received a frame on the new data socket), or some - // unrecoverable error occurs. - bool done = false; - while (!done) - { - // Even though we're performing a renegotation, we want to continue - // receiving data as smoothly as possible. Therefore we will continue to - // try to receive a frame from the server on the old data socket. If we - // receive a frame on this socket we will interrupt the io_service, - // print the frame, and resume waiting for the other operations to - // complete. - frame f2; - done = true; // Let's be optimistic. - if (data_socket) // Might have been closed by new_data_socket's handler. - { - data_socket->async_receive(f2.to_buffers(), 0, - ( - lambda::if_(!lambda::_1) - [ - // We have successfully received a frame on the old data - // socket. Stop the io_service so that we can print it. - lambda::bind(&boost::asio::io_service::stop, &io_service), - lambda::var(done) = false - ] - )); - } - - // Run the operations in parallel. This will block until all operations - // have finished, or until the io_service is interrupted. (No threads!) - io_service.reset(); - io_service.run(); - - // If the io_service.run() was interrupted then we have received a frame - // on the old data socket. We need to keep waiting for the renegotation - // operations to complete. - if (!done) - { - if (f2.number() > last_frame_number) - { - last_frame_number = f2.number(); - std::cout << "\n" << f2.payload(); - } - } - } - - // Since the loop has finished, we have either successfully completed - // the renegotation, or an error has occurred. First we'll check for - // errors. - if (control_result) - throw boost::system::system_error(control_result); - if (new_data_socket_result) - throw boost::system::system_error(new_data_socket_result); - - // If we get here it means we have successfully started receiving data on - // the new data socket. This new data socket will be used from now on - // (until the next time we renegotiate). - std::cout << " Renegotiation complete"; - data_socket = new_data_socket; - data_endpoint = new_data_endpoint; - if (f1.number() > last_frame_number) - { - last_frame_number = f1.number(); - std::cout << "\n" << f1.payload(); - } - } - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << std::endl; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/porthopper/protocol.hpp b/doc/html/boost_asio/example/cpp03/porthopper/protocol.hpp deleted file mode 100644 index a30bb89225..0000000000 --- a/doc/html/boost_asio/example/cpp03/porthopper/protocol.hpp +++ /dev/null @@ -1,156 +0,0 @@ -// -// protocol.hpp -// ~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 PORTHOPPER_PROTOCOL_HPP -#define PORTHOPPER_PROTOCOL_HPP - -#include <boost/array.hpp> -#include <boost/asio.hpp> -#include <cstring> -#include <iomanip> -#include <string> -#include <strstream> - -// This request is sent by the client to the server over a TCP connection. -// The client uses it to perform three functions: -// - To request that data start being sent to a given port. -// - To request that data is no longer sent to a given port. -// - To change the target port to another. -class control_request -{ -public: - // Construct an empty request. Used when receiving. - control_request() - { - } - - // Create a request to start sending data to a given port. - static const control_request start(unsigned short port) - { - return control_request(0, port); - } - - // Create a request to stop sending data to a given port. - static const control_request stop(unsigned short port) - { - return control_request(port, 0); - } - - // Create a request to change the port that data is sent to. - static const control_request change( - unsigned short old_port, unsigned short new_port) - { - return control_request(old_port, new_port); - } - - // Get the old port. Returns 0 for start requests. - unsigned short old_port() const - { - std::istrstream is(data_, encoded_port_size); - unsigned short port = 0; - is >> std::setw(encoded_port_size) >> std::hex >> port; - return port; - } - - // Get the new port. Returns 0 for stop requests. - unsigned short new_port() const - { - std::istrstream is(data_ + encoded_port_size, encoded_port_size); - unsigned short port = 0; - is >> std::setw(encoded_port_size) >> std::hex >> port; - return port; - } - - // Obtain buffers for reading from or writing to a socket. - boost::array<boost::asio::mutable_buffer, 1> to_buffers() - { - boost::array<boost::asio::mutable_buffer, 1> buffers - = { { boost::asio::buffer(data_) } }; - return buffers; - } - -private: - // Construct with specified old and new ports. - control_request(unsigned short old_port_number, - unsigned short new_port_number) - { - std::ostrstream os(data_, control_request_size); - os << std::setw(encoded_port_size) << std::hex << old_port_number; - os << std::setw(encoded_port_size) << std::hex << new_port_number; - } - - // The length in bytes of a control_request and its components. - enum - { - encoded_port_size = 4, // 16-bit port in hex. - control_request_size = encoded_port_size * 2 - }; - - // The encoded request data. - char data_[control_request_size]; -}; - -// This frame is sent from the server to subscribed clients over UDP. -class frame -{ -public: - // The maximum allowable length of the payload. - enum { payload_size = 32 }; - - // Construct an empty frame. Used when receiving. - frame() - { - } - - // Construct a frame with specified frame number and payload. - frame(unsigned long frame_number, const std::string& payload_data) - { - std::ostrstream os(data_, frame_size); - os << std::setw(encoded_number_size) << std::hex << frame_number; - os << std::setw(payload_size) - << std::setfill(' ') << payload_data.substr(0, payload_size); - } - - // Get the frame number. - unsigned long number() const - { - std::istrstream is(data_, encoded_number_size); - unsigned long frame_number = 0; - is >> std::setw(encoded_number_size) >> std::hex >> frame_number; - return frame_number; - } - - // Get the payload data. - const std::string payload() const - { - return std::string(data_ + encoded_number_size, payload_size); - } - - // Obtain buffers for reading from or writing to a socket. - boost::array<boost::asio::mutable_buffer, 1> to_buffers() - { - boost::array<boost::asio::mutable_buffer, 1> buffers - = { { boost::asio::buffer(data_) } }; - return buffers; - } - -private: - // The length in bytes of a frame and its components. - enum - { - encoded_number_size = 8, // Frame number in hex. - frame_size = encoded_number_size + payload_size - }; - - // The encoded frame data. - char data_[frame_size]; -}; - -#endif // PORTHOPPER_PROTOCOL_HPP diff --git a/doc/html/boost_asio/example/cpp03/porthopper/server.cpp b/doc/html/boost_asio/example/cpp03/porthopper/server.cpp deleted file mode 100644 index 802be7f511..0000000000 --- a/doc/html/boost_asio/example/cpp03/porthopper/server.cpp +++ /dev/null @@ -1,187 +0,0 @@ -// -// server.cpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <boost/asio.hpp> -#include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> -#include <cmath> -#include <cstdlib> -#include <exception> -#include <iostream> -#include <set> -#include "protocol.hpp" - -using boost::asio::ip::tcp; -using boost::asio::ip::udp; - -typedef boost::shared_ptr<tcp::socket> tcp_socket_ptr; -typedef boost::shared_ptr<boost::asio::deadline_timer> timer_ptr; -typedef boost::shared_ptr<control_request> control_request_ptr; - -class server -{ -public: - // Construct the server to wait for incoming control connections. - server(boost::asio::io_service& io_service, unsigned short port) - : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)), - timer_(io_service), - udp_socket_(io_service, udp::endpoint(udp::v4(), 0)), - next_frame_number_(1) - { - // Start waiting for a new control connection. - tcp_socket_ptr new_socket(new tcp::socket(acceptor_.get_io_service())); - acceptor_.async_accept(*new_socket, - boost::bind(&server::handle_accept, this, - boost::asio::placeholders::error, new_socket)); - - // Start the timer used to generate outgoing frames. - timer_.expires_from_now(boost::posix_time::milliseconds(100)); - timer_.async_wait(boost::bind(&server::handle_timer, this)); - } - - // Handle a new control connection. - void handle_accept(const boost::system::error_code& ec, tcp_socket_ptr socket) - { - if (!ec) - { - // Start receiving control requests on the connection. - control_request_ptr request(new control_request); - boost::asio::async_read(*socket, request->to_buffers(), - boost::bind(&server::handle_control_request, this, - boost::asio::placeholders::error, socket, request)); - } - - // Start waiting for a new control connection. - tcp_socket_ptr new_socket(new tcp::socket(acceptor_.get_io_service())); - acceptor_.async_accept(*new_socket, - boost::bind(&server::handle_accept, this, - boost::asio::placeholders::error, new_socket)); - } - - // Handle a new control request. - void handle_control_request(const boost::system::error_code& ec, - tcp_socket_ptr socket, control_request_ptr request) - { - if (!ec) - { - // Delay handling of the control request to simulate network latency. - timer_ptr delay_timer( - new boost::asio::deadline_timer(acceptor_.get_io_service())); - delay_timer->expires_from_now(boost::posix_time::seconds(2)); - delay_timer->async_wait( - boost::bind(&server::handle_control_request_timer, this, - socket, request, delay_timer)); - } - } - - void handle_control_request_timer(tcp_socket_ptr socket, - control_request_ptr request, timer_ptr /*delay_timer*/) - { - // Determine what address this client is connected from, since - // subscriptions must be stored on the server as a complete endpoint, not - // just a port. We use the non-throwing overload of remote_endpoint() since - // it may fail if the socket is no longer connected. - boost::system::error_code ec; - tcp::endpoint remote_endpoint = socket->remote_endpoint(ec); - if (!ec) - { - // Remove old port subscription, if any. - if (unsigned short old_port = request->old_port()) - { - udp::endpoint old_endpoint(remote_endpoint.address(), old_port); - subscribers_.erase(old_endpoint); - std::cout << "Removing subscription " << old_endpoint << std::endl; - } - - // Add new port subscription, if any. - if (unsigned short new_port = request->new_port()) - { - udp::endpoint new_endpoint(remote_endpoint.address(), new_port); - subscribers_.insert(new_endpoint); - std::cout << "Adding subscription " << new_endpoint << std::endl; - } - } - - // Wait for next control request on this connection. - boost::asio::async_read(*socket, request->to_buffers(), - boost::bind(&server::handle_control_request, this, - boost::asio::placeholders::error, socket, request)); - } - - // Every time the timer fires we will generate a new frame and send it to all - // subscribers. - void handle_timer() - { - // Generate payload. - double x = next_frame_number_ * 0.2; - double y = std::sin(x); - int char_index = static_cast<int>((y + 1.0) * (frame::payload_size / 2)); - std::string payload; - for (int i = 0; i < frame::payload_size; ++i) - payload += (i == char_index ? '*' : '.'); - - // Create the frame to be sent to all subscribers. - frame f(next_frame_number_++, payload); - - // Send frame to all subscribers. We can use synchronous calls here since - // UDP send operations typically do not block. - std::set<udp::endpoint>::iterator j; - for (j = subscribers_.begin(); j != subscribers_.end(); ++j) - { - boost::system::error_code ec; - udp_socket_.send_to(f.to_buffers(), *j, 0, ec); - } - - // Wait for next timeout. - timer_.expires_from_now(boost::posix_time::milliseconds(100)); - timer_.async_wait(boost::bind(&server::handle_timer, this)); - } - -private: - // The acceptor used to accept incoming control connections. - tcp::acceptor acceptor_; - - // The timer used for generating data. - boost::asio::deadline_timer timer_; - - // The socket used to send data to subscribers. - udp::socket udp_socket_; - - // The next frame number. - unsigned long next_frame_number_; - - // The set of endpoints that are subscribed. - std::set<udp::endpoint> subscribers_; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: server <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - using namespace std; // For atoi. - server s(io_service, atoi(argv[1])); - - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << std::endl; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/serialization/client.cpp b/doc/html/boost_asio/example/cpp03/serialization/client.cpp deleted file mode 100644 index 968434d68a..0000000000 --- a/doc/html/boost_asio/example/cpp03/serialization/client.cpp +++ /dev/null @@ -1,125 +0,0 @@ -// -// client.cpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <boost/asio.hpp> -#include <boost/bind.hpp> -#include <iostream> -#include <vector> -#include "connection.hpp" // Must come before boost/serialization headers. -#include <boost/serialization/vector.hpp> -#include "stock.hpp" - -namespace s11n_example { - -/// Downloads stock quote information from a server. -class client -{ -public: - /// Constructor starts the asynchronous connect operation. - client(boost::asio::io_service& io_service, - const std::string& host, const std::string& service) - : connection_(io_service) - { - // Resolve the host name into an IP address. - boost::asio::ip::tcp::resolver resolver(io_service); - boost::asio::ip::tcp::resolver::query query(host, service); - boost::asio::ip::tcp::resolver::iterator endpoint_iterator = - resolver.resolve(query); - - // Start an asynchronous connect operation. - boost::asio::async_connect(connection_.socket(), endpoint_iterator, - boost::bind(&client::handle_connect, this, - boost::asio::placeholders::error)); - } - - /// Handle completion of a connect operation. - void handle_connect(const boost::system::error_code& e) - { - if (!e) - { - // Successfully established connection. Start operation to read the list - // of stocks. The connection::async_read() function will automatically - // decode the data that is read from the underlying socket. - connection_.async_read(stocks_, - boost::bind(&client::handle_read, this, - boost::asio::placeholders::error)); - } - else - { - // An error occurred. Log it and return. Since we are not starting a new - // operation the io_service will run out of work to do and the client will - // exit. - std::cerr << e.message() << std::endl; - } - } - - /// Handle completion of a read operation. - void handle_read(const boost::system::error_code& e) - { - if (!e) - { - // Print out the data that was received. - for (std::size_t i = 0; i < stocks_.size(); ++i) - { - std::cout << "Stock number " << i << "\n"; - std::cout << " code: " << stocks_[i].code << "\n"; - std::cout << " name: " << stocks_[i].name << "\n"; - std::cout << " open_price: " << stocks_[i].open_price << "\n"; - std::cout << " high_price: " << stocks_[i].high_price << "\n"; - std::cout << " low_price: " << stocks_[i].low_price << "\n"; - std::cout << " last_price: " << stocks_[i].last_price << "\n"; - std::cout << " buy_price: " << stocks_[i].buy_price << "\n"; - std::cout << " buy_quantity: " << stocks_[i].buy_quantity << "\n"; - std::cout << " sell_price: " << stocks_[i].sell_price << "\n"; - std::cout << " sell_quantity: " << stocks_[i].sell_quantity << "\n"; - } - } - else - { - // An error occurred. - std::cerr << e.message() << std::endl; - } - - // Since we are not starting a new operation the io_service will run out of - // work to do and the client will exit. - } - -private: - /// The connection to the server. - connection connection_; - - /// The data received from the server. - std::vector<stock> stocks_; -}; - -} // namespace s11n_example - -int main(int argc, char* argv[]) -{ - try - { - // Check command line arguments. - if (argc != 3) - { - std::cerr << "Usage: client <host> <port>" << std::endl; - return 1; - } - - boost::asio::io_service io_service; - s11n_example::client client(io_service, argv[1], argv[2]); - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << e.what() << std::endl; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/serialization/connection.hpp b/doc/html/boost_asio/example/cpp03/serialization/connection.hpp deleted file mode 100644 index 9fdcb4bfcd..0000000000 --- a/doc/html/boost_asio/example/cpp03/serialization/connection.hpp +++ /dev/null @@ -1,188 +0,0 @@ -// -// connection.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 SERIALIZATION_CONNECTION_HPP -#define SERIALIZATION_CONNECTION_HPP - -#include <boost/asio.hpp> -#include <boost/archive/text_iarchive.hpp> -#include <boost/archive/text_oarchive.hpp> -#include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/tuple/tuple.hpp> -#include <iomanip> -#include <string> -#include <sstream> -#include <vector> - -namespace s11n_example { - -/// The connection class provides serialization primitives on top of a socket. -/** - * Each message sent using this class consists of: - * @li An 8-byte header containing the length of the serialized data in - * hexadecimal. - * @li The serialized data. - */ -class connection -{ -public: - /// Constructor. - connection(boost::asio::io_service& io_service) - : socket_(io_service) - { - } - - /// Get the underlying socket. Used for making a connection or for accepting - /// an incoming connection. - boost::asio::ip::tcp::socket& socket() - { - return socket_; - } - - /// Asynchronously write a data structure to the socket. - template <typename T, typename Handler> - void async_write(const T& t, Handler handler) - { - // Serialize the data first so we know how large it is. - std::ostringstream archive_stream; - boost::archive::text_oarchive archive(archive_stream); - archive << t; - outbound_data_ = archive_stream.str(); - - // Format the header. - std::ostringstream header_stream; - header_stream << std::setw(header_length) - << std::hex << outbound_data_.size(); - if (!header_stream || header_stream.str().size() != header_length) - { - // Something went wrong, inform the caller. - boost::system::error_code error(boost::asio::error::invalid_argument); - socket_.get_io_service().post(boost::bind(handler, error)); - return; - } - outbound_header_ = header_stream.str(); - - // Write the serialized data to the socket. We use "gather-write" to send - // both the header and the data in a single write operation. - std::vector<boost::asio::const_buffer> buffers; - buffers.push_back(boost::asio::buffer(outbound_header_)); - buffers.push_back(boost::asio::buffer(outbound_data_)); - boost::asio::async_write(socket_, buffers, handler); - } - - /// Asynchronously read a data structure from the socket. - template <typename T, typename Handler> - void async_read(T& t, Handler handler) - { - // Issue a read operation to read exactly the number of bytes in a header. - void (connection::*f)( - const boost::system::error_code&, - T&, boost::tuple<Handler>) - = &connection::handle_read_header<T, Handler>; - boost::asio::async_read(socket_, boost::asio::buffer(inbound_header_), - boost::bind(f, - this, boost::asio::placeholders::error, boost::ref(t), - boost::make_tuple(handler))); - } - - /// Handle a completed read of a message header. The handler is passed using - /// a tuple since boost::bind seems to have trouble binding a function object - /// created using boost::bind as a parameter. - template <typename T, typename Handler> - void handle_read_header(const boost::system::error_code& e, - T& t, boost::tuple<Handler> handler) - { - if (e) - { - boost::get<0>(handler)(e); - } - else - { - // Determine the length of the serialized data. - std::istringstream is(std::string(inbound_header_, header_length)); - std::size_t inbound_data_size = 0; - if (!(is >> std::hex >> inbound_data_size)) - { - // Header doesn't seem to be valid. Inform the caller. - boost::system::error_code error(boost::asio::error::invalid_argument); - boost::get<0>(handler)(error); - return; - } - - // Start an asynchronous call to receive the data. - inbound_data_.resize(inbound_data_size); - void (connection::*f)( - const boost::system::error_code&, - T&, boost::tuple<Handler>) - = &connection::handle_read_data<T, Handler>; - boost::asio::async_read(socket_, boost::asio::buffer(inbound_data_), - boost::bind(f, this, - boost::asio::placeholders::error, boost::ref(t), handler)); - } - } - - /// Handle a completed read of message data. - template <typename T, typename Handler> - void handle_read_data(const boost::system::error_code& e, - T& t, boost::tuple<Handler> handler) - { - if (e) - { - boost::get<0>(handler)(e); - } - else - { - // Extract the data structure from the data just received. - try - { - std::string archive_data(&inbound_data_[0], inbound_data_.size()); - std::istringstream archive_stream(archive_data); - boost::archive::text_iarchive archive(archive_stream); - archive >> t; - } - catch (std::exception& e) - { - // Unable to decode data. - boost::system::error_code error(boost::asio::error::invalid_argument); - boost::get<0>(handler)(error); - return; - } - - // Inform caller that data has been received ok. - boost::get<0>(handler)(e); - } - } - -private: - /// The underlying socket. - boost::asio::ip::tcp::socket socket_; - - /// The size of a fixed length header. - enum { header_length = 8 }; - - /// Holds an outbound header. - std::string outbound_header_; - - /// Holds the outbound data. - std::string outbound_data_; - - /// Holds an inbound header. - char inbound_header_[header_length]; - - /// Holds the inbound data. - std::vector<char> inbound_data_; -}; - -typedef boost::shared_ptr<connection> connection_ptr; - -} // namespace s11n_example - -#endif // SERIALIZATION_CONNECTION_HPP diff --git a/doc/html/boost_asio/example/cpp03/serialization/server.cpp b/doc/html/boost_asio/example/cpp03/serialization/server.cpp deleted file mode 100644 index 65f314ad1c..0000000000 --- a/doc/html/boost_asio/example/cpp03/serialization/server.cpp +++ /dev/null @@ -1,123 +0,0 @@ -// -// server.cpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <boost/asio.hpp> -#include <boost/bind.hpp> -#include <boost/lexical_cast.hpp> -#include <iostream> -#include <vector> -#include "connection.hpp" // Must come before boost/serialization headers. -#include <boost/serialization/vector.hpp> -#include "stock.hpp" - -namespace s11n_example { - -/// Serves stock quote information to any client that connects to it. -class server -{ -public: - /// Constructor opens the acceptor and starts waiting for the first incoming - /// connection. - server(boost::asio::io_service& io_service, unsigned short port) - : acceptor_(io_service, - boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)) - { - // Create the data to be sent to each client. - stock s; - s.code = "ABC"; - s.name = "A Big Company"; - s.open_price = 4.56; - s.high_price = 5.12; - s.low_price = 4.33; - s.last_price = 4.98; - s.buy_price = 4.96; - s.buy_quantity = 1000; - s.sell_price = 4.99; - s.sell_quantity = 2000; - stocks_.push_back(s); - s.code = "DEF"; - s.name = "Developer Entertainment Firm"; - s.open_price = 20.24; - s.high_price = 22.88; - s.low_price = 19.50; - s.last_price = 19.76; - s.buy_price = 19.72; - s.buy_quantity = 34000; - s.sell_price = 19.85; - s.sell_quantity = 45000; - stocks_.push_back(s); - - // Start an accept operation for a new connection. - connection_ptr new_conn(new connection(acceptor_.get_io_service())); - acceptor_.async_accept(new_conn->socket(), - boost::bind(&server::handle_accept, this, - boost::asio::placeholders::error, new_conn)); - } - - /// Handle completion of a accept operation. - void handle_accept(const boost::system::error_code& e, connection_ptr conn) - { - if (!e) - { - // Successfully accepted a new connection. Send the list of stocks to the - // client. The connection::async_write() function will automatically - // serialize the data structure for us. - conn->async_write(stocks_, - boost::bind(&server::handle_write, this, - boost::asio::placeholders::error, conn)); - } - - // Start an accept operation for a new connection. - connection_ptr new_conn(new connection(acceptor_.get_io_service())); - acceptor_.async_accept(new_conn->socket(), - boost::bind(&server::handle_accept, this, - boost::asio::placeholders::error, new_conn)); - } - - /// Handle completion of a write operation. - void handle_write(const boost::system::error_code& e, connection_ptr conn) - { - // Nothing to do. The socket will be closed automatically when the last - // reference to the connection object goes away. - } - -private: - /// The acceptor object used to accept incoming socket connections. - boost::asio::ip::tcp::acceptor acceptor_; - - /// The data to be sent to each client. - std::vector<stock> stocks_; -}; - -} // namespace s11n_example - -int main(int argc, char* argv[]) -{ - try - { - // Check command line arguments. - if (argc != 2) - { - std::cerr << "Usage: server <port>" << std::endl; - return 1; - } - unsigned short port = boost::lexical_cast<unsigned short>(argv[1]); - - boost::asio::io_service io_service; - s11n_example::server server(io_service, port); - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << e.what() << std::endl; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/serialization/stock.hpp b/doc/html/boost_asio/example/cpp03/serialization/stock.hpp deleted file mode 100644 index 3993cbfd1e..0000000000 --- a/doc/html/boost_asio/example/cpp03/serialization/stock.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// -// stock.hpp -// ~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 SERIALIZATION_STOCK_HPP -#define SERIALIZATION_STOCK_HPP - -#include <string> - -namespace s11n_example { - -/// Structure to hold information about a single stock. -struct stock -{ - std::string code; - std::string name; - double open_price; - double high_price; - double low_price; - double last_price; - double buy_price; - int buy_quantity; - double sell_price; - int sell_quantity; - - template <typename Archive> - void serialize(Archive& ar, const unsigned int version) - { - ar & code; - ar & name; - ar & open_price; - ar & high_price; - ar & low_price; - ar & last_price; - ar & buy_price; - ar & buy_quantity; - ar & sell_price; - ar & sell_quantity; - } -}; - -} // namespace s11n_example - -#endif // SERIALIZATION_STOCK_HPP diff --git a/doc/html/boost_asio/example/cpp03/services/basic_logger.hpp b/doc/html/boost_asio/example/cpp03/services/basic_logger.hpp deleted file mode 100644 index 075cb92a36..0000000000 --- a/doc/html/boost_asio/example/cpp03/services/basic_logger.hpp +++ /dev/null @@ -1,83 +0,0 @@ -// -// basic_logger.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 SERVICES_BASIC_LOGGER_HPP -#define SERVICES_BASIC_LOGGER_HPP - -#include <boost/asio.hpp> -#include <boost/noncopyable.hpp> -#include <string> - -namespace services { - -/// Class to provide simple logging functionality. Use the services::logger -/// typedef. -template <typename Service> -class basic_logger - : private boost::noncopyable -{ -public: - /// The type of the service that will be used to provide timer operations. - typedef Service service_type; - - /// The native implementation type of the timer. - typedef typename service_type::impl_type impl_type; - - /// Constructor. - /** - * This constructor creates a logger. - * - * @param io_service The io_service object used to locate the logger service. - * - * @param identifier An identifier for this logger. - */ - explicit basic_logger(boost::asio::io_service& io_service, - const std::string& identifier) - : service_(boost::asio::use_service<Service>(io_service)), - impl_(service_.null()) - { - service_.create(impl_, identifier); - } - - /// Destructor. - ~basic_logger() - { - service_.destroy(impl_); - } - - /// Get the io_service associated with the object. - boost::asio::io_service& get_io_service() - { - return service_.get_io_service(); - } - - /// Set the output file for all logger instances. - void use_file(const std::string& file) - { - service_.use_file(impl_, file); - } - - /// Log a message. - void log(const std::string& message) - { - service_.log(impl_, message); - } - -private: - /// The backend service implementation. - service_type& service_; - - /// The underlying native implementation. - impl_type impl_; -}; - -} // namespace services - -#endif // SERVICES_BASIC_LOGGER_HPP diff --git a/doc/html/boost_asio/example/cpp03/services/daytime_client.cpp b/doc/html/boost_asio/example/cpp03/services/daytime_client.cpp deleted file mode 100644 index ff2d4cac09..0000000000 --- a/doc/html/boost_asio/example/cpp03/services/daytime_client.cpp +++ /dev/null @@ -1,85 +0,0 @@ -// -// daytime_client.cpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <boost/asio.hpp> -#include <boost/bind.hpp> -#include <iostream> -#include "logger.hpp" -#include "stream_socket_service.hpp" - -typedef boost::asio::basic_stream_socket<boost::asio::ip::tcp, - services::stream_socket_service<boost::asio::ip::tcp> > debug_stream_socket; - -char read_buffer[1024]; - -void read_handler(const boost::system::error_code& e, - std::size_t bytes_transferred, debug_stream_socket* s) -{ - if (!e) - { - std::cout.write(read_buffer, bytes_transferred); - - s->async_read_some(boost::asio::buffer(read_buffer), - boost::bind(read_handler, boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred, s)); - } -} - -void connect_handler(const boost::system::error_code& e, debug_stream_socket* s) -{ - if (!e) - { - s->async_read_some(boost::asio::buffer(read_buffer), - boost::bind(read_handler, boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred, s)); - } - else - { - std::cerr << e.message() << std::endl; - } -} - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: daytime_client <host>" << std::endl; - return 1; - } - - boost::asio::io_service io_service; - - // Set the name of the file that all logger instances will use. - services::logger logger(io_service, ""); - logger.use_file("log.txt"); - - // Resolve the address corresponding to the given host. - boost::asio::ip::tcp::resolver resolver(io_service); - boost::asio::ip::tcp::resolver::query query(argv[1], "daytime"); - boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); - - // Start an asynchronous connect. - debug_stream_socket socket(io_service); - boost::asio::async_connect(socket, iterator, - boost::bind(connect_handler, - boost::asio::placeholders::error, &socket)); - - // Run the io_service until all operations have finished. - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << e.what() << std::endl; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/services/logger.hpp b/doc/html/boost_asio/example/cpp03/services/logger.hpp deleted file mode 100644 index 4b77b5dd5a..0000000000 --- a/doc/html/boost_asio/example/cpp03/services/logger.hpp +++ /dev/null @@ -1,24 +0,0 @@ -// -// logger.hpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 SERVICES_LOGGER_HPP -#define SERVICES_LOGGER_HPP - -#include "basic_logger.hpp" -#include "logger_service.hpp" - -namespace services { - -/// Typedef for typical logger usage. -typedef basic_logger<logger_service> logger; - -} // namespace services - -#endif // SERVICES_LOGGER_HPP diff --git a/doc/html/boost_asio/example/cpp03/services/logger_service.cpp b/doc/html/boost_asio/example/cpp03/services/logger_service.cpp deleted file mode 100644 index d67876a0af..0000000000 --- a/doc/html/boost_asio/example/cpp03/services/logger_service.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// -// logger_service.cpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "logger_service.hpp" - -namespace services { - -boost::asio::io_service::id logger_service::id; - -} // namespace services diff --git a/doc/html/boost_asio/example/cpp03/services/logger_service.hpp b/doc/html/boost_asio/example/cpp03/services/logger_service.hpp deleted file mode 100644 index 8934291f2b..0000000000 --- a/doc/html/boost_asio/example/cpp03/services/logger_service.hpp +++ /dev/null @@ -1,145 +0,0 @@ -// -// logger_service.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 SERVICES_LOGGER_SERVICE_HPP -#define SERVICES_LOGGER_SERVICE_HPP - -#include <boost/asio.hpp> -#include <boost/thread/thread.hpp> -#include <boost/bind.hpp> -#include <boost/date_time/posix_time/posix_time.hpp> -#include <boost/noncopyable.hpp> -#include <boost/scoped_ptr.hpp> -#include <fstream> -#include <sstream> -#include <string> - -namespace services { - -/// Service implementation for the logger. -class logger_service - : public boost::asio::io_service::service -{ -public: - /// The unique service identifier. - static boost::asio::io_service::id id; - - /// The backend implementation of a logger. - struct logger_impl - { - explicit logger_impl(const std::string& ident) : identifier(ident) {} - std::string identifier; - }; - - /// The type for an implementation of the logger. - typedef logger_impl* impl_type; - - /// Constructor creates a thread to run a private io_service. - logger_service(boost::asio::io_service& io_service) - : boost::asio::io_service::service(io_service), - work_io_service_(), - work_(new boost::asio::io_service::work(work_io_service_)), - work_thread_(new boost::thread( - boost::bind(&boost::asio::io_service::run, &work_io_service_))) - { - } - - /// Destructor shuts down the private io_service. - ~logger_service() - { - /// Indicate that we have finished with the private io_service. Its - /// io_service::run() function will exit once all other work has completed. - work_.reset(); - if (work_thread_) - work_thread_->join(); - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Return a null logger implementation. - impl_type null() const - { - return 0; - } - - /// Create a new logger implementation. - void create(impl_type& impl, const std::string& identifier) - { - impl = new logger_impl(identifier); - } - - /// Destroy a logger implementation. - void destroy(impl_type& impl) - { - delete impl; - impl = null(); - } - - /// Set the output file for the logger. The current implementation sets the - /// output file for all logger instances, and so the impl parameter is not - /// actually needed. It is retained here to illustrate how service functions - /// are typically defined. - void use_file(impl_type& /*impl*/, const std::string& file) - { - // Pass the work of opening the file to the background thread. - work_io_service_.post(boost::bind( - &logger_service::use_file_impl, this, file)); - } - - /// Log a message. - void log(impl_type& impl, const std::string& message) - { - // Format the text to be logged. - std::ostringstream os; - os << impl->identifier << ": " << message; - - // Pass the work of opening the file to the background thread. - work_io_service_.post(boost::bind( - &logger_service::log_impl, this, os.str())); - } - -private: - /// Helper function used to open the output file from within the private - /// io_service's thread. - void use_file_impl(const std::string& file) - { - ofstream_.close(); - ofstream_.clear(); - ofstream_.open(file.c_str()); - } - - /// Helper function used to log a message from within the private io_service's - /// thread. - void log_impl(const std::string& text) - { - ofstream_ << text << std::endl; - } - - /// Private io_service used for performing logging operations. - boost::asio::io_service work_io_service_; - - /// Work for the private io_service to perform. If we do not give the - /// io_service some work to do then the io_service::run() function will exit - /// immediately. - boost::scoped_ptr<boost::asio::io_service::work> work_; - - /// Thread used for running the work io_service's run loop. - boost::scoped_ptr<boost::thread> work_thread_; - - /// The file to which log messages will be written. - std::ofstream ofstream_; -}; - -} // namespace services - -#endif // SERVICES_LOGGER_SERVICE_HPP diff --git a/doc/html/boost_asio/example/cpp03/services/stream_socket_service.hpp b/doc/html/boost_asio/example/cpp03/services/stream_socket_service.hpp deleted file mode 100644 index 5d22c8cc5a..0000000000 --- a/doc/html/boost_asio/example/cpp03/services/stream_socket_service.hpp +++ /dev/null @@ -1,351 +0,0 @@ -// -// stream_socket_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 SERVICES_STREAM_SOCKET_SERVICE_HPP -#define SERVICES_STREAM_SOCKET_SERVICE_HPP - -#include <boost/asio.hpp> -#include <boost/noncopyable.hpp> -#include <boost/lexical_cast.hpp> -#include "logger.hpp" - -namespace services { - -/// Debugging stream socket service that wraps the normal stream socket service. -template <typename Protocol> -class stream_socket_service - : public boost::asio::io_service::service -{ -private: - /// The type of the wrapped stream socket service. - typedef boost::asio::stream_socket_service<Protocol> service_impl_type; - -public: - /// The unique service identifier. - static boost::asio::io_service::id id; - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - /// The implementation type of a stream socket. - typedef typename service_impl_type::implementation_type implementation_type; - - /// The native type of a stream socket. - typedef typename service_impl_type::native_handle_type native_handle_type; - - /// Construct a new stream socket service for the specified io_service. - explicit stream_socket_service(boost::asio::io_service& io_service) - : boost::asio::io_service::service(io_service), - service_impl_(boost::asio::use_service<service_impl_type>(io_service)), - logger_(io_service, "stream_socket") - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Construct a new stream socket implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a stream socket implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Open a new stream socket implementation. - boost::system::error_code open(implementation_type& impl, - const protocol_type& protocol, boost::system::error_code& ec) - { - logger_.log("Opening new socket"); - return service_impl_.open(impl, protocol, ec); - } - - /// Open a stream socket from an existing native socket. - boost::system::error_code assign(implementation_type& impl, - const protocol_type& protocol, const native_handle_type& native_socket, - boost::system::error_code& ec) - { - logger_.log("Assigning from a native socket"); - return service_impl_.assign(impl, protocol, native_socket, ec); - } - - /// Determine whether the socket is open. - bool is_open(const implementation_type& impl) const - { - logger_.log("Checking if socket is open"); - return service_impl_.is_open(impl); - } - - /// Close a stream socket implementation. - boost::system::error_code close(implementation_type& impl, - boost::system::error_code& ec) - { - logger_.log("Closing socket"); - return service_impl_.close(impl, ec); - } - - /// Determine whether the socket is at the out-of-band data mark. - bool at_mark(const implementation_type& impl, - boost::system::error_code& ec) const - { - logger_.log("Checking if socket is at out-of-band data mark"); - return service_impl_.at_mark(impl, ec); - } - - /// Determine the number of bytes available for reading. - std::size_t available(const implementation_type& impl, - boost::system::error_code& ec) const - { - logger_.log("Determining number of bytes available for reading"); - return service_impl_.available(impl, ec); - } - - /// Bind the stream socket to the specified local endpoint. - boost::system::error_code bind(implementation_type& impl, - const endpoint_type& endpoint, boost::system::error_code& ec) - { - logger_.log("Binding socket"); - return service_impl_.bind(impl, endpoint, ec); - } - - /// Connect the stream socket to the specified endpoint. - boost::system::error_code connect(implementation_type& impl, - const endpoint_type& peer_endpoint, boost::system::error_code& ec) - { - logger_.log("Connecting socket to " + - boost::lexical_cast<std::string>(peer_endpoint)); - return service_impl_.connect(impl, peer_endpoint, ec); - } - - /// Handler to wrap asynchronous connect completion. - template <typename Handler> - class connect_handler - { - public: - connect_handler(Handler h, logger& l) - : handler_(h), - logger_(l) - { - } - - void operator()(const boost::system::error_code& e) - { - if (e) - { - std::string msg = "Asynchronous connect failed: "; - msg += e.message(); - logger_.log(msg); - } - else - { - logger_.log("Asynchronous connect succeeded"); - } - - handler_(e); - } - - private: - Handler handler_; - logger& logger_; - }; - - /// Start an asynchronous connect. - template <typename Handler> - void async_connect(implementation_type& impl, - const endpoint_type& peer_endpoint, Handler handler) - { - logger_.log("Starting asynchronous connect to " + - boost::lexical_cast<std::string>(peer_endpoint)); - service_impl_.async_connect(impl, peer_endpoint, - connect_handler<Handler>(handler, logger_)); - } - - /// Set a socket option. - template <typename Option> - boost::system::error_code set_option(implementation_type& impl, - const Option& option, boost::system::error_code& ec) - { - logger_.log("Setting socket option"); - return service_impl_.set_option(impl, option, ec); - } - - /// Get a socket option. - template <typename Option> - boost::system::error_code get_option(const implementation_type& impl, - Option& option, boost::system::error_code& ec) const - { - logger_.log("Getting socket option"); - return service_impl_.get_option(impl, option, ec); - } - - /// Perform an IO control command on the socket. - template <typename IO_Control_Command> - boost::system::error_code io_control(implementation_type& impl, - IO_Control_Command& command, boost::system::error_code& ec) - { - logger_.log("Performing IO control command on socket"); - return service_impl_.io_control(impl, command, ec); - } - - /// Get the local endpoint. - endpoint_type local_endpoint(const implementation_type& impl, - boost::system::error_code& ec) const - { - logger_.log("Getting socket's local endpoint"); - return service_impl_.local_endpoint(impl, ec); - } - - /// Get the remote endpoint. - endpoint_type remote_endpoint(const implementation_type& impl, - boost::system::error_code& ec) const - { - logger_.log("Getting socket's remote endpoint"); - return service_impl_.remote_endpoint(impl, ec); - } - - /// Disable sends or receives on the socket. - boost::system::error_code shutdown(implementation_type& impl, - boost::asio::socket_base::shutdown_type what, - boost::system::error_code& ec) - { - logger_.log("Shutting down socket"); - return service_impl_.shutdown(impl, what, ec); - } - - /// Send the given data to the peer. - template <typename Const_Buffers> - std::size_t send(implementation_type& impl, const Const_Buffers& buffers, - boost::asio::socket_base::message_flags flags, - boost::system::error_code& ec) - { - logger_.log("Sending data on socket"); - return service_impl_.send(impl, buffers, flags, ec); - } - - /// Handler to wrap asynchronous send completion. - template <typename Handler> - class send_handler - { - public: - send_handler(Handler h, logger& l) - : handler_(h), - logger_(l) - { - } - - void operator()(const boost::system::error_code& e, - std::size_t bytes_transferred) - { - if (e) - { - std::string msg = "Asynchronous send failed: "; - msg += e.message(); - logger_.log(msg); - } - else - { - logger_.log("Asynchronous send succeeded"); - } - - handler_(e, bytes_transferred); - } - - private: - Handler handler_; - logger& logger_; - }; - - /// Start an asynchronous send. - template <typename Const_Buffers, typename Handler> - void async_send(implementation_type& impl, const Const_Buffers& buffers, - boost::asio::socket_base::message_flags flags, Handler handler) - { - logger_.log("Starting asynchronous send"); - service_impl_.async_send(impl, buffers, flags, - send_handler<Handler>(handler, logger_)); - } - - /// Receive some data from the peer. - template <typename Mutable_Buffers> - std::size_t receive(implementation_type& impl, - const Mutable_Buffers& buffers, - boost::asio::socket_base::message_flags flags, - boost::system::error_code& ec) - { - logger_.log("Receiving data on socket"); - return service_impl_.receive(impl, buffers, flags, ec); - } - - /// Handler to wrap asynchronous receive completion. - template <typename Handler> - class receive_handler - { - public: - receive_handler(Handler h, logger& l) - : handler_(h), - logger_(l) - { - } - - void operator()(const boost::system::error_code& e, - std::size_t bytes_transferred) - { - if (e) - { - std::string msg = "Asynchronous receive failed: "; - msg += e.message(); - logger_.log(msg); - } - else - { - logger_.log("Asynchronous receive succeeded"); - } - - handler_(e, bytes_transferred); - } - - private: - Handler handler_; - logger& logger_; - }; - - /// Start an asynchronous receive. - template <typename Mutable_Buffers, typename Handler> - void async_receive(implementation_type& impl, const Mutable_Buffers& buffers, - boost::asio::socket_base::message_flags flags, Handler handler) - { - logger_.log("Starting asynchronous receive"); - service_impl_.async_receive(impl, buffers, flags, - receive_handler<Handler>(handler, logger_)); - } - -private: - /// The wrapped stream socket service. - service_impl_type& service_impl_; - - /// The logger used for writing debug messages. - mutable logger logger_; -}; - -template <typename Protocol> -boost::asio::io_service::id stream_socket_service<Protocol>::id; - -} // namespace services - -#endif // SERVICES_STREAM_SOCKET_SERVICE_HPP diff --git a/doc/html/boost_asio/example/cpp03/socks4/socks4.hpp b/doc/html/boost_asio/example/cpp03/socks4/socks4.hpp deleted file mode 100644 index 8b001f74df..0000000000 --- a/doc/html/boost_asio/example/cpp03/socks4/socks4.hpp +++ /dev/null @@ -1,144 +0,0 @@ -// -// socks4.hpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 SOCKS4_HPP -#define SOCKS4_HPP - -#include <string> -#include <boost/asio.hpp> -#include <boost/array.hpp> - -namespace socks4 { - -const unsigned char version = 0x04; - -class request -{ -public: - enum command_type - { - connect = 0x01, - bind = 0x02 - }; - - request(command_type cmd, const boost::asio::ip::tcp::endpoint& endpoint, - const std::string& user_id) - : version_(version), - command_(cmd), - user_id_(user_id), - null_byte_(0) - { - // Only IPv4 is supported by the SOCKS 4 protocol. - if (endpoint.protocol() != boost::asio::ip::tcp::v4()) - { - throw boost::system::system_error( - boost::asio::error::address_family_not_supported); - } - - // Convert port number to network byte order. - unsigned short port = endpoint.port(); - port_high_byte_ = (port >> 8) & 0xff; - port_low_byte_ = port & 0xff; - - // Save IP address in network byte order. - address_ = endpoint.address().to_v4().to_bytes(); - } - - boost::array<boost::asio::const_buffer, 7> buffers() const - { - boost::array<boost::asio::const_buffer, 7> bufs = - { - { - boost::asio::buffer(&version_, 1), - boost::asio::buffer(&command_, 1), - boost::asio::buffer(&port_high_byte_, 1), - boost::asio::buffer(&port_low_byte_, 1), - boost::asio::buffer(address_), - boost::asio::buffer(user_id_), - boost::asio::buffer(&null_byte_, 1) - } - }; - return bufs; - } - -private: - unsigned char version_; - unsigned char command_; - unsigned char port_high_byte_; - unsigned char port_low_byte_; - boost::asio::ip::address_v4::bytes_type address_; - std::string user_id_; - unsigned char null_byte_; -}; - -class reply -{ -public: - enum status_type - { - request_granted = 0x5a, - request_failed = 0x5b, - request_failed_no_identd = 0x5c, - request_failed_bad_user_id = 0x5d - }; - - reply() - : null_byte_(0), - status_() - { - } - - boost::array<boost::asio::mutable_buffer, 5> buffers() - { - boost::array<boost::asio::mutable_buffer, 5> bufs = - { - { - boost::asio::buffer(&null_byte_, 1), - boost::asio::buffer(&status_, 1), - boost::asio::buffer(&port_high_byte_, 1), - boost::asio::buffer(&port_low_byte_, 1), - boost::asio::buffer(address_) - } - }; - return bufs; - } - - bool success() const - { - return null_byte_ == 0 && status_ == request_granted; - } - - unsigned char status() const - { - return status_; - } - - boost::asio::ip::tcp::endpoint endpoint() const - { - unsigned short port = port_high_byte_; - port = (port << 8) & 0xff00; - port = port | port_low_byte_; - - boost::asio::ip::address_v4 address(address_); - - return boost::asio::ip::tcp::endpoint(address, port); - } - -private: - unsigned char null_byte_; - unsigned char status_; - unsigned char port_high_byte_; - unsigned char port_low_byte_; - boost::asio::ip::address_v4::bytes_type address_; -}; - -} // namespace socks4 - -#endif // SOCKS4_HPP diff --git a/doc/html/boost_asio/example/cpp03/socks4/sync_client.cpp b/doc/html/boost_asio/example/cpp03/socks4/sync_client.cpp deleted file mode 100644 index d2e9bf929a..0000000000 --- a/doc/html/boost_asio/example/cpp03/socks4/sync_client.cpp +++ /dev/null @@ -1,95 +0,0 @@ -// -// sync_client.cpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <iostream> -#include <iomanip> -#include <ostream> -#include <string> -#include <boost/asio.hpp> -#include <boost/array.hpp> -#include "socks4.hpp" - -using boost::asio::ip::tcp; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 4) - { - std::cout << "Usage: sync_client <socks4server> <socks4port> <user>\n"; - std::cout << "Examples:\n"; - std::cout << " sync_client 127.0.0.1 1080 chris\n"; - std::cout << " sync_client localhost socks chris\n"; - return 1; - } - - boost::asio::io_service io_service; - - // Get a list of endpoints corresponding to the SOCKS 4 server name. - tcp::resolver resolver(io_service); - tcp::resolver::query socks_query(argv[1], argv[2]); - tcp::resolver::iterator endpoint_iterator = resolver.resolve(socks_query); - - // Try each endpoint until we successfully establish a connection to the - // SOCKS 4 server. - tcp::socket socket(io_service); - boost::asio::connect(socket, endpoint_iterator); - - // Get an endpoint for the Boost website. This will be passed to the SOCKS - // 4 server. Explicitly specify IPv4 since SOCKS 4 does not support IPv6. - tcp::resolver::query http_query(tcp::v4(), "www.boost.org", "http"); - tcp::endpoint http_endpoint = *resolver.resolve(http_query); - - // Send the request to the SOCKS 4 server. - socks4::request socks_request( - socks4::request::connect, http_endpoint, argv[3]); - boost::asio::write(socket, socks_request.buffers()); - - // Receive a response from the SOCKS 4 server. - socks4::reply socks_reply; - boost::asio::read(socket, socks_reply.buffers()); - - // Check whether we successfully negotiated with the SOCKS 4 server. - if (!socks_reply.success()) - { - std::cout << "Connection failed.\n"; - std::cout << "status = 0x" << std::hex << socks_reply.status(); - return 1; - } - - // Form the HTTP request. We specify the "Connection: close" header so that - // the server will close the socket after transmitting the response. This - // will allow us to treat all data up until the EOF as the response. - std::string request = - "GET / HTTP/1.0\r\n" - "Host: www.boost.org\r\n" - "Accept: */*\r\n" - "Connection: close\r\n\r\n"; - - // Send the HTTP request. - boost::asio::write(socket, boost::asio::buffer(request)); - - // Read until EOF, writing data to output as we go. - boost::array<char, 512> response; - boost::system::error_code error; - while (std::size_t s = socket.read_some( - boost::asio::buffer(response), error)) - std::cout.write(response.data(), s); - if (error != boost::asio::error::eof) - throw boost::system::system_error(error); - } - catch (std::exception& e) - { - std::cout << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/spawn/echo_server.cpp b/doc/html/boost_asio/example/cpp03/spawn/echo_server.cpp deleted file mode 100644 index e703fbb783..0000000000 --- a/doc/html/boost_asio/example/cpp03/spawn/echo_server.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// -// echo_server.cpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <boost/asio/deadline_timer.hpp> -#include <boost/asio/io_service.hpp> -#include <boost/asio/ip/tcp.hpp> -#include <boost/asio/spawn.hpp> -#include <boost/asio/write.hpp> -#include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> -#include <iostream> - -using boost::asio::ip::tcp; - -class session : public boost::enable_shared_from_this<session> -{ -public: - explicit session(boost::asio::io_service& io_service) - : strand_(io_service), - socket_(io_service), - timer_(io_service) - { - } - - tcp::socket& socket() - { - return socket_; - } - - void go() - { - boost::asio::spawn(strand_, - boost::bind(&session::echo, - shared_from_this(), _1)); - boost::asio::spawn(strand_, - boost::bind(&session::timeout, - shared_from_this(), _1)); - } - -private: - void echo(boost::asio::yield_context yield) - { - try - { - char data[128]; - for (;;) - { - timer_.expires_from_now(boost::posix_time::seconds(10)); - std::size_t n = socket_.async_read_some(boost::asio::buffer(data), yield); - boost::asio::async_write(socket_, boost::asio::buffer(data, n), yield); - } - } - catch (std::exception& e) - { - socket_.close(); - timer_.cancel(); - } - } - - void timeout(boost::asio::yield_context yield) - { - while (socket_.is_open()) - { - boost::system::error_code ignored_ec; - timer_.async_wait(yield[ignored_ec]); - if (timer_.expires_from_now() <= boost::posix_time::seconds(0)) - socket_.close(); - } - } - - boost::asio::io_service::strand strand_; - tcp::socket socket_; - boost::asio::deadline_timer timer_; -}; - -void do_accept(boost::asio::io_service& io_service, - unsigned short port, boost::asio::yield_context yield) -{ - tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), port)); - - for (;;) - { - boost::system::error_code ec; - boost::shared_ptr<session> new_session(new session(io_service)); - acceptor.async_accept(new_session->socket(), yield[ec]); - if (!ec) new_session->go(); - } -} - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: echo_server <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - boost::asio::spawn(io_service, - boost::bind(do_accept, - boost::ref(io_service), atoi(argv[1]), _1)); - - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/ssl/client.cpp b/doc/html/boost_asio/example/cpp03/ssl/client.cpp deleted file mode 100644 index 173c9b6f83..0000000000 --- a/doc/html/boost_asio/example/cpp03/ssl/client.cpp +++ /dev/null @@ -1,156 +0,0 @@ -// -// client.cpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstdlib> -#include <iostream> -#include <boost/bind.hpp> -#include <boost/asio.hpp> -#include <boost/asio/ssl.hpp> - -enum { max_length = 1024 }; - -class client -{ -public: - client(boost::asio::io_service& io_service, - boost::asio::ssl::context& context, - boost::asio::ip::tcp::resolver::iterator endpoint_iterator) - : socket_(io_service, context) - { - socket_.set_verify_mode(boost::asio::ssl::verify_peer); - socket_.set_verify_callback( - boost::bind(&client::verify_certificate, this, _1, _2)); - - boost::asio::async_connect(socket_.lowest_layer(), endpoint_iterator, - boost::bind(&client::handle_connect, this, - boost::asio::placeholders::error)); - } - - bool verify_certificate(bool preverified, - boost::asio::ssl::verify_context& ctx) - { - // The verify callback can be used to check whether the certificate that is - // being presented is valid for the peer. For example, RFC 2818 describes - // the steps involved in doing this for HTTPS. Consult the OpenSSL - // documentation for more details. Note that the callback is called once - // for each certificate in the certificate chain, starting from the root - // certificate authority. - - // In this example we will simply print the certificate's subject name. - char subject_name[256]; - X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle()); - X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256); - std::cout << "Verifying " << subject_name << "\n"; - - return preverified; - } - - void handle_connect(const boost::system::error_code& error) - { - if (!error) - { - socket_.async_handshake(boost::asio::ssl::stream_base::client, - boost::bind(&client::handle_handshake, this, - boost::asio::placeholders::error)); - } - else - { - std::cout << "Connect failed: " << error.message() << "\n"; - } - } - - void handle_handshake(const boost::system::error_code& error) - { - if (!error) - { - std::cout << "Enter message: "; - std::cin.getline(request_, max_length); - size_t request_length = strlen(request_); - - boost::asio::async_write(socket_, - boost::asio::buffer(request_, request_length), - boost::bind(&client::handle_write, this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - else - { - std::cout << "Handshake failed: " << error.message() << "\n"; - } - } - - void handle_write(const boost::system::error_code& error, - size_t bytes_transferred) - { - if (!error) - { - boost::asio::async_read(socket_, - boost::asio::buffer(reply_, bytes_transferred), - boost::bind(&client::handle_read, this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - else - { - std::cout << "Write failed: " << error.message() << "\n"; - } - } - - void handle_read(const boost::system::error_code& error, - size_t bytes_transferred) - { - if (!error) - { - std::cout << "Reply: "; - std::cout.write(reply_, bytes_transferred); - std::cout << "\n"; - } - else - { - std::cout << "Read failed: " << error.message() << "\n"; - } - } - -private: - boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_; - char request_[max_length]; - char reply_[max_length]; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 3) - { - std::cerr << "Usage: client <host> <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - boost::asio::ip::tcp::resolver resolver(io_service); - boost::asio::ip::tcp::resolver::query query(argv[1], argv[2]); - boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); - - boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); - ctx.load_verify_file("ca.pem"); - - client c(io_service, ctx, iterator); - - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/ssl/server.cpp b/doc/html/boost_asio/example/cpp03/ssl/server.cpp deleted file mode 100644 index 9c39de5a97..0000000000 --- a/doc/html/boost_asio/example/cpp03/ssl/server.cpp +++ /dev/null @@ -1,170 +0,0 @@ -// -// server.cpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstdlib> -#include <iostream> -#include <boost/bind.hpp> -#include <boost/asio.hpp> -#include <boost/asio/ssl.hpp> - -typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket; - -class session -{ -public: - session(boost::asio::io_service& io_service, - boost::asio::ssl::context& context) - : socket_(io_service, context) - { - } - - ssl_socket::lowest_layer_type& socket() - { - return socket_.lowest_layer(); - } - - void start() - { - socket_.async_handshake(boost::asio::ssl::stream_base::server, - boost::bind(&session::handle_handshake, this, - boost::asio::placeholders::error)); - } - - void handle_handshake(const boost::system::error_code& error) - { - if (!error) - { - socket_.async_read_some(boost::asio::buffer(data_, max_length), - boost::bind(&session::handle_read, this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - else - { - delete this; - } - } - - void handle_read(const boost::system::error_code& error, - size_t bytes_transferred) - { - if (!error) - { - boost::asio::async_write(socket_, - boost::asio::buffer(data_, bytes_transferred), - boost::bind(&session::handle_write, this, - boost::asio::placeholders::error)); - } - else - { - delete this; - } - } - - void handle_write(const boost::system::error_code& error) - { - if (!error) - { - socket_.async_read_some(boost::asio::buffer(data_, max_length), - boost::bind(&session::handle_read, this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - else - { - delete this; - } - } - -private: - ssl_socket socket_; - enum { max_length = 1024 }; - char data_[max_length]; -}; - -class server -{ -public: - server(boost::asio::io_service& io_service, unsigned short port) - : io_service_(io_service), - acceptor_(io_service, - boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)), - context_(boost::asio::ssl::context::sslv23) - { - context_.set_options( - boost::asio::ssl::context::default_workarounds - | boost::asio::ssl::context::no_sslv2 - | boost::asio::ssl::context::single_dh_use); - context_.set_password_callback(boost::bind(&server::get_password, this)); - context_.use_certificate_chain_file("server.pem"); - context_.use_private_key_file("server.pem", boost::asio::ssl::context::pem); - context_.use_tmp_dh_file("dh2048.pem"); - - start_accept(); - } - - std::string get_password() const - { - return "test"; - } - - void start_accept() - { - session* new_session = new session(io_service_, context_); - acceptor_.async_accept(new_session->socket(), - boost::bind(&server::handle_accept, this, new_session, - boost::asio::placeholders::error)); - } - - void handle_accept(session* new_session, - const boost::system::error_code& error) - { - if (!error) - { - new_session->start(); - } - else - { - delete new_session; - } - - start_accept(); - } - -private: - boost::asio::io_service& io_service_; - boost::asio::ip::tcp::acceptor acceptor_; - boost::asio::ssl::context context_; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: server <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - using namespace std; // For atoi. - server s(io_service, atoi(argv[1])); - - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/timeouts/async_tcp_client.cpp b/doc/html/boost_asio/example/cpp03/timeouts/async_tcp_client.cpp deleted file mode 100644 index e42daf6928..0000000000 --- a/doc/html/boost_asio/example/cpp03/timeouts/async_tcp_client.cpp +++ /dev/null @@ -1,306 +0,0 @@ -// -// async_tcp_client.cpp -// ~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <boost/asio/deadline_timer.hpp> -#include <boost/asio/io_service.hpp> -#include <boost/asio/ip/tcp.hpp> -#include <boost/asio/read_until.hpp> -#include <boost/asio/streambuf.hpp> -#include <boost/asio/write.hpp> -#include <boost/bind.hpp> -#include <iostream> - -using boost::asio::deadline_timer; -using boost::asio::ip::tcp; - -// -// This class manages socket timeouts by applying the concept of a deadline. -// Some asynchronous operations are given deadlines by which they must complete. -// Deadlines are enforced by an "actor" that persists for the lifetime of the -// client object: -// -// +----------------+ -// | | -// | check_deadline |<---+ -// | | | -// +----------------+ | async_wait() -// | | -// +---------+ -// -// If the deadline actor determines that the deadline has expired, the socket -// is closed and any outstanding operations are consequently cancelled. -// -// Connection establishment involves trying each endpoint in turn until a -// connection is successful, or the available endpoints are exhausted. If the -// deadline actor closes the socket, the connect actor is woken up and moves to -// the next endpoint. -// -// +---------------+ -// | | -// | start_connect |<---+ -// | | | -// +---------------+ | -// | | -// async_- | +----------------+ -// connect() | | | -// +--->| handle_connect | -// | | -// +----------------+ -// : -// Once a connection is : -// made, the connect : -// actor forks in two - : -// : -// an actor for reading : and an actor for -// inbound messages: : sending heartbeats: -// : -// +------------+ : +-------------+ -// | |<- - - - -+- - - - ->| | -// | start_read | | start_write |<---+ -// | |<---+ | | | -// +------------+ | +-------------+ | async_wait() -// | | | | -// async_- | +-------------+ async_- | +--------------+ -// read_- | | | write() | | | -// until() +--->| handle_read | +--->| handle_write | -// | | | | -// +-------------+ +--------------+ -// -// The input actor reads messages from the socket, where messages are delimited -// by the newline character. The deadline for a complete message is 30 seconds. -// -// The heartbeat actor sends a heartbeat (a message that consists of a single -// newline character) every 10 seconds. In this example, no deadline is applied -// message sending. -// -class client -{ -public: - client(boost::asio::io_service& io_service) - : stopped_(false), - socket_(io_service), - deadline_(io_service), - heartbeat_timer_(io_service) - { - } - - // Called by the user of the client class to initiate the connection process. - // The endpoint iterator will have been obtained using a tcp::resolver. - void start(tcp::resolver::iterator endpoint_iter) - { - // Start the connect actor. - start_connect(endpoint_iter); - - // Start the deadline actor. You will note that we're not setting any - // particular deadline here. Instead, the connect and input actors will - // update the deadline prior to each asynchronous operation. - deadline_.async_wait(boost::bind(&client::check_deadline, this)); - } - - // This function terminates all the actors to shut down the connection. It - // may be called by the user of the client class, or by the class itself in - // response to graceful termination or an unrecoverable error. - void stop() - { - stopped_ = true; - boost::system::error_code ignored_ec; - socket_.close(ignored_ec); - deadline_.cancel(); - heartbeat_timer_.cancel(); - } - -private: - void start_connect(tcp::resolver::iterator endpoint_iter) - { - if (endpoint_iter != tcp::resolver::iterator()) - { - std::cout << "Trying " << endpoint_iter->endpoint() << "...\n"; - - // Set a deadline for the connect operation. - deadline_.expires_from_now(boost::posix_time::seconds(60)); - - // Start the asynchronous connect operation. - socket_.async_connect(endpoint_iter->endpoint(), - boost::bind(&client::handle_connect, - this, _1, endpoint_iter)); - } - else - { - // There are no more endpoints to try. Shut down the client. - stop(); - } - } - - void handle_connect(const boost::system::error_code& ec, - tcp::resolver::iterator endpoint_iter) - { - if (stopped_) - return; - - // The async_connect() function automatically opens the socket at the start - // of the asynchronous operation. If the socket is closed at this time then - // the timeout handler must have run first. - if (!socket_.is_open()) - { - std::cout << "Connect timed out\n"; - - // Try the next available endpoint. - start_connect(++endpoint_iter); - } - - // Check if the connect operation failed before the deadline expired. - else if (ec) - { - std::cout << "Connect error: " << ec.message() << "\n"; - - // We need to close the socket used in the previous connection attempt - // before starting a new one. - socket_.close(); - - // Try the next available endpoint. - start_connect(++endpoint_iter); - } - - // Otherwise we have successfully established a connection. - else - { - std::cout << "Connected to " << endpoint_iter->endpoint() << "\n"; - - // Start the input actor. - start_read(); - - // Start the heartbeat actor. - start_write(); - } - } - - void start_read() - { - // Set a deadline for the read operation. - deadline_.expires_from_now(boost::posix_time::seconds(30)); - - // Start an asynchronous operation to read a newline-delimited message. - boost::asio::async_read_until(socket_, input_buffer_, '\n', - boost::bind(&client::handle_read, this, _1)); - } - - void handle_read(const boost::system::error_code& ec) - { - if (stopped_) - return; - - if (!ec) - { - // Extract the newline-delimited message from the buffer. - std::string line; - std::istream is(&input_buffer_); - std::getline(is, line); - - // Empty messages are heartbeats and so ignored. - if (!line.empty()) - { - std::cout << "Received: " << line << "\n"; - } - - start_read(); - } - else - { - std::cout << "Error on receive: " << ec.message() << "\n"; - - stop(); - } - } - - void start_write() - { - if (stopped_) - return; - - // Start an asynchronous operation to send a heartbeat message. - boost::asio::async_write(socket_, boost::asio::buffer("\n", 1), - boost::bind(&client::handle_write, this, _1)); - } - - void handle_write(const boost::system::error_code& ec) - { - if (stopped_) - return; - - if (!ec) - { - // Wait 10 seconds before sending the next heartbeat. - heartbeat_timer_.expires_from_now(boost::posix_time::seconds(10)); - heartbeat_timer_.async_wait(boost::bind(&client::start_write, this)); - } - else - { - std::cout << "Error on heartbeat: " << ec.message() << "\n"; - - stop(); - } - } - - void check_deadline() - { - if (stopped_) - return; - - // Check whether the deadline has passed. We compare the deadline against - // the current time since a new asynchronous operation may have moved the - // deadline before this actor had a chance to run. - if (deadline_.expires_at() <= deadline_timer::traits_type::now()) - { - // The deadline has passed. The socket is closed so that any outstanding - // asynchronous operations are cancelled. - socket_.close(); - - // There is no longer an active deadline. The expiry is set to positive - // infinity so that the actor takes no action until a new deadline is set. - deadline_.expires_at(boost::posix_time::pos_infin); - } - - // Put the actor back to sleep. - deadline_.async_wait(boost::bind(&client::check_deadline, this)); - } - -private: - bool stopped_; - tcp::socket socket_; - boost::asio::streambuf input_buffer_; - deadline_timer deadline_; - deadline_timer heartbeat_timer_; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 3) - { - std::cerr << "Usage: client <host> <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - tcp::resolver r(io_service); - client c(io_service); - - c.start(r.resolve(tcp::resolver::query(argv[1], argv[2]))); - - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/timeouts/blocking_tcp_client.cpp b/doc/html/boost_asio/example/cpp03/timeouts/blocking_tcp_client.cpp deleted file mode 100644 index 2ffb3a1d7f..0000000000 --- a/doc/html/boost_asio/example/cpp03/timeouts/blocking_tcp_client.cpp +++ /dev/null @@ -1,241 +0,0 @@ -// -// blocking_tcp_client.cpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <boost/asio/connect.hpp> -#include <boost/asio/deadline_timer.hpp> -#include <boost/asio/io_service.hpp> -#include <boost/asio/ip/tcp.hpp> -#include <boost/asio/read_until.hpp> -#include <boost/asio/streambuf.hpp> -#include <boost/system/system_error.hpp> -#include <boost/asio/write.hpp> -#include <cstdlib> -#include <iostream> -#include <string> -#include <boost/lambda/bind.hpp> -#include <boost/lambda/lambda.hpp> - -using boost::asio::deadline_timer; -using boost::asio::ip::tcp; -using boost::lambda::bind; -using boost::lambda::var; -using boost::lambda::_1; - -//---------------------------------------------------------------------- - -// -// This class manages socket timeouts by applying the concept of a deadline. -// Each asynchronous operation is given a deadline by which it must complete. -// Deadlines are enforced by an "actor" that persists for the lifetime of the -// client object: -// -// +----------------+ -// | | -// | check_deadline |<---+ -// | | | -// +----------------+ | async_wait() -// | | -// +---------+ -// -// If the actor determines that the deadline has expired, the socket is closed -// and any outstanding operations are consequently cancelled. The socket -// operations themselves use boost::lambda function objects as completion -// handlers. For a given socket operation, the client object runs the -// io_service to block thread execution until the actor completes. -// -class client -{ -public: - client() - : socket_(io_service_), - deadline_(io_service_) - { - // No deadline is required until the first socket operation is started. We - // set the deadline to positive infinity so that the actor takes no action - // until a specific deadline is set. - deadline_.expires_at(boost::posix_time::pos_infin); - - // Start the persistent actor that checks for deadline expiry. - check_deadline(); - } - - void connect(const std::string& host, const std::string& service, - boost::posix_time::time_duration timeout) - { - // Resolve the host name and service to a list of endpoints. - tcp::resolver::query query(host, service); - tcp::resolver::iterator iter = tcp::resolver(io_service_).resolve(query); - - // Set a deadline for the asynchronous operation. As a host name may - // resolve to multiple endpoints, this function uses the composed operation - // async_connect. The deadline applies to the entire operation, rather than - // individual connection attempts. - deadline_.expires_from_now(timeout); - - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - boost::system::error_code ec = boost::asio::error::would_block; - - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - boost::asio::async_connect(socket_, iter, var(ec) = _1); - - // Block until the asynchronous operation has completed. - do io_service_.run_one(); while (ec == boost::asio::error::would_block); - - // Determine whether a connection was successfully established. The - // deadline actor may have had a chance to run and close our socket, even - // though the connect operation notionally succeeded. Therefore we must - // check whether the socket is still open before deciding if we succeeded - // or failed. - if (ec || !socket_.is_open()) - throw boost::system::system_error( - ec ? ec : boost::asio::error::operation_aborted); - } - - std::string read_line(boost::posix_time::time_duration timeout) - { - // Set a deadline for the asynchronous operation. Since this function uses - // a composed operation (async_read_until), the deadline applies to the - // entire operation, rather than individual reads from the socket. - deadline_.expires_from_now(timeout); - - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - boost::system::error_code ec = boost::asio::error::would_block; - - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - boost::asio::async_read_until(socket_, input_buffer_, '\n', var(ec) = _1); - - // Block until the asynchronous operation has completed. - do io_service_.run_one(); while (ec == boost::asio::error::would_block); - - if (ec) - throw boost::system::system_error(ec); - - std::string line; - std::istream is(&input_buffer_); - std::getline(is, line); - return line; - } - - void write_line(const std::string& line, - boost::posix_time::time_duration timeout) - { - std::string data = line + "\n"; - - // Set a deadline for the asynchronous operation. Since this function uses - // a composed operation (async_write), the deadline applies to the entire - // operation, rather than individual writes to the socket. - deadline_.expires_from_now(timeout); - - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - boost::system::error_code ec = boost::asio::error::would_block; - - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - boost::asio::async_write(socket_, boost::asio::buffer(data), var(ec) = _1); - - // Block until the asynchronous operation has completed. - do io_service_.run_one(); while (ec == boost::asio::error::would_block); - - if (ec) - throw boost::system::system_error(ec); - } - -private: - void check_deadline() - { - // Check whether the deadline has passed. We compare the deadline against - // the current time since a new asynchronous operation may have moved the - // deadline before this actor had a chance to run. - if (deadline_.expires_at() <= deadline_timer::traits_type::now()) - { - // The deadline has passed. The socket is closed so that any outstanding - // asynchronous operations are cancelled. This allows the blocked - // connect(), read_line() or write_line() functions to return. - boost::system::error_code ignored_ec; - socket_.close(ignored_ec); - - // There is no longer an active deadline. The expiry is set to positive - // infinity so that the actor takes no action until a new deadline is set. - deadline_.expires_at(boost::posix_time::pos_infin); - } - - // Put the actor back to sleep. - deadline_.async_wait(bind(&client::check_deadline, this)); - } - - boost::asio::io_service io_service_; - tcp::socket socket_; - deadline_timer deadline_; - boost::asio::streambuf input_buffer_; -}; - -//---------------------------------------------------------------------- - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 4) - { - std::cerr << "Usage: blocking_tcp <host> <port> <message>\n"; - return 1; - } - - client c; - c.connect(argv[1], argv[2], boost::posix_time::seconds(10)); - - boost::posix_time::ptime time_sent = - boost::posix_time::microsec_clock::universal_time(); - - c.write_line(argv[3], boost::posix_time::seconds(10)); - - for (;;) - { - std::string line = c.read_line(boost::posix_time::seconds(10)); - - // Keep going until we get back the line that was sent. - if (line == argv[3]) - break; - } - - boost::posix_time::ptime time_received = - boost::posix_time::microsec_clock::universal_time(); - - std::cout << "Round trip time: "; - std::cout << (time_received - time_sent).total_microseconds(); - std::cout << " microseconds\n"; - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/timeouts/blocking_udp_client.cpp b/doc/html/boost_asio/example/cpp03/timeouts/blocking_udp_client.cpp deleted file mode 100644 index 16b86e7423..0000000000 --- a/doc/html/boost_asio/example/cpp03/timeouts/blocking_udp_client.cpp +++ /dev/null @@ -1,182 +0,0 @@ -// -// blocking_udp_client.cpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <boost/asio/deadline_timer.hpp> -#include <boost/asio/io_service.hpp> -#include <boost/asio/ip/udp.hpp> -#include <cstdlib> -#include <boost/bind.hpp> -#include <boost/date_time/posix_time/posix_time_types.hpp> -#include <iostream> - -using boost::asio::deadline_timer; -using boost::asio::ip::udp; - -//---------------------------------------------------------------------- - -// -// This class manages socket timeouts by applying the concept of a deadline. -// Each asynchronous operation is given a deadline by which it must complete. -// Deadlines are enforced by an "actor" that persists for the lifetime of the -// client object: -// -// +----------------+ -// | | -// | check_deadline |<---+ -// | | | -// +----------------+ | async_wait() -// | | -// +---------+ -// -// If the actor determines that the deadline has expired, any outstanding -// socket operations are cancelled. The socket operations themselves are -// implemented as transient actors: -// -// +---------------+ -// | | -// | receive | -// | | -// +---------------+ -// | -// async_- | +----------------+ -// receive() | | | -// +--->| handle_receive | -// | | -// +----------------+ -// -// The client object runs the io_service to block thread execution until the -// actor completes. -// -class client -{ -public: - client(const udp::endpoint& listen_endpoint) - : socket_(io_service_, listen_endpoint), - deadline_(io_service_) - { - // No deadline is required until the first socket operation is started. We - // set the deadline to positive infinity so that the actor takes no action - // until a specific deadline is set. - deadline_.expires_at(boost::posix_time::pos_infin); - - // Start the persistent actor that checks for deadline expiry. - check_deadline(); - } - - std::size_t receive(const boost::asio::mutable_buffer& buffer, - boost::posix_time::time_duration timeout, boost::system::error_code& ec) - { - // Set a deadline for the asynchronous operation. - deadline_.expires_from_now(timeout); - - // Set up the variables that receive the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - ec = boost::asio::error::would_block; - std::size_t length = 0; - - // Start the asynchronous operation itself. The handle_receive function - // used as a callback will update the ec and length variables. - socket_.async_receive(boost::asio::buffer(buffer), - boost::bind(&client::handle_receive, _1, _2, &ec, &length)); - - // Block until the asynchronous operation has completed. - do io_service_.run_one(); while (ec == boost::asio::error::would_block); - - return length; - } - -private: - void check_deadline() - { - // Check whether the deadline has passed. We compare the deadline against - // the current time since a new asynchronous operation may have moved the - // deadline before this actor had a chance to run. - if (deadline_.expires_at() <= deadline_timer::traits_type::now()) - { - // The deadline has passed. The outstanding asynchronous operation needs - // to be cancelled so that the blocked receive() function will return. - // - // Please note that cancel() has portability issues on some versions of - // Microsoft Windows, and it may be necessary to use close() instead. - // Consult the documentation for cancel() for further information. - socket_.cancel(); - - // There is no longer an active deadline. The expiry is set to positive - // infinity so that the actor takes no action until a new deadline is set. - deadline_.expires_at(boost::posix_time::pos_infin); - } - - // Put the actor back to sleep. - deadline_.async_wait(boost::bind(&client::check_deadline, this)); - } - - static void handle_receive( - const boost::system::error_code& ec, std::size_t length, - boost::system::error_code* out_ec, std::size_t* out_length) - { - *out_ec = ec; - *out_length = length; - } - -private: - boost::asio::io_service io_service_; - udp::socket socket_; - deadline_timer deadline_; -}; - -//---------------------------------------------------------------------- - -int main(int argc, char* argv[]) -{ - try - { - using namespace std; // For atoi. - - if (argc != 3) - { - std::cerr << "Usage: blocking_udp_timeout <listen_addr> <listen_port>\n"; - return 1; - } - - udp::endpoint listen_endpoint( - boost::asio::ip::address::from_string(argv[1]), - std::atoi(argv[2])); - - client c(listen_endpoint); - - for (;;) - { - char data[1024]; - boost::system::error_code ec; - std::size_t n = c.receive(boost::asio::buffer(data), - boost::posix_time::seconds(10), ec); - - if (ec) - { - std::cout << "Receive error: " << ec.message() << "\n"; - } - else - { - std::cout << "Received: "; - std::cout.write(data, n); - std::cout << "\n"; - } - } - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/timeouts/server.cpp b/doc/html/boost_asio/example/cpp03/timeouts/server.cpp deleted file mode 100644 index cdeeb2a7cb..0000000000 --- a/doc/html/boost_asio/example/cpp03/timeouts/server.cpp +++ /dev/null @@ -1,427 +0,0 @@ -// -// server.cpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <algorithm> -#include <cstdlib> -#include <deque> -#include <iostream> -#include <set> -#include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> -#include <boost/asio/deadline_timer.hpp> -#include <boost/asio/io_service.hpp> -#include <boost/asio/ip/tcp.hpp> -#include <boost/asio/ip/udp.hpp> -#include <boost/asio/read_until.hpp> -#include <boost/asio/streambuf.hpp> -#include <boost/asio/write.hpp> - -using boost::asio::deadline_timer; -using boost::asio::ip::tcp; -using boost::asio::ip::udp; - -//---------------------------------------------------------------------- - -class subscriber -{ -public: - virtual ~subscriber() {} - virtual void deliver(const std::string& msg) = 0; -}; - -typedef boost::shared_ptr<subscriber> subscriber_ptr; - -//---------------------------------------------------------------------- - -class channel -{ -public: - void join(subscriber_ptr subscriber) - { - subscribers_.insert(subscriber); - } - - void leave(subscriber_ptr subscriber) - { - subscribers_.erase(subscriber); - } - - void deliver(const std::string& msg) - { - std::for_each(subscribers_.begin(), subscribers_.end(), - boost::bind(&subscriber::deliver, _1, boost::ref(msg))); - } - -private: - std::set<subscriber_ptr> subscribers_; -}; - -//---------------------------------------------------------------------- - -// -// This class manages socket timeouts by applying the concept of a deadline. -// Some asynchronous operations are given deadlines by which they must complete. -// Deadlines are enforced by two "actors" that persist for the lifetime of the -// session object, one for input and one for output: -// -// +----------------+ +----------------+ -// | | | | -// | check_deadline |<---+ | check_deadline |<---+ -// | | | async_wait() | | | async_wait() -// +----------------+ | on input +----------------+ | on output -// | | deadline | | deadline -// +---------+ +---------+ -// -// If either deadline actor determines that the corresponding deadline has -// expired, the socket is closed and any outstanding operations are cancelled. -// -// The input actor reads messages from the socket, where messages are delimited -// by the newline character: -// -// +------------+ -// | | -// | start_read |<---+ -// | | | -// +------------+ | -// | | -// async_- | +-------------+ -// read_- | | | -// until() +--->| handle_read | -// | | -// +-------------+ -// -// The deadline for receiving a complete message is 30 seconds. If a non-empty -// message is received, it is delivered to all subscribers. If a heartbeat (a -// message that consists of a single newline character) is received, a heartbeat -// is enqueued for the client, provided there are no other messages waiting to -// be sent. -// -// The output actor is responsible for sending messages to the client: -// -// +--------------+ -// | |<---------------------+ -// | await_output | | -// | |<---+ | -// +--------------+ | | -// | | | async_wait() | -// | +--------+ | -// V | -// +-------------+ +--------------+ -// | | async_write() | | -// | start_write |-------------->| handle_write | -// | | | | -// +-------------+ +--------------+ -// -// The output actor first waits for an output message to be enqueued. It does -// this by using a deadline_timer as an asynchronous condition variable. The -// deadline_timer will be signalled whenever the output queue is non-empty. -// -// Once a message is available, it is sent to the client. The deadline for -// sending a complete message is 30 seconds. After the message is successfully -// sent, the output actor again waits for the output queue to become non-empty. -// -class tcp_session - : public subscriber, - public boost::enable_shared_from_this<tcp_session> -{ -public: - tcp_session(boost::asio::io_service& io_service, channel& ch) - : channel_(ch), - socket_(io_service), - input_deadline_(io_service), - non_empty_output_queue_(io_service), - output_deadline_(io_service) - { - input_deadline_.expires_at(boost::posix_time::pos_infin); - output_deadline_.expires_at(boost::posix_time::pos_infin); - - // The non_empty_output_queue_ deadline_timer is set to pos_infin whenever - // the output queue is empty. This ensures that the output actor stays - // asleep until a message is put into the queue. - non_empty_output_queue_.expires_at(boost::posix_time::pos_infin); - } - - tcp::socket& socket() - { - return socket_; - } - - // Called by the server object to initiate the four actors. - void start() - { - channel_.join(shared_from_this()); - - start_read(); - - input_deadline_.async_wait( - boost::bind(&tcp_session::check_deadline, - shared_from_this(), &input_deadline_)); - - await_output(); - - output_deadline_.async_wait( - boost::bind(&tcp_session::check_deadline, - shared_from_this(), &output_deadline_)); - } - -private: - void stop() - { - channel_.leave(shared_from_this()); - - boost::system::error_code ignored_ec; - socket_.close(ignored_ec); - input_deadline_.cancel(); - non_empty_output_queue_.cancel(); - output_deadline_.cancel(); - } - - bool stopped() const - { - return !socket_.is_open(); - } - - void deliver(const std::string& msg) - { - output_queue_.push_back(msg + "\n"); - - // Signal that the output queue contains messages. Modifying the expiry - // will wake the output actor, if it is waiting on the timer. - non_empty_output_queue_.expires_at(boost::posix_time::neg_infin); - } - - void start_read() - { - // Set a deadline for the read operation. - input_deadline_.expires_from_now(boost::posix_time::seconds(30)); - - // Start an asynchronous operation to read a newline-delimited message. - boost::asio::async_read_until(socket_, input_buffer_, '\n', - boost::bind(&tcp_session::handle_read, shared_from_this(), _1)); - } - - void handle_read(const boost::system::error_code& ec) - { - if (stopped()) - return; - - if (!ec) - { - // Extract the newline-delimited message from the buffer. - std::string msg; - std::istream is(&input_buffer_); - std::getline(is, msg); - - if (!msg.empty()) - { - channel_.deliver(msg); - } - else - { - // We received a heartbeat message from the client. If there's nothing - // else being sent or ready to be sent, send a heartbeat right back. - if (output_queue_.empty()) - { - output_queue_.push_back("\n"); - - // Signal that the output queue contains messages. Modifying the - // expiry will wake the output actor, if it is waiting on the timer. - non_empty_output_queue_.expires_at(boost::posix_time::neg_infin); - } - } - - start_read(); - } - else - { - stop(); - } - } - - void await_output() - { - if (stopped()) - return; - - if (output_queue_.empty()) - { - // There are no messages that are ready to be sent. The actor goes to - // sleep by waiting on the non_empty_output_queue_ timer. When a new - // message is added, the timer will be modified and the actor will wake. - non_empty_output_queue_.expires_at(boost::posix_time::pos_infin); - non_empty_output_queue_.async_wait( - boost::bind(&tcp_session::await_output, shared_from_this())); - } - else - { - start_write(); - } - } - - void start_write() - { - // Set a deadline for the write operation. - output_deadline_.expires_from_now(boost::posix_time::seconds(30)); - - // Start an asynchronous operation to send a message. - boost::asio::async_write(socket_, - boost::asio::buffer(output_queue_.front()), - boost::bind(&tcp_session::handle_write, shared_from_this(), _1)); - } - - void handle_write(const boost::system::error_code& ec) - { - if (stopped()) - return; - - if (!ec) - { - output_queue_.pop_front(); - - await_output(); - } - else - { - stop(); - } - } - - void check_deadline(deadline_timer* deadline) - { - if (stopped()) - return; - - // Check whether the deadline has passed. We compare the deadline against - // the current time since a new asynchronous operation may have moved the - // deadline before this actor had a chance to run. - if (deadline->expires_at() <= deadline_timer::traits_type::now()) - { - // The deadline has passed. Stop the session. The other actors will - // terminate as soon as possible. - stop(); - } - else - { - // Put the actor back to sleep. - deadline->async_wait( - boost::bind(&tcp_session::check_deadline, - shared_from_this(), deadline)); - } - } - - channel& channel_; - tcp::socket socket_; - boost::asio::streambuf input_buffer_; - deadline_timer input_deadline_; - std::deque<std::string> output_queue_; - deadline_timer non_empty_output_queue_; - deadline_timer output_deadline_; -}; - -typedef boost::shared_ptr<tcp_session> tcp_session_ptr; - -//---------------------------------------------------------------------- - -class udp_broadcaster - : public subscriber -{ -public: - udp_broadcaster(boost::asio::io_service& io_service, - const udp::endpoint& broadcast_endpoint) - : socket_(io_service) - { - socket_.connect(broadcast_endpoint); - } - -private: - void deliver(const std::string& msg) - { - boost::system::error_code ignored_ec; - socket_.send(boost::asio::buffer(msg), 0, ignored_ec); - } - - udp::socket socket_; -}; - -//---------------------------------------------------------------------- - -class server -{ -public: - server(boost::asio::io_service& io_service, - const tcp::endpoint& listen_endpoint, - const udp::endpoint& broadcast_endpoint) - : io_service_(io_service), - acceptor_(io_service, listen_endpoint) - { - subscriber_ptr bc(new udp_broadcaster(io_service_, broadcast_endpoint)); - channel_.join(bc); - - start_accept(); - } - - void start_accept() - { - tcp_session_ptr new_session(new tcp_session(io_service_, channel_)); - - acceptor_.async_accept(new_session->socket(), - boost::bind(&server::handle_accept, this, new_session, _1)); - } - - void handle_accept(tcp_session_ptr session, - const boost::system::error_code& ec) - { - if (!ec) - { - session->start(); - } - - start_accept(); - } - -private: - boost::asio::io_service& io_service_; - tcp::acceptor acceptor_; - channel channel_; -}; - -//---------------------------------------------------------------------- - -int main(int argc, char* argv[]) -{ - try - { - using namespace std; // For atoi. - - if (argc != 4) - { - std::cerr << "Usage: server <listen_port> <bcast_address> <bcast_port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - tcp::endpoint listen_endpoint(tcp::v4(), atoi(argv[1])); - - udp::endpoint broadcast_endpoint( - boost::asio::ip::address::from_string(argv[2]), atoi(argv[3])); - - server s(io_service, listen_endpoint, broadcast_endpoint); - - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/timers/tick_count_timer.cpp b/doc/html/boost_asio/example/cpp03/timers/tick_count_timer.cpp deleted file mode 100644 index 0c06e751ce..0000000000 --- a/doc/html/boost_asio/example/cpp03/timers/tick_count_timer.cpp +++ /dev/null @@ -1,123 +0,0 @@ -// -// tick_count_timer.cpp -// ~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <boost/asio.hpp> -#include <ctime> -#include <iostream> - -#if defined(WIN32) -# include <windows.h> -#else -# error This example is for Windows only! -#endif - -struct tick_count_traits -{ - // The time type. This type has no constructor that takes a DWORD to ensure - // that the timer can only be used with relative times. - class time_type - { - public: - time_type() : ticks_(0) {} - private: - friend struct tick_count_traits; - DWORD ticks_; - }; - - // The duration type. According to the TimeTraits requirements, the duration - // must be a signed type. This means we can't handle durations larger than - // 2^31. - class duration_type - { - public: - duration_type() : ticks_(0) {} - duration_type(LONG ticks) : ticks_(ticks) {} - private: - friend struct tick_count_traits; - LONG ticks_; - }; - - // Get the current time. - static time_type now() - { - time_type result; - result.ticks_ = ::GetTickCount(); - return result; - } - - // Add a duration to a time. - static time_type add(const time_type& t, const duration_type& d) - { - time_type result; - result.ticks_ = t.ticks_ + d.ticks_; - return result; - } - - // Subtract one time from another. - static duration_type subtract(const time_type& t1, const time_type& t2) - { - // DWORD tick count values can wrap (see less_than() below). We'll convert - // to a duration by taking the absolute difference and adding the sign - // based on which is the "lesser" absolute time. - return duration_type(less_than(t1, t2) - ? -static_cast<LONG>(t2.ticks_ - t1.ticks_) - : static_cast<LONG>(t1.ticks_ - t2.ticks_)); - } - - // Test whether one time is less than another. - static bool less_than(const time_type& t1, const time_type& t2) - { - // DWORD tick count values wrap periodically, so we'll use a heuristic that - // says that if subtracting t1 from t2 yields a value smaller than 2^31, - // then t1 is probably less than t2. This means that we can't handle - // durations larger than 2^31, which shouldn't be a problem in practice. - return (t2.ticks_ - t1.ticks_) < static_cast<DWORD>(1 << 31); - } - - // Convert to POSIX duration type. - static boost::posix_time::time_duration to_posix_duration( - const duration_type& d) - { - return boost::posix_time::milliseconds(d.ticks_); - } -}; - -typedef boost::asio::basic_deadline_timer< - DWORD, tick_count_traits> tick_count_timer; - -void handle_timeout(const boost::system::error_code&) -{ - std::cout << "handle_timeout\n"; -} - -int main() -{ - try - { - boost::asio::io_service io_service; - - tick_count_timer timer(io_service, 5000); - std::cout << "Starting synchronous wait\n"; - timer.wait(); - std::cout << "Finished synchronous wait\n"; - - timer.expires_from_now(5000); - std::cout << "Starting asynchronous wait\n"; - timer.async_wait(&handle_timeout); - io_service.run(); - std::cout << "Finished asynchronous wait\n"; - } - catch (std::exception& e) - { - std::cout << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/timers/time_t_timer.cpp b/doc/html/boost_asio/example/cpp03/timers/time_t_timer.cpp deleted file mode 100644 index 999ce88a6a..0000000000 --- a/doc/html/boost_asio/example/cpp03/timers/time_t_timer.cpp +++ /dev/null @@ -1,93 +0,0 @@ -// -// time_t_timer.cpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <boost/asio.hpp> -#include <ctime> -#include <iostream> - -struct time_t_traits -{ - // The time type. - typedef std::time_t time_type; - - // The duration type. - struct duration_type - { - duration_type() : value(0) {} - duration_type(std::time_t v) : value(v) {} - std::time_t value; - }; - - // Get the current time. - static time_type now() - { - return std::time(0); - } - - // Add a duration to a time. - static time_type add(const time_type& t, const duration_type& d) - { - return t + d.value; - } - - // Subtract one time from another. - static duration_type subtract(const time_type& t1, const time_type& t2) - { - return duration_type(t1 - t2); - } - - // Test whether one time is less than another. - static bool less_than(const time_type& t1, const time_type& t2) - { - return t1 < t2; - } - - // Convert to POSIX duration type. - static boost::posix_time::time_duration to_posix_duration( - const duration_type& d) - { - return boost::posix_time::seconds(d.value); - } -}; - -typedef boost::asio::basic_deadline_timer< - std::time_t, time_t_traits> time_t_timer; - -void handle_timeout(const boost::system::error_code&) -{ - std::cout << "handle_timeout\n"; -} - -int main() -{ - try - { - boost::asio::io_service io_service; - - time_t_timer timer(io_service); - - timer.expires_from_now(5); - std::cout << "Starting synchronous wait\n"; - timer.wait(); - std::cout << "Finished synchronous wait\n"; - - timer.expires_from_now(5); - std::cout << "Starting asynchronous wait\n"; - timer.async_wait(&handle_timeout); - io_service.run(); - std::cout << "Finished asynchronous wait\n"; - } - catch (std::exception& e) - { - std::cout << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp03/windows/transmit_file.cpp b/doc/html/boost_asio/example/cpp03/windows/transmit_file.cpp deleted file mode 100644 index e3dbec80cf..0000000000 --- a/doc/html/boost_asio/example/cpp03/windows/transmit_file.cpp +++ /dev/null @@ -1,171 +0,0 @@ -// -// transmit_file.cpp -// ~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <ctime> -#include <iostream> -#include <string> -#include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> -#include <boost/asio.hpp> - -#if defined(BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR) - -using boost::asio::ip::tcp; -using boost::asio::windows::overlapped_ptr; -using boost::asio::windows::random_access_handle; - -// A wrapper for the TransmitFile overlapped I/O operation. -template <typename Handler> -void transmit_file(tcp::socket& socket, - random_access_handle& file, Handler handler) -{ - // Construct an OVERLAPPED-derived object to contain the handler. - overlapped_ptr overlapped(socket.get_io_service(), handler); - - // Initiate the TransmitFile operation. - BOOL ok = ::TransmitFile(socket.native_handle(), - file.native_handle(), 0, 0, overlapped.get(), 0, 0); - DWORD last_error = ::GetLastError(); - - // Check if the operation completed immediately. - if (!ok && last_error != ERROR_IO_PENDING) - { - // The operation completed immediately, so a completion notification needs - // to be posted. When complete() is called, ownership of the OVERLAPPED- - // derived object passes to the io_service. - boost::system::error_code ec(last_error, - boost::asio::error::get_system_category()); - overlapped.complete(ec, 0); - } - else - { - // The operation was successfully initiated, so ownership of the - // OVERLAPPED-derived object has passed to the io_service. - overlapped.release(); - } -} - -class connection - : public boost::enable_shared_from_this<connection> -{ -public: - typedef boost::shared_ptr<connection> pointer; - - static pointer create(boost::asio::io_service& io_service, - const std::string& filename) - { - return pointer(new connection(io_service, filename)); - } - - tcp::socket& socket() - { - return socket_; - } - - void start() - { - boost::system::error_code ec; - file_.assign(::CreateFile(filename_.c_str(), GENERIC_READ, 0, 0, - OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 0), ec); - if (file_.is_open()) - { - transmit_file(socket_, file_, - boost::bind(&connection::handle_write, shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - } - -private: - connection(boost::asio::io_service& io_service, const std::string& filename) - : socket_(io_service), - filename_(filename), - file_(io_service) - { - } - - void handle_write(const boost::system::error_code& /*error*/, - size_t /*bytes_transferred*/) - { - boost::system::error_code ignored_ec; - socket_.shutdown(tcp::socket::shutdown_both, ignored_ec); - } - - tcp::socket socket_; - std::string filename_; - random_access_handle file_; -}; - -class server -{ -public: - server(boost::asio::io_service& io_service, - unsigned short port, const std::string& filename) - : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)), - filename_(filename) - { - start_accept(); - } - -private: - void start_accept() - { - connection::pointer new_connection = - connection::create(acceptor_.get_io_service(), filename_); - - acceptor_.async_accept(new_connection->socket(), - boost::bind(&server::handle_accept, this, new_connection, - boost::asio::placeholders::error)); - } - - void handle_accept(connection::pointer new_connection, - const boost::system::error_code& error) - { - if (!error) - { - new_connection->start(); - } - - start_accept(); - } - - tcp::acceptor acceptor_; - std::string filename_; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 3) - { - std::cerr << "Usage: transmit_file <port> <filename>\n"; - return 1; - } - - boost::asio::io_service io_service; - - using namespace std; // For atoi. - server s(io_service, atoi(argv[1]), argv[2]); - - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << e.what() << std::endl; - } - - return 0; -} - -#else // defined(BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR) -# error Overlapped I/O not available on this platform -#endif // defined(BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR) diff --git a/doc/html/boost_asio/example/cpp11/allocation/server.cpp b/doc/html/boost_asio/example/cpp11/allocation/server.cpp deleted file mode 100644 index ce7223ebe7..0000000000 --- a/doc/html/boost_asio/example/cpp11/allocation/server.cpp +++ /dev/null @@ -1,215 +0,0 @@ -// -// server.cpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <array> -#include <cstdlib> -#include <iostream> -#include <memory> -#include <type_traits> -#include <utility> -#include <boost/asio.hpp> - -using boost::asio::ip::tcp; - -// Class to manage the memory to be used for handler-based custom allocation. -// It contains a single block of memory which may be returned for allocation -// requests. If the memory is in use when an allocation request is made, the -// allocator delegates allocation to the global heap. -class handler_allocator -{ -public: - handler_allocator() - : in_use_(false) - { - } - - handler_allocator(const handler_allocator&) = delete; - handler_allocator& operator=(const handler_allocator&) = delete; - - void* allocate(std::size_t size) - { - if (!in_use_ && size < sizeof(storage_)) - { - in_use_ = true; - return &storage_; - } - else - { - return ::operator new(size); - } - } - - void deallocate(void* pointer) - { - if (pointer == &storage_) - { - in_use_ = false; - } - else - { - ::operator delete(pointer); - } - } - -private: - // Storage space used for handler-based custom memory allocation. - typename std::aligned_storage<1024>::type storage_; - - // Whether the handler-based custom allocation storage has been used. - bool in_use_; -}; - -// Wrapper class template for handler objects to allow handler memory -// allocation to be customised. Calls to operator() are forwarded to the -// encapsulated handler. -template <typename Handler> -class custom_alloc_handler -{ -public: - custom_alloc_handler(handler_allocator& a, Handler h) - : allocator_(a), - handler_(h) - { - } - - template <typename ...Args> - void operator()(Args&&... args) - { - handler_(std::forward<Args>(args)...); - } - - friend void* asio_handler_allocate(std::size_t size, - custom_alloc_handler<Handler>* this_handler) - { - return this_handler->allocator_.allocate(size); - } - - friend void asio_handler_deallocate(void* pointer, std::size_t /*size*/, - custom_alloc_handler<Handler>* this_handler) - { - this_handler->allocator_.deallocate(pointer); - } - -private: - handler_allocator& allocator_; - Handler handler_; -}; - -// Helper function to wrap a handler object to add custom allocation. -template <typename Handler> -inline custom_alloc_handler<Handler> make_custom_alloc_handler( - handler_allocator& a, Handler h) -{ - return custom_alloc_handler<Handler>(a, h); -} - -class session - : public std::enable_shared_from_this<session> -{ -public: - session(tcp::socket socket) - : socket_(std::move(socket)) - { - } - - void start() - { - do_read(); - } - -private: - void do_read() - { - auto self(shared_from_this()); - socket_.async_read_some(boost::asio::buffer(data_), - make_custom_alloc_handler(allocator_, - [this, self](boost::system::error_code ec, std::size_t length) - { - if (!ec) - { - do_write(length); - } - })); - } - - void do_write(std::size_t length) - { - auto self(shared_from_this()); - boost::asio::async_write(socket_, boost::asio::buffer(data_, length), - make_custom_alloc_handler(allocator_, - [this, self](boost::system::error_code ec, std::size_t /*length*/) - { - if (!ec) - { - do_read(); - } - })); - } - - // The socket used to communicate with the client. - tcp::socket socket_; - - // Buffer used to store data received from the client. - std::array<char, 1024> data_; - - // The allocator to use for handler-based custom memory allocation. - handler_allocator allocator_; -}; - -class server -{ -public: - server(boost::asio::io_service& io_service, short port) - : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)), - socket_(io_service) - { - do_accept(); - } - -private: - void do_accept() - { - acceptor_.async_accept(socket_, - [this](boost::system::error_code ec) - { - if (!ec) - { - std::make_shared<session>(std::move(socket_))->start(); - } - - do_accept(); - }); - } - - tcp::acceptor acceptor_; - tcp::socket socket_; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: server <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - server s(io_service, std::atoi(argv[1])); - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp11/buffers/reference_counted.cpp b/doc/html/boost_asio/example/cpp11/buffers/reference_counted.cpp deleted file mode 100644 index 7b5a35ba70..0000000000 --- a/doc/html/boost_asio/example/cpp11/buffers/reference_counted.cpp +++ /dev/null @@ -1,123 +0,0 @@ -// -// reference_counted.cpp -// ~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <boost/asio.hpp> -#include <iostream> -#include <memory> -#include <utility> -#include <vector> - -using boost::asio::ip::tcp; - -// A reference-counted non-modifiable buffer class. -class shared_const_buffer -{ -public: - // Construct from a std::string. - explicit shared_const_buffer(const std::string& data) - : data_(new std::vector<char>(data.begin(), data.end())), - buffer_(boost::asio::buffer(*data_)) - { - } - - // Implement the ConstBufferSequence requirements. - typedef boost::asio::const_buffer value_type; - typedef const boost::asio::const_buffer* const_iterator; - const boost::asio::const_buffer* begin() const { return &buffer_; } - const boost::asio::const_buffer* end() const { return &buffer_ + 1; } - -private: - std::shared_ptr<std::vector<char> > data_; - boost::asio::const_buffer buffer_; -}; - -class session - : public std::enable_shared_from_this<session> -{ -public: - session(tcp::socket socket) - : socket_(std::move(socket)) - { - } - - void start() - { - do_write(); - } - -private: - void do_write() - { - std::time_t now = std::time(0); - shared_const_buffer buffer(std::ctime(&now)); - - auto self(shared_from_this()); - boost::asio::async_write(socket_, buffer, - [this, self](boost::system::error_code /*ec*/, std::size_t /*length*/) - { - }); - } - - // The socket used to communicate with the client. - tcp::socket socket_; -}; - -class server -{ -public: - server(boost::asio::io_service& io_service, short port) - : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)), - socket_(io_service) - { - do_accept(); - } - -private: - void do_accept() - { - acceptor_.async_accept(socket_, - [this](boost::system::error_code ec) - { - if (!ec) - { - std::make_shared<session>(std::move(socket_))->start(); - } - - do_accept(); - }); - } - - tcp::acceptor acceptor_; - tcp::socket socket_; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: reference_counted <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - server s(io_service, std::atoi(argv[1])); - - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp11/chat/chat_client.cpp b/doc/html/boost_asio/example/cpp11/chat/chat_client.cpp deleted file mode 100644 index a9faeca7c7..0000000000 --- a/doc/html/boost_asio/example/cpp11/chat/chat_client.cpp +++ /dev/null @@ -1,167 +0,0 @@ -// -// chat_client.cpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstdlib> -#include <deque> -#include <iostream> -#include <thread> -#include <boost/asio.hpp> -#include "chat_message.hpp" - -using boost::asio::ip::tcp; - -typedef std::deque<chat_message> chat_message_queue; - -class chat_client -{ -public: - chat_client(boost::asio::io_service& io_service, - tcp::resolver::iterator endpoint_iterator) - : io_service_(io_service), - socket_(io_service) - { - do_connect(endpoint_iterator); - } - - void write(const chat_message& msg) - { - io_service_.post( - [this, msg]() - { - bool write_in_progress = !write_msgs_.empty(); - write_msgs_.push_back(msg); - if (!write_in_progress) - { - do_write(); - } - }); - } - - void close() - { - io_service_.post([this]() { socket_.close(); }); - } - -private: - void do_connect(tcp::resolver::iterator endpoint_iterator) - { - boost::asio::async_connect(socket_, endpoint_iterator, - [this](boost::system::error_code ec, tcp::resolver::iterator) - { - if (!ec) - { - do_read_header(); - } - }); - } - - void do_read_header() - { - boost::asio::async_read(socket_, - boost::asio::buffer(read_msg_.data(), chat_message::header_length), - [this](boost::system::error_code ec, std::size_t /*length*/) - { - if (!ec && read_msg_.decode_header()) - { - do_read_body(); - } - else - { - socket_.close(); - } - }); - } - - void do_read_body() - { - boost::asio::async_read(socket_, - boost::asio::buffer(read_msg_.body(), read_msg_.body_length()), - [this](boost::system::error_code ec, std::size_t /*length*/) - { - if (!ec) - { - std::cout.write(read_msg_.body(), read_msg_.body_length()); - std::cout << "\n"; - do_read_header(); - } - else - { - socket_.close(); - } - }); - } - - void do_write() - { - boost::asio::async_write(socket_, - boost::asio::buffer(write_msgs_.front().data(), - write_msgs_.front().length()), - [this](boost::system::error_code ec, std::size_t /*length*/) - { - if (!ec) - { - write_msgs_.pop_front(); - if (!write_msgs_.empty()) - { - do_write(); - } - } - else - { - socket_.close(); - } - }); - } - -private: - boost::asio::io_service& io_service_; - tcp::socket socket_; - chat_message read_msg_; - chat_message_queue write_msgs_; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 3) - { - std::cerr << "Usage: chat_client <host> <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - tcp::resolver resolver(io_service); - auto endpoint_iterator = resolver.resolve({ argv[1], argv[2] }); - chat_client c(io_service, endpoint_iterator); - - std::thread t([&io_service](){ io_service.run(); }); - - char line[chat_message::max_body_length + 1]; - while (std::cin.getline(line, chat_message::max_body_length + 1)) - { - chat_message msg; - msg.body_length(std::strlen(line)); - std::memcpy(msg.body(), line, msg.body_length()); - msg.encode_header(); - c.write(msg); - } - - c.close(); - t.join(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp11/chat/chat_message.hpp b/doc/html/boost_asio/example/cpp11/chat/chat_message.hpp deleted file mode 100644 index d1593cd8df..0000000000 --- a/doc/html/boost_asio/example/cpp11/chat/chat_message.hpp +++ /dev/null @@ -1,91 +0,0 @@ -// -// chat_message.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 CHAT_MESSAGE_HPP -#define CHAT_MESSAGE_HPP - -#include <cstdio> -#include <cstdlib> -#include <cstring> - -class chat_message -{ -public: - enum { header_length = 4 }; - enum { max_body_length = 512 }; - - chat_message() - : body_length_(0) - { - } - - const char* data() const - { - return data_; - } - - char* data() - { - return data_; - } - - std::size_t length() const - { - return header_length + body_length_; - } - - const char* body() const - { - return data_ + header_length; - } - - char* body() - { - return data_ + header_length; - } - - std::size_t body_length() const - { - return body_length_; - } - - void body_length(std::size_t new_length) - { - body_length_ = new_length; - if (body_length_ > max_body_length) - body_length_ = max_body_length; - } - - bool decode_header() - { - char header[header_length + 1] = ""; - std::strncat(header, data_, header_length); - body_length_ = std::atoi(header); - if (body_length_ > max_body_length) - { - body_length_ = 0; - return false; - } - return true; - } - - void encode_header() - { - char header[header_length + 1] = ""; - std::sprintf(header, "%4d", static_cast<int>(body_length_)); - std::memcpy(data_, header, header_length); - } - -private: - char data_[header_length + max_body_length]; - std::size_t body_length_; -}; - -#endif // CHAT_MESSAGE_HPP diff --git a/doc/html/boost_asio/example/cpp11/chat/chat_server.cpp b/doc/html/boost_asio/example/cpp11/chat/chat_server.cpp deleted file mode 100644 index d8a1dc3558..0000000000 --- a/doc/html/boost_asio/example/cpp11/chat/chat_server.cpp +++ /dev/null @@ -1,229 +0,0 @@ -// -// chat_server.cpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstdlib> -#include <deque> -#include <iostream> -#include <list> -#include <memory> -#include <set> -#include <utility> -#include <boost/asio.hpp> -#include "chat_message.hpp" - -using boost::asio::ip::tcp; - -//---------------------------------------------------------------------- - -typedef std::deque<chat_message> chat_message_queue; - -//---------------------------------------------------------------------- - -class chat_participant -{ -public: - virtual ~chat_participant() {} - virtual void deliver(const chat_message& msg) = 0; -}; - -typedef std::shared_ptr<chat_participant> chat_participant_ptr; - -//---------------------------------------------------------------------- - -class chat_room -{ -public: - void join(chat_participant_ptr participant) - { - participants_.insert(participant); - for (auto msg: recent_msgs_) - participant->deliver(msg); - } - - void leave(chat_participant_ptr participant) - { - participants_.erase(participant); - } - - void deliver(const chat_message& msg) - { - recent_msgs_.push_back(msg); - while (recent_msgs_.size() > max_recent_msgs) - recent_msgs_.pop_front(); - - for (auto participant: participants_) - participant->deliver(msg); - } - -private: - std::set<chat_participant_ptr> participants_; - enum { max_recent_msgs = 100 }; - chat_message_queue recent_msgs_; -}; - -//---------------------------------------------------------------------- - -class chat_session - : public chat_participant, - public std::enable_shared_from_this<chat_session> -{ -public: - chat_session(tcp::socket socket, chat_room& room) - : socket_(std::move(socket)), - room_(room) - { - } - - void start() - { - room_.join(shared_from_this()); - do_read_header(); - } - - void deliver(const chat_message& msg) - { - bool write_in_progress = !write_msgs_.empty(); - write_msgs_.push_back(msg); - if (!write_in_progress) - { - do_write(); - } - } - -private: - void do_read_header() - { - auto self(shared_from_this()); - boost::asio::async_read(socket_, - boost::asio::buffer(read_msg_.data(), chat_message::header_length), - [this, self](boost::system::error_code ec, std::size_t /*length*/) - { - if (!ec && read_msg_.decode_header()) - { - do_read_body(); - } - else - { - room_.leave(shared_from_this()); - } - }); - } - - void do_read_body() - { - auto self(shared_from_this()); - boost::asio::async_read(socket_, - boost::asio::buffer(read_msg_.body(), read_msg_.body_length()), - [this, self](boost::system::error_code ec, std::size_t /*length*/) - { - if (!ec) - { - room_.deliver(read_msg_); - do_read_header(); - } - else - { - room_.leave(shared_from_this()); - } - }); - } - - void do_write() - { - auto self(shared_from_this()); - boost::asio::async_write(socket_, - boost::asio::buffer(write_msgs_.front().data(), - write_msgs_.front().length()), - [this, self](boost::system::error_code ec, std::size_t /*length*/) - { - if (!ec) - { - write_msgs_.pop_front(); - if (!write_msgs_.empty()) - { - do_write(); - } - } - else - { - room_.leave(shared_from_this()); - } - }); - } - - tcp::socket socket_; - chat_room& room_; - chat_message read_msg_; - chat_message_queue write_msgs_; -}; - -//---------------------------------------------------------------------- - -class chat_server -{ -public: - chat_server(boost::asio::io_service& io_service, - const tcp::endpoint& endpoint) - : acceptor_(io_service, endpoint), - socket_(io_service) - { - do_accept(); - } - -private: - void do_accept() - { - acceptor_.async_accept(socket_, - [this](boost::system::error_code ec) - { - if (!ec) - { - std::make_shared<chat_session>(std::move(socket_), room_)->start(); - } - - do_accept(); - }); - } - - tcp::acceptor acceptor_; - tcp::socket socket_; - chat_room room_; -}; - -//---------------------------------------------------------------------- - -int main(int argc, char* argv[]) -{ - try - { - if (argc < 2) - { - std::cerr << "Usage: chat_server <port> [<port> ...]\n"; - return 1; - } - - boost::asio::io_service io_service; - - std::list<chat_server> servers; - for (int i = 1; i < argc; ++i) - { - tcp::endpoint endpoint(tcp::v4(), std::atoi(argv[i])); - servers.emplace_back(io_service, endpoint); - } - - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp11/echo/async_tcp_echo_server.cpp b/doc/html/boost_asio/example/cpp11/echo/async_tcp_echo_server.cpp deleted file mode 100644 index 2f679e245e..0000000000 --- a/doc/html/boost_asio/example/cpp11/echo/async_tcp_echo_server.cpp +++ /dev/null @@ -1,116 +0,0 @@ -// -// async_tcp_echo_server.cpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstdlib> -#include <iostream> -#include <memory> -#include <utility> -#include <boost/asio.hpp> - -using boost::asio::ip::tcp; - -class session - : public std::enable_shared_from_this<session> -{ -public: - session(tcp::socket socket) - : socket_(std::move(socket)) - { - } - - void start() - { - do_read(); - } - -private: - void do_read() - { - auto self(shared_from_this()); - socket_.async_read_some(boost::asio::buffer(data_, max_length), - [this, self](boost::system::error_code ec, std::size_t length) - { - if (!ec) - { - do_write(length); - } - }); - } - - void do_write(std::size_t length) - { - auto self(shared_from_this()); - boost::asio::async_write(socket_, boost::asio::buffer(data_, length), - [this, self](boost::system::error_code ec, std::size_t /*length*/) - { - if (!ec) - { - do_read(); - } - }); - } - - tcp::socket socket_; - enum { max_length = 1024 }; - char data_[max_length]; -}; - -class server -{ -public: - server(boost::asio::io_service& io_service, short port) - : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)), - socket_(io_service) - { - do_accept(); - } - -private: - void do_accept() - { - acceptor_.async_accept(socket_, - [this](boost::system::error_code ec) - { - if (!ec) - { - std::make_shared<session>(std::move(socket_))->start(); - } - - do_accept(); - }); - } - - tcp::acceptor acceptor_; - tcp::socket socket_; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: async_tcp_echo_server <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - server s(io_service, std::atoi(argv[1])); - - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp11/echo/async_udp_echo_server.cpp b/doc/html/boost_asio/example/cpp11/echo/async_udp_echo_server.cpp deleted file mode 100644 index c457d6d400..0000000000 --- a/doc/html/boost_asio/example/cpp11/echo/async_udp_echo_server.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// -// async_udp_echo_server.cpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstdlib> -#include <iostream> -#include <boost/asio.hpp> - -using boost::asio::ip::udp; - -class server -{ -public: - server(boost::asio::io_service& io_service, short port) - : socket_(io_service, udp::endpoint(udp::v4(), port)) - { - do_receive(); - } - - void do_receive() - { - socket_.async_receive_from( - boost::asio::buffer(data_, max_length), sender_endpoint_, - [this](boost::system::error_code ec, std::size_t bytes_recvd) - { - if (!ec && bytes_recvd > 0) - { - do_send(bytes_recvd); - } - else - { - do_receive(); - } - }); - } - - void do_send(std::size_t length) - { - socket_.async_send_to( - boost::asio::buffer(data_, length), sender_endpoint_, - [this](boost::system::error_code /*ec*/, std::size_t /*bytes_sent*/) - { - do_receive(); - }); - } - -private: - udp::socket socket_; - udp::endpoint sender_endpoint_; - enum { max_length = 1024 }; - char data_[max_length]; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: async_udp_echo_server <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - server s(io_service, std::atoi(argv[1])); - - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_client.cpp b/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_client.cpp deleted file mode 100644 index db56bf5608..0000000000 --- a/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_client.cpp +++ /dev/null @@ -1,55 +0,0 @@ -// -// blocking_tcp_echo_client.cpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstdlib> -#include <cstring> -#include <iostream> -#include <boost/asio.hpp> - -using boost::asio::ip::tcp; - -enum { max_length = 1024 }; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 3) - { - std::cerr << "Usage: blocking_tcp_echo_client <host> <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - tcp::socket s(io_service); - tcp::resolver resolver(io_service); - boost::asio::connect(s, resolver.resolve({argv[1], argv[2]})); - - std::cout << "Enter message: "; - char request[max_length]; - std::cin.getline(request, max_length); - size_t request_length = std::strlen(request); - boost::asio::write(s, boost::asio::buffer(request, request_length)); - - char reply[max_length]; - size_t reply_length = boost::asio::read(s, - boost::asio::buffer(reply, request_length)); - std::cout << "Reply is: "; - std::cout.write(reply, reply_length); - std::cout << "\n"; - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_server.cpp b/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_server.cpp deleted file mode 100644 index 31d6bee055..0000000000 --- a/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_server.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// -// blocking_tcp_echo_server.cpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstdlib> -#include <iostream> -#include <thread> -#include <utility> -#include <boost/asio.hpp> - -using boost::asio::ip::tcp; - -const int max_length = 1024; - -void session(tcp::socket sock) -{ - try - { - for (;;) - { - char data[max_length]; - - boost::system::error_code error; - size_t length = sock.read_some(boost::asio::buffer(data), error); - if (error == boost::asio::error::eof) - break; // Connection closed cleanly by peer. - else if (error) - throw boost::system::system_error(error); // Some other error. - - boost::asio::write(sock, boost::asio::buffer(data, length)); - } - } - catch (std::exception& e) - { - std::cerr << "Exception in thread: " << e.what() << "\n"; - } -} - -void server(boost::asio::io_service& io_service, unsigned short port) -{ - tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), port)); - for (;;) - { - tcp::socket sock(io_service); - a.accept(sock); - std::thread(session, std::move(sock)).detach(); - } -} - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: blocking_tcp_echo_server <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - server(io_service, std::atoi(argv[1])); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp11/echo/blocking_udp_echo_client.cpp b/doc/html/boost_asio/example/cpp11/echo/blocking_udp_echo_client.cpp deleted file mode 100644 index 81de8d341b..0000000000 --- a/doc/html/boost_asio/example/cpp11/echo/blocking_udp_echo_client.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// -// blocking_udp_echo_client.cpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstdlib> -#include <cstring> -#include <iostream> -#include <boost/asio.hpp> - -using boost::asio::ip::udp; - -enum { max_length = 1024 }; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 3) - { - std::cerr << "Usage: blocking_udp_echo_client <host> <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - udp::socket s(io_service, udp::endpoint(udp::v4(), 0)); - - udp::resolver resolver(io_service); - udp::endpoint endpoint = *resolver.resolve({udp::v4(), argv[1], argv[2]}); - - std::cout << "Enter message: "; - char request[max_length]; - std::cin.getline(request, max_length); - size_t request_length = std::strlen(request); - s.send_to(boost::asio::buffer(request, request_length), endpoint); - - char reply[max_length]; - udp::endpoint sender_endpoint; - size_t reply_length = s.receive_from( - boost::asio::buffer(reply, max_length), sender_endpoint); - std::cout << "Reply is: "; - std::cout.write(reply, reply_length); - std::cout << "\n"; - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp11/echo/blocking_udp_echo_server.cpp b/doc/html/boost_asio/example/cpp11/echo/blocking_udp_echo_server.cpp deleted file mode 100644 index db37fcf5b6..0000000000 --- a/doc/html/boost_asio/example/cpp11/echo/blocking_udp_echo_server.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// -// blocking_udp_echo_server.cpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <cstdlib> -#include <iostream> -#include <boost/asio.hpp> - -using boost::asio::ip::udp; - -enum { max_length = 1024 }; - -void server(boost::asio::io_service& io_service, unsigned short port) -{ - udp::socket sock(io_service, udp::endpoint(udp::v4(), port)); - for (;;) - { - char data[max_length]; - udp::endpoint sender_endpoint; - size_t length = sock.receive_from( - boost::asio::buffer(data, max_length), sender_endpoint); - sock.send_to(boost::asio::buffer(data, length), sender_endpoint); - } -} - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: blocking_udp_echo_server <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - server(io_service, std::atoi(argv[1])); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp11/futures/daytime_client.cpp b/doc/html/boost_asio/example/cpp11/futures/daytime_client.cpp deleted file mode 100644 index e255b3c169..0000000000 --- a/doc/html/boost_asio/example/cpp11/futures/daytime_client.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// -// daytime_client.cpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <array> -#include <future> -#include <iostream> -#include <thread> -#include <boost/asio/io_service.hpp> -#include <boost/asio/ip/udp.hpp> -#include <boost/asio/use_future.hpp> - -using boost::asio::ip::udp; - -void get_daytime(boost::asio::io_service& io_service, const char* hostname) -{ - try - { - udp::resolver resolver(io_service); - - std::future<udp::resolver::iterator> iter = - resolver.async_resolve( - {udp::v4(), hostname, "daytime"}, - boost::asio::use_future); - - // The async_resolve operation above returns the endpoint iterator as a - // future value that is not retrieved ... - - udp::socket socket(io_service, udp::v4()); - - std::array<char, 1> send_buf = {{ 0 }}; - std::future<std::size_t> send_length = - socket.async_send_to(boost::asio::buffer(send_buf), - *iter.get(), // ... until here. This call may block. - boost::asio::use_future); - - // Do other things here while the send completes. - - send_length.get(); // Blocks until the send is complete. Throws any errors. - - std::array<char, 128> recv_buf; - udp::endpoint sender_endpoint; - std::future<std::size_t> recv_length = - socket.async_receive_from( - boost::asio::buffer(recv_buf), - sender_endpoint, - boost::asio::use_future); - - // Do other things here while the receive completes. - - std::cout.write( - recv_buf.data(), - recv_length.get()); // Blocks until receive is complete. - } - catch (std::system_error& e) - { - std::cerr << e.what() << std::endl; - } -} - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: daytime_client <host>" << std::endl; - return 1; - } - - // We run the io_service off in its own thread so that it operates - // completely asynchronously with respect to the rest of the program. - boost::asio::io_service io_service; - boost::asio::io_service::work work(io_service); - std::thread thread([&io_service](){ io_service.run(); }); - - get_daytime(io_service, argv[1]); - - io_service.stop(); - thread.join(); - } - catch (std::exception& e) - { - std::cerr << e.what() << std::endl; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp11/http/server/connection.cpp b/doc/html/boost_asio/example/cpp11/http/server/connection.cpp deleted file mode 100644 index 1996b1fccf..0000000000 --- a/doc/html/boost_asio/example/cpp11/http/server/connection.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// -// connection.cpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "connection.hpp" -#include <utility> -#include <vector> -#include "connection_manager.hpp" -#include "request_handler.hpp" - -namespace http { -namespace server { - -connection::connection(boost::asio::ip::tcp::socket socket, - connection_manager& manager, request_handler& handler) - : socket_(std::move(socket)), - connection_manager_(manager), - request_handler_(handler) -{ -} - -void connection::start() -{ - do_read(); -} - -void connection::stop() -{ - socket_.close(); -} - -void connection::do_read() -{ - auto self(shared_from_this()); - socket_.async_read_some(boost::asio::buffer(buffer_), - [this, self](boost::system::error_code ec, std::size_t bytes_transferred) - { - if (!ec) - { - request_parser::result_type result; - std::tie(result, std::ignore) = request_parser_.parse( - request_, buffer_.data(), buffer_.data() + bytes_transferred); - - if (result == request_parser::good) - { - request_handler_.handle_request(request_, reply_); - do_write(); - } - else if (result == request_parser::bad) - { - reply_ = reply::stock_reply(reply::bad_request); - do_write(); - } - else - { - do_read(); - } - } - else if (ec != boost::asio::error::operation_aborted) - { - connection_manager_.stop(shared_from_this()); - } - }); -} - -void connection::do_write() -{ - auto self(shared_from_this()); - boost::asio::async_write(socket_, reply_.to_buffers(), - [this, self](boost::system::error_code ec, std::size_t) - { - if (!ec) - { - // Initiate graceful connection closure. - boost::system::error_code ignored_ec; - socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, - ignored_ec); - } - - if (ec != boost::asio::error::operation_aborted) - { - connection_manager_.stop(shared_from_this()); - } - }); -} - -} // namespace server -} // namespace http diff --git a/doc/html/boost_asio/example/cpp11/http/server/connection.hpp b/doc/html/boost_asio/example/cpp11/http/server/connection.hpp deleted file mode 100644 index 3c87b6a7e9..0000000000 --- a/doc/html/boost_asio/example/cpp11/http/server/connection.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// connection.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_CONNECTION_HPP -#define HTTP_CONNECTION_HPP - -#include <array> -#include <memory> -#include <boost/asio.hpp> -#include "reply.hpp" -#include "request.hpp" -#include "request_handler.hpp" -#include "request_parser.hpp" - -namespace http { -namespace server { - -class connection_manager; - -/// Represents a single connection from a client. -class connection - : public std::enable_shared_from_this<connection> -{ -public: - connection(const connection&) = delete; - connection& operator=(const connection&) = delete; - - /// Construct a connection with the given socket. - explicit connection(boost::asio::ip::tcp::socket socket, - connection_manager& manager, request_handler& handler); - - /// Start the first asynchronous operation for the connection. - void start(); - - /// Stop all asynchronous operations associated with the connection. - void stop(); - -private: - /// Perform an asynchronous read operation. - void do_read(); - - /// Perform an asynchronous write operation. - void do_write(); - - /// Socket for the connection. - boost::asio::ip::tcp::socket socket_; - - /// The manager for this connection. - connection_manager& connection_manager_; - - /// The handler used to process the incoming request. - request_handler& request_handler_; - - /// Buffer for incoming data. - std::array<char, 8192> buffer_; - - /// The incoming request. - request request_; - - /// The parser for the incoming request. - request_parser request_parser_; - - /// The reply to be sent back to the client. - reply reply_; -}; - -typedef std::shared_ptr<connection> connection_ptr; - -} // namespace server -} // namespace http - -#endif // HTTP_CONNECTION_HPP diff --git a/doc/html/boost_asio/example/cpp11/http/server/connection_manager.cpp b/doc/html/boost_asio/example/cpp11/http/server/connection_manager.cpp deleted file mode 100644 index 5699ed1b26..0000000000 --- a/doc/html/boost_asio/example/cpp11/http/server/connection_manager.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// connection_manager.cpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "connection_manager.hpp" - -namespace http { -namespace server { - -connection_manager::connection_manager() -{ -} - -void connection_manager::start(connection_ptr c) -{ - connections_.insert(c); - c->start(); -} - -void connection_manager::stop(connection_ptr c) -{ - connections_.erase(c); - c->stop(); -} - -void connection_manager::stop_all() -{ - for (auto c: connections_) - c->stop(); - connections_.clear(); -} - -} // namespace server -} // namespace http diff --git a/doc/html/boost_asio/example/cpp11/http/server/connection_manager.hpp b/doc/html/boost_asio/example/cpp11/http/server/connection_manager.hpp deleted file mode 100644 index 400d14be6d..0000000000 --- a/doc/html/boost_asio/example/cpp11/http/server/connection_manager.hpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// connection_manager.hpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_CONNECTION_MANAGER_HPP -#define HTTP_CONNECTION_MANAGER_HPP - -#include <set> -#include "connection.hpp" - -namespace http { -namespace server { - -/// Manages open connections so that they may be cleanly stopped when the server -/// needs to shut down. -class connection_manager -{ -public: - connection_manager(const connection_manager&) = delete; - connection_manager& operator=(const connection_manager&) = delete; - - /// Construct a connection manager. - connection_manager(); - - /// Add the specified connection to the manager and start it. - void start(connection_ptr c); - - /// Stop the specified connection. - void stop(connection_ptr c); - - /// Stop all connections. - void stop_all(); - -private: - /// The managed connections. - std::set<connection_ptr> connections_; -}; - -} // namespace server -} // namespace http - -#endif // HTTP_CONNECTION_MANAGER_HPP diff --git a/doc/html/boost_asio/example/cpp11/http/server/header.hpp b/doc/html/boost_asio/example/cpp11/http/server/header.hpp deleted file mode 100644 index 524097edc6..0000000000 --- a/doc/html/boost_asio/example/cpp11/http/server/header.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// -// header.hpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_HEADER_HPP -#define HTTP_HEADER_HPP - -#include <string> - -namespace http { -namespace server { - -struct header -{ - std::string name; - std::string value; -}; - -} // namespace server -} // namespace http - -#endif // HTTP_HEADER_HPP diff --git a/doc/html/boost_asio/example/cpp11/http/server/main.cpp b/doc/html/boost_asio/example/cpp11/http/server/main.cpp deleted file mode 100644 index 4a280e55e2..0000000000 --- a/doc/html/boost_asio/example/cpp11/http/server/main.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// -// main.cpp -// ~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <iostream> -#include <string> -#include <boost/asio.hpp> -#include "server.hpp" - -int main(int argc, char* argv[]) -{ - try - { - // Check command line arguments. - if (argc != 4) - { - std::cerr << "Usage: http_server <address> <port> <doc_root>\n"; - std::cerr << " For IPv4, try:\n"; - std::cerr << " receiver 0.0.0.0 80 .\n"; - std::cerr << " For IPv6, try:\n"; - std::cerr << " receiver 0::0 80 .\n"; - return 1; - } - - // Initialise the server. - http::server::server s(argv[1], argv[2], argv[3]); - - // Run the server until stopped. - s.run(); - } - catch (std::exception& e) - { - std::cerr << "exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/example/cpp11/http/server/mime_types.cpp b/doc/html/boost_asio/example/cpp11/http/server/mime_types.cpp deleted file mode 100644 index c3528970ae..0000000000 --- a/doc/html/boost_asio/example/cpp11/http/server/mime_types.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// mime_types.cpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "mime_types.hpp" - -namespace http { -namespace server { -namespace mime_types { - -struct mapping -{ - const char* extension; - const char* mime_type; -} mappings[] = -{ - { "gif", "image/gif" }, - { "htm", "text/html" }, - { "html", "text/html" }, - { "jpg", "image/jpeg" }, - { "png", "image/png" } -}; - -std::string extension_to_type(const std::string& extension) -{ - for (mapping m: mappings) - { - if (m.extension == extension) - { - return m.mime_type; - } - } - - return "text/plain"; -} - -} // namespace mime_types -} // namespace server -} // namespace http diff --git a/doc/html/boost_asio/example/cpp11/http/server/mime_types.hpp b/doc/html/boost_asio/example/cpp11/http/server/mime_types.hpp deleted file mode 100644 index e5881f2e88..0000000000 --- a/doc/html/boost_asio/example/cpp11/http/server/mime_types.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// -// mime_types.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_MIME_TYPES_HPP -#define HTTP_MIME_TYPES_HPP - -#include <string> - -namespace http { -namespace server { -namespace mime_types { - -/// Convert a file extension into a MIME type. -std::string extension_to_type(const std::string& extension); - -} // namespace mime_types -} // namespace server -} // namespace http - -#endif // HTTP_MIME_TYPES_HPP diff --git a/doc/html/boost_asio/example/cpp11/http/server/reply.cpp b/doc/html/boost_asio/example/cpp11/http/server/reply.cpp deleted file mode 100644 index 5651d65f17..0000000000 --- a/doc/html/boost_asio/example/cpp11/http/server/reply.cpp +++ /dev/null @@ -1,255 +0,0 @@ -// -// reply.cpp -// ~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "reply.hpp" -#include <string> - -namespace http { -namespace server { - -namespace status_strings { - -const std::string ok = - "HTTP/1.0 200 OK\r\n"; -const std::string created = - "HTTP/1.0 201 Created\r\n"; -const std::string accepted = - "HTTP/1.0 202 Accepted\r\n"; -const std::string no_content = - "HTTP/1.0 204 No Content\r\n"; -const std::string multiple_choices = - "HTTP/1.0 300 Multiple Choices\r\n"; -const std::string moved_permanently = - "HTTP/1.0 301 Moved Permanently\r\n"; -const std::string moved_temporarily = - "HTTP/1.0 302 Moved Temporarily\r\n"; -const std::string not_modified = - "HTTP/1.0 304 Not Modified\r\n"; -const std::string bad_request = - "HTTP/1.0 400 Bad Request\r\n"; -const std::string unauthorized = - "HTTP/1.0 401 Unauthorized\r\n"; -const std::string forbidden = - "HTTP/1.0 403 Forbidden\r\n"; -const std::string not_found = - "HTTP/1.0 404 Not Found\r\n"; -const std::string internal_server_error = - "HTTP/1.0 500 Internal Server Error\r\n"; -const std::string not_implemented = - "HTTP/1.0 501 Not Implemented\r\n"; -const std::string bad_gateway = - "HTTP/1.0 502 Bad Gateway\r\n"; -const std::string service_unavailable = - "HTTP/1.0 503 Service Unavailable\r\n"; - -boost::asio::const_buffer to_buffer(reply::status_type status) -{ - switch (status) - { - case reply::ok: - return boost::asio::buffer(ok); - case reply::created: - return boost::asio::buffer(created); - case reply::accepted: - return boost::asio::buffer(accepted); - case reply::no_content: - return boost::asio::buffer(no_content); - case reply::multiple_choices: - return boost::asio::buffer(multiple_choices); - case reply::moved_permanently: - return boost::asio::buffer(moved_permanently); - case reply::moved_temporarily: - return boost::asio::buffer(moved_temporarily); - case reply::not_modified: - return boost::asio::buffer(not_modified); - case reply::bad_request: - return boost::asio::buffer(bad_request); - case reply::unauthorized: - return boost::asio::buffer(unauthorized); - case reply::forbidden: - return boost::asio::buffer(forbidden); - case reply::not_found: - return boost::asio::buffer(not_found); - case reply::internal_server_error: - return boost::asio::buffer(internal_server_error); - case reply::not_implemented: - return boost::asio::buffer(not_implemented); - case reply::bad_gateway: - return boost::asio::buffer(bad_gateway); - case reply::service_unavailable: - return boost::asio::buffer(service_unavailable); - default: - return boost::asio::buffer(internal_server_error); - } -} - -} // namespace status_strings - -namespace misc_strings { - -const char name_value_separator[] = { ':', ' ' }; -const char crlf[] = { '\r', '\n' }; - -} // namespace misc_strings - -std::vector<boost::asio::const_buffer> reply::to_buffers() -{ - std::vector<boost::asio::const_buffer> buffers; - buffers.push_back(status_strings::to_buffer(status)); - for (std::size_t i = 0; i < headers.size(); ++i) - { - header& h = headers[i]; - buffers.push_back(boost::asio::buffer(h.name)); - buffers.push_back(boost::asio::buffer(misc_strings::name_value_separator)); - buffers.push_back(boost::asio::buffer(h.value)); - buffers.push_back(boost::asio::buffer(misc_strings::crlf)); - } - buffers.push_back(boost::asio::buffer(misc_strings::crlf)); - buffers.push_back(boost::asio::buffer(content)); - return buffers; -} - -namespace stock_replies { - -const char ok[] = ""; -const char created[] = - "<html>" - "<head><title>Created</title></head>" - "<body><h1>201 Created</h1></body>" - "</html>"; -const char accepted[] = - "<html>" - "<head><title>Accepted</title></head>" - "<body><h1>202 Accepted</h1></body>" - "</html>"; -const char no_content[] = - "<html>" - "<head><title>No Content</title></head>" - "<body><h1>204 Content</h1></body>" - "</html>"; -const char multiple_choices[] = - "<html>" - "<head><title>Multiple Choices</title></head>" - "<body><h1>300 Multiple Choices</h1></body>" - "</html>"; -const char moved_permanently[] = - "<html>" - "<head><title>Moved Permanently</title></head>" - "<body><h1>301 Moved Permanently</h1></body>" - "</html>"; -const char moved_temporarily[] = - "<html>" - "<head><title>Moved Temporarily</title></head>" - "<body><h1>302 Moved Temporarily</h1></body>" - "</html>"; -const char not_modified[] = - "<html>" - "<head><title>Not Modified</title></head>" - "<body><h1>304 Not Modified</h1></body>" - "</html>"; -const char bad_request[] = - "<html>" - "<head><title>Bad Request</title></head>" - "<body><h1>400 Bad Request</h1></body>" - "</html>"; -const char unauthorized[] = - "<html>" - "<head><title>Unauthorized</title></head>" - "<body><h1>401 Unauthorized</h1></body>" - "</html>"; -const char forbidden[] = - "<html>" - "<head><title>Forbidden</title></head>" - "<body><h1>403 Forbidden</h1></body>" - "</html>"; -const char not_found[] = - "<html>" - "<head><title>Not Found</title></head>" - "<body><h1>404 Not Found</h1></body>" - "</html>"; -const char internal_server_error[] = - "<html>" - "<head><title>Internal Server Error</title></head>" - "<body><h1>500 Internal Server Error</h1></body>" - "</html>"; -const char not_implemented[] = - "<html>" - "<head><title>Not Implemented</title></head>" - "<body><h1>501 Not Implemented</h1></body>" - "</html>"; -const char bad_gateway[] = - "<html>" - "<head><title>Bad Gateway</title></head>" - "<body><h1>502 Bad Gateway</h1></body>" - "</html>"; -const char service_unavailable[] = - "<html>" - "<head><title>Service Unavailable</title></head>" - "<body><h1>503 Service Unavailable</h1></body>" - "</html>"; - -std::string to_string(reply::status_type status) -{ - switch (status) - { - case reply::ok: - return ok; - case reply::created: - return created; - case reply::accepted: - return accepted; - case reply::no_content: - return no_content; - case reply::multiple_choices: - return multiple_choices; - case reply::moved_permanently: - return moved_permanently; - case reply::moved_temporarily: - return moved_temporarily; - case reply::not_modified: - return not_modified; - case reply::bad_request: - return bad_request; - case reply::unauthorized: - return unauthorized; - case reply::forbidden: - return forbidden; - case reply::not_found: - return not_found; - case reply::internal_server_error: - return internal_server_error; - case reply::not_implemented: - return not_implemented; - case reply::bad_gateway: - return bad_gateway; - case reply::service_unavailable: - return service_unavailable; - default: - return internal_server_error; - } -} - -} // namespace stock_replies - -reply reply::stock_reply(reply::status_type status) -{ - reply rep; - rep.status = status; - rep.content = stock_replies::to_string(status); - rep.headers.resize(2); - rep.headers[0].name = "Content-Length"; - rep.headers[0].value = std::to_string(rep.content.size()); - rep.headers[1].name = "Content-Type"; - rep.headers[1].value = "text/html"; - return rep; -} - -} // namespace server -} // namespace http diff --git a/doc/html/boost_asio/example/cpp11/http/server/reply.hpp b/doc/html/boost_asio/example/cpp11/http/server/reply.hpp deleted file mode 100644 index f391121952..0000000000 --- a/doc/html/boost_asio/example/cpp11/http/server/reply.hpp +++ /dev/null @@ -1,64 +0,0 @@ -// -// reply.hpp -// ~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_REPLY_HPP -#define HTTP_REPLY_HPP - -#include <string> -#include <vector> -#include <boost/asio.hpp> -#include "header.hpp" - -namespace http { -namespace server { - -/// A reply to be sent to a client. -struct reply -{ - /// The status of the reply. - 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, - internal_server_error = 500, - not_implemented = 501, - bad_gateway = 502, - service_unavailable = 503 - } status; - - /// The headers to be included in the reply. - std::vector<header> headers; - - /// The content to be sent in the reply. - std::string content; - - /// Convert the reply into a vector of buffers. The buffers do not own the - /// underlying memory blocks, therefore the reply object must remain valid and - /// not be changed until the write operation has completed. - std::vector<boost::asio::const_buffer> to_buffers(); - - /// Get a stock reply. - static reply stock_reply(status_type status); -}; - -} // namespace server -} // namespace http - -#endif // HTTP_REPLY_HPP diff --git a/doc/html/boost_asio/example/cpp11/http/server/request.hpp b/doc/html/boost_asio/example/cpp11/http/server/request.hpp deleted file mode 100644 index 2a38f39e48..0000000000 --- a/doc/html/boost_asio/example/cpp11/http/server/request.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// -// request.hpp -// ~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_REQUEST_HPP -#define HTTP_REQUEST_HPP - -#include <string> -#include <vector> -#include "header.hpp" - -namespace http { -namespace server { - -/// A request received from a client. -struct request -{ - std::string method; - std::string uri; - int http_version_major; - int http_version_minor; - std::vector<header> headers; -}; - -} // namespace server -} // namespace http - -#endif // HTTP_REQUEST_HPP diff --git a/doc/html/boost_asio/example/cpp11/http/server/request_handler.cpp b/doc/html/boost_asio/example/cpp11/http/server/request_handler.cpp deleted file mode 100644 index 2fb5d2631f..0000000000 --- a/doc/html/boost_asio/example/cpp11/http/server/request_handler.cpp +++ /dev/null @@ -1,121 +0,0 @@ -// -// request_handler.cpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "request_handler.hpp" -#include <fstream> -#include <sstream> -#include <string> -#include "mime_types.hpp" -#include "reply.hpp" -#include "request.hpp" - -namespace http { -namespace server { - -request_handler::request_handler(const std::string& doc_root) - : doc_root_(doc_root) -{ -} - -void request_handler::handle_request(const request& req, reply& rep) -{ - // Decode url to path. - std::string request_path; - if (!url_decode(req.uri, request_path)) - { - rep = reply::stock_reply(reply::bad_request); - return; - } - - // Request path must be absolute and not contain "..". - if (request_path.empty() || request_path[0] != '/' - || request_path.find("..") != std::string::npos) - { - rep = reply::stock_reply(reply::bad_request); - return; - } - - // If path ends in slash (i.e. is a directory) then add "index.html". - if (request_path[request_path.size() - 1] == '/') - { - request_path += "index.html"; - } - - // Determine the file extension. - std::size_t last_slash_pos = request_path.find_last_of("/"); - std::size_t last_dot_pos = request_path.find_last_of("."); - std::string extension; - if (last_dot_pos != std::string::npos && last_dot_pos > last_slash_pos) - { - extension = request_path.substr(last_dot_pos + 1); - } - - // Open the file to send back. - std::string full_path = doc_root_ + request_path; - std::ifstream is(full_path.c_str(), std::ios::in | std::ios::binary); - if (!is) - { - rep = reply::stock_reply(reply::not_found); - return; - } - - // Fill out the reply to be sent to the client. - rep.status = reply::ok; - char buf[512]; - while (is.read(buf, sizeof(buf)).gcount() > 0) - rep.content.append(buf, is.gcount()); - rep.headers.resize(2); - rep.headers[0].name = "Content-Length"; - rep.headers[0].value = std::to_string(rep.content.size()); - rep.headers[1].name = "Content-Type"; - rep.headers[1].value = mime_types::extension_to_type(extension); -} - -bool request_handler::url_decode(const std::string& in, std::string& out) -{ - out.clear(); - out.reserve(in.size()); - for (std::size_t i = 0; i < in.size(); ++i) - { - if (in[i] == '%') - { - if (i + 3 <= in.size()) - { - int value = 0; - std::istringstream is(in.substr(i + 1, 2)); - if (is >> std::hex >> value) - { - out += static_cast<char>(value); - i += 2; - } - else - { - return false; - } - } - else - { - return false; - } - } - else if (in[i] == '+') - { - out += ' '; - } - else - { - out += in[i]; - } - } - return true; -} - -} // namespace server -} // namespace http diff --git a/doc/html/boost_asio/example/cpp11/http/server/request_handler.hpp b/doc/html/boost_asio/example/cpp11/http/server/request_handler.hpp deleted file mode 100644 index 95d1a6052f..0000000000 --- a/doc/html/boost_asio/example/cpp11/http/server/request_handler.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// -// request_handler.hpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_REQUEST_HANDLER_HPP -#define HTTP_REQUEST_HANDLER_HPP - -#include <string> - -namespace http { -namespace server { - -struct reply; -struct request; - -/// The common handler for all incoming requests. -class request_handler -{ -public: - request_handler(const request_handler&) = delete; - request_handler& operator=(const request_handler&) = delete; - - /// Construct with a directory containing files to be served. - explicit request_handler(const std::string& doc_root); - - /// Handle a request and produce a reply. - void handle_request(const request& req, reply& rep); - -private: - /// The directory containing the files to be served. - std::string doc_root_; - - /// Perform URL-decoding on a string. Returns false if the encoding was - /// invalid. - static bool url_decode(const std::string& in, std::string& out); -}; - -} // namespace server -} // namespace http - -#endif // HTTP_REQUEST_HANDLER_HPP diff --git a/doc/html/boost_asio/example/cpp11/http/server/request_parser.cpp b/doc/html/boost_asio/example/cpp11/http/server/request_parser.cpp deleted file mode 100644 index 57d50966c8..0000000000 --- a/doc/html/boost_asio/example/cpp11/http/server/request_parser.cpp +++ /dev/null @@ -1,315 +0,0 @@ -// -// request_parser.cpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "request_parser.hpp" -#include "request.hpp" - -namespace http { -namespace server { - -request_parser::request_parser() - : state_(method_start) -{ -} - -void request_parser::reset() -{ - state_ = method_start; -} - -request_parser::result_type request_parser::consume(request& req, char input) -{ - switch (state_) - { - case method_start: - if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return bad; - } - else - { - state_ = method; - req.method.push_back(input); - return indeterminate; - } - case method: - if (input == ' ') - { - state_ = uri; - return indeterminate; - } - else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return bad; - } - else - { - req.method.push_back(input); - return indeterminate; - } - case uri: - if (input == ' ') - { - state_ = http_version_h; - return indeterminate; - } - else if (is_ctl(input)) - { - return bad; - } - else - { - req.uri.push_back(input); - return indeterminate; - } - case http_version_h: - if (input == 'H') - { - state_ = http_version_t_1; - return indeterminate; - } - else - { - return bad; - } - case http_version_t_1: - if (input == 'T') - { - state_ = http_version_t_2; - return indeterminate; - } - else - { - return bad; - } - case http_version_t_2: - if (input == 'T') - { - state_ = http_version_p; - return indeterminate; - } - else - { - return bad; - } - case http_version_p: - if (input == 'P') - { - state_ = http_version_slash; - return indeterminate; - } - else - { - return bad; - } - case http_version_slash: - if (input == '/') - { - req.http_version_major = 0; - req.http_version_minor = 0; - state_ = http_version_major_start; - return indeterminate; - } - else - { - return bad; - } - case http_version_major_start: - if (is_digit(input)) - { - req.http_version_major = req.http_version_major * 10 + input - '0'; - state_ = http_version_major; - return indeterminate; - } - else - { - return bad; - } - case http_version_major: - if (input == '.') - { - state_ = http_version_minor_start; - return indeterminate; - } - else if (is_digit(input)) - { - req.http_version_major = req.http_version_major * 10 + input - '0'; - return indeterminate; - } - else - { - return bad; - } - case http_version_minor_start: - if (is_digit(input)) - { - req.http_version_minor = req.http_version_minor * 10 + input - '0'; - state_ = http_version_minor; - return indeterminate; - } - else - { - return bad; - } - case http_version_minor: - if (input == '\r') - { - state_ = expecting_newline_1; - return indeterminate; - } - else if (is_digit(input)) - { - req.http_version_minor = req.http_version_minor * 10 + input - '0'; - return indeterminate; - } - else - { - return bad; - } - case expecting_newline_1: - if (input == '\n') - { - state_ = header_line_start; - return indeterminate; - } - else - { - return bad; - } - case header_line_start: - if (input == '\r') - { - state_ = expecting_newline_3; - return indeterminate; - } - else if (!req.headers.empty() && (input == ' ' || input == '\t')) - { - state_ = header_lws; - return indeterminate; - } - else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return bad; - } - else - { - req.headers.push_back(header()); - req.headers.back().name.push_back(input); - state_ = header_name; - return indeterminate; - } - case header_lws: - if (input == '\r') - { - state_ = expecting_newline_2; - return indeterminate; - } - else if (input == ' ' || input == '\t') - { - return indeterminate; - } - else if (is_ctl(input)) - { - return bad; - } - else - { - state_ = header_value; - req.headers.back().value.push_back(input); - return indeterminate; - } - case header_name: - if (input == ':') - { - state_ = space_before_header_value; - return indeterminate; - } - else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return bad; - } - else - { - req.headers.back().name.push_back(input); - return indeterminate; - } - case space_before_header_value: - if (input == ' ') - { - state_ = header_value; - return indeterminate; - } - else - { - return bad; - } - case header_value: - if (input == '\r') - { - state_ = expecting_newline_2; - return indeterminate; - } - else if (is_ctl(input)) - { - return bad; - } - else - { - req.headers.back().value.push_back(input); - return indeterminate; - } - case expecting_newline_2: - if (input == '\n') - { - state_ = header_line_start; - return indeterminate; - } - else - { - return bad; - } - case expecting_newline_3: - return (input == '\n') ? good : bad; - default: - return bad; - } -} - -bool request_parser::is_char(int c) -{ - return c >= 0 && c <= 127; -} - -bool request_parser::is_ctl(int c) -{ - return (c >= 0 && c <= 31) || (c == 127); -} - -bool request_parser::is_tspecial(int c) -{ - switch (c) - { - case '(': case ')': case '<': case '>': case '@': - case ',': case ';': case ':': case '\\': case '"': - case '/': case '[': case ']': case '?': case '=': - case '{': case '}': case ' ': case '\t': - return true; - default: - return false; - } -} - -bool request_parser::is_digit(int c) -{ - return c >= '0' && c <= '9'; -} - -} // namespace server -} // namespace http diff --git a/doc/html/boost_asio/example/cpp11/http/server/request_parser.hpp b/doc/html/boost_asio/example/cpp11/http/server/request_parser.hpp deleted file mode 100644 index 1e84e80990..0000000000 --- a/doc/html/boost_asio/example/cpp11/http/server/request_parser.hpp +++ /dev/null @@ -1,96 +0,0 @@ -// -// request_parser.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_REQUEST_PARSER_HPP -#define HTTP_REQUEST_PARSER_HPP - -#include <tuple> - -namespace http { -namespace server { - -struct request; - -/// Parser for incoming requests. -class request_parser -{ -public: - /// Construct ready to parse the request method. - request_parser(); - - /// Reset to initial parser state. - void reset(); - - /// Result of parse. - enum result_type { good, bad, indeterminate }; - - /// Parse some data. The enum return value is good when a complete request has - /// been parsed, bad if the data is invalid, indeterminate when more data is - /// required. The InputIterator return value indicates how much of the input - /// has been consumed. - template <typename InputIterator> - std::tuple<result_type, InputIterator> parse(request& req, - InputIterator begin, InputIterator end) - { - while (begin != end) - { - result_type result = consume(req, *begin++); - if (result == good || result == bad) - return std::make_tuple(result, begin); - } - return std::make_tuple(indeterminate, begin); - } - -private: - /// Handle the next character of input. - result_type consume(request& req, char input); - - /// Check if a byte is an HTTP character. - static bool is_char(int c); - - /// Check if a byte is an HTTP control character. - static bool is_ctl(int c); - - /// Check if a byte is defined as an HTTP tspecial character. - static bool is_tspecial(int c); - - /// Check if a byte is a digit. - static bool is_digit(int c); - - /// The current state of the parser. - enum state - { - method_start, - method, - uri, - http_version_h, - http_version_t_1, - http_version_t_2, - http_version_p, - http_version_slash, - http_version_major_start, - http_version_major, - http_version_minor_start, - http_version_minor, - expecting_newline_1, - header_line_start, - header_lws, - header_name, - space_before_header_value, - header_value, - expecting_newline_2, - expecting_newline_3 - } state_; -}; - -} // namespace server -} // namespace http - -#endif // HTTP_REQUEST_PARSER_HPP diff --git a/doc/html/boost_asio/example/cpp11/http/server/server.cpp b/doc/html/boost_asio/example/cpp11/http/server/server.cpp deleted file mode 100644 index 25ad6b42c1..0000000000 --- a/doc/html/boost_asio/example/cpp11/http/server/server.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// -// server.cpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include "server.hpp" -#include <signal.h> -#include <utility> - -namespace http { -namespace server { - -server::server(const std::string& address, const std::string& port, - const std::string& doc_root) - : io_service_(), - signals_(io_service_), - acceptor_(io_service_), - connection_manager_(), - socket_(io_service_), - request_handler_(doc_root) -{ - // Register to handle the signals that indicate when the server should exit. - // It is safe to register for the same signal multiple times in a program, - // provided all registration for the specified signal is made through Asio. - signals_.add(SIGINT); - signals_.add(SIGTERM); -#if defined(SIGQUIT) - signals_.add(SIGQUIT); -#endif // defined(SIGQUIT) - - do_await_stop(); - - // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR). - boost::asio::ip::tcp::resolver resolver(io_service_); - boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve({address, port}); - acceptor_.open(endpoint.protocol()); - acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); - acceptor_.bind(endpoint); - acceptor_.listen(); - - do_accept(); -} - -void server::run() -{ - // The io_service::run() call will block until all asynchronous operations - // have finished. While the server is running, there is always at least one - // asynchronous operation outstanding: the asynchronous accept call waiting - // for new incoming connections. - io_service_.run(); -} - -void server::do_accept() -{ - acceptor_.async_accept(socket_, - [this](boost::system::error_code ec) - { - // Check whether the server was stopped by a signal before this - // completion handler had a chance to run. - if (!acceptor_.is_open()) - { - return; - } - - if (!ec) - { - connection_manager_.start(std::make_shared<connection>( - std::move(socket_), connection_manager_, request_handler_)); - } - - do_accept(); - }); -} - -void server::do_await_stop() -{ - signals_.async_wait( - [this](boost::system::error_code /*ec*/, int /*signo*/) - { - // The server is stopped by cancelling all outstanding asynchronous - // operations. Once all operations have finished the io_service::run() - // call will exit. - acceptor_.close(); - connection_manager_.stop_all(); - }); -} - -} // namespace server -} // namespace http diff --git a/doc/html/boost_asio/example/cpp11/http/server/server.hpp b/doc/html/boost_asio/example/cpp11/http/server/server.hpp deleted file mode 100644 index 39fc3a4750..0000000000 --- a/doc/html/boost_asio/example/cpp11/http/server/server.hpp +++ /dev/null @@ -1,67 +0,0 @@ -// -// server.hpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// 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 HTTP_SERVER_HPP -#define HTTP_SERVER_HPP - -#include <boost/asio.hpp> -#include <string> -#include "connection.hpp" -#include "connection_manager.hpp" -#include "request_handler.hpp" - -namespace http { -namespace server { - -/// The top-level class of the HTTP server. -class server -{ -public: - server(const server&) = delete; - server& operator=(const server&) = delete; - - /// Construct the server to listen on the specified TCP address and port, and - /// serve up files from the given directory. - explicit server(const std::string& address, const std::string& port, - const std::string& doc_root); - - /// Run the server's io_service loop. - void run(); - -private: - /// Perform an asynchronous accept operation. - void do_accept(); - - /// Wait for a request to stop the server. - void do_await_stop(); - - /// The io_service used to perform asynchronous operations. - boost::asio::io_service io_service_; - - /// The signal_set is used to register for process termination notifications. - boost::asio::signal_set signals_; - - /// Acceptor used to listen for incoming connections. - boost::asio::ip::tcp::acceptor acceptor_; - - /// The connection manager which owns all live connections. - connection_manager connection_manager_; - - /// The next socket to be accepted. - boost::asio::ip::tcp::socket socket_; - - /// The handler for all incoming requests. - request_handler request_handler_; -}; - -} // namespace server -} // namespace http - -#endif // HTTP_SERVER_HPP diff --git a/doc/html/boost_asio/example/cpp11/spawn/echo_server.cpp b/doc/html/boost_asio/example/cpp11/spawn/echo_server.cpp deleted file mode 100644 index ec15242ae4..0000000000 --- a/doc/html/boost_asio/example/cpp11/spawn/echo_server.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// -// echo_server.cpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include <boost/asio/io_service.hpp> -#include <boost/asio/ip/tcp.hpp> -#include <boost/asio/spawn.hpp> -#include <boost/asio/steady_timer.hpp> -#include <boost/asio/write.hpp> -#include <iostream> -#include <memory> - -using boost::asio::ip::tcp; - -class session : public std::enable_shared_from_this<session> -{ -public: - explicit session(tcp::socket socket) - : socket_(std::move(socket)), - timer_(socket_.get_io_service()), - strand_(socket_.get_io_service()) - { - } - - void go() - { - auto self(shared_from_this()); - boost::asio::spawn(strand_, - [this, self](boost::asio::yield_context yield) - { - try - { - char data[128]; - for (;;) - { - timer_.expires_from_now(std::chrono::seconds(10)); - std::size_t n = socket_.async_read_some(boost::asio::buffer(data), yield); - boost::asio::async_write(socket_, boost::asio::buffer(data, n), yield); - } - } - catch (std::exception& e) - { - socket_.close(); - timer_.cancel(); - } - }); - - boost::asio::spawn(strand_, - [this, self](boost::asio::yield_context yield) - { - while (socket_.is_open()) - { - boost::system::error_code ignored_ec; - timer_.async_wait(yield[ignored_ec]); - if (timer_.expires_from_now() <= std::chrono::seconds(0)) - socket_.close(); - } - }); - } - -private: - tcp::socket socket_; - boost::asio::steady_timer timer_; - boost::asio::io_service::strand strand_; -}; - -int main(int argc, char* argv[]) -{ - try - { - if (argc != 2) - { - std::cerr << "Usage: echo_server <port>\n"; - return 1; - } - - boost::asio::io_service io_service; - - boost::asio::spawn(io_service, - [&](boost::asio::yield_context yield) - { - tcp::acceptor acceptor(io_service, - tcp::endpoint(tcp::v4(), std::atoi(argv[1]))); - - for (;;) - { - boost::system::error_code ec; - tcp::socket socket(io_service); - acceptor.async_accept(socket, yield[ec]); - if (!ec) std::make_shared<session>(std::move(socket))->go(); - } - }); - - io_service.run(); - } - catch (std::exception& e) - { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return 0; -} diff --git a/doc/html/boost_asio/proactor.png b/doc/html/boost_asio/proactor.png Binary files differdeleted file mode 100644 index a0653b0106..0000000000 --- a/doc/html/boost_asio/proactor.png +++ /dev/null diff --git a/doc/html/boost_asio/sync_op.png b/doc/html/boost_asio/sync_op.png Binary files differdeleted file mode 100644 index 12324631bd..0000000000 --- a/doc/html/boost_asio/sync_op.png +++ /dev/null |