]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/asio/example/cpp03/http/server4/server.cpp
5 // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
12 #include "request.hpp"
18 server::server(boost::asio::io_context
& io_context
,
19 const std::string
& address
, const std::string
& port
,
20 boost::function
<void(const request
&, reply
&)> request_handler
)
21 : request_handler_(request_handler
)
23 tcp::resolver
resolver(io_context
);
24 boost::asio::ip::tcp::endpoint endpoint
=
25 *resolver
.resolve(address
, port
).begin();
26 acceptor_
.reset(new tcp::acceptor(io_context
, endpoint
));
29 // Enable the pseudo-keywords reenter, yield and fork.
30 #include <boost/asio/yield.hpp>
32 void server::operator()(boost::system::error_code ec
, std::size_t length
)
34 // In this example we keep the error handling code in one place by
35 // hoisting it outside the coroutine. An alternative approach would be to
36 // check the value of ec after each yield for an asynchronous operation.
39 // On reentering a coroutine, control jumps to the location of the last
40 // yield or fork. The argument to the "reenter" pseudo-keyword can be a
41 // pointer or reference to an object of type coroutine.
44 // Loop to accept incoming connections.
47 // Create a new socket for the next incoming connection.
48 socket_
.reset(new tcp::socket(acceptor_
->get_executor()));
50 // Accept a new connection. The "yield" pseudo-keyword saves the current
51 // line number and exits the coroutine's "reenter" block. We use the
52 // server coroutine as the completion handler for the async_accept
53 // operation. When the asynchronous operation completes, the io_context
54 // invokes the function call operator, we "reenter" the coroutine, and
55 // then control resumes at the following line.
56 yield acceptor_
->async_accept(*socket_
, *this);
58 // We "fork" by cloning a new server coroutine to handle the connection.
59 // After forking we have a parent coroutine and a child coroutine. Both
60 // parent and child continue execution at the following line. They can
61 // be distinguished using the functions coroutine::is_parent() and
62 // coroutine::is_child().
65 // The parent continues looping to accept the next incoming connection.
66 // The child exits the loop and processes the connection.
67 } while (is_parent());
69 // Create the objects needed to receive a request on the connection.
70 buffer_
.reset(new boost::array
<char, 8192>);
71 request_
.reset(new request
);
73 // Loop until a complete request (or an invalid one) has been received.
76 // Receive some more data. When control resumes at the following line,
77 // the ec and length parameters reflect the result of the asynchronous
79 yield socket_
->async_read_some(boost::asio::buffer(*buffer_
), *this);
81 // Parse the data we just received.
82 boost::tie(valid_request_
, boost::tuples::ignore
)
83 = request_parser_
.parse(*request_
,
84 buffer_
->data(), buffer_
->data() + length
);
86 // An indeterminate result means we need more data, so keep looping.
87 } while (boost::indeterminate(valid_request_
));
89 // Create the reply object that will be sent back to the client.
90 reply_
.reset(new reply
);
94 // A valid request was received. Call the user-supplied function object
95 // to process the request and compose a reply.
96 request_handler_(*request_
, *reply_
);
100 // The request was invalid.
101 *reply_
= reply::stock_reply(reply::bad_request
);
104 // Send the reply back to the client.
105 yield
boost::asio::async_write(*socket_
, reply_
->to_buffers(), *this);
107 // Initiate graceful connection closure.
108 socket_
->shutdown(tcp::socket::shutdown_both
, ec
);
112 // If an error occurs then the coroutine is not reentered. Consequently, no
113 // new asynchronous operations are started. This means that all shared_ptr
114 // references will disappear and the resources associated with the coroutine
115 // will be destroyed automatically after this function call returns.
118 // Disable the pseudo-keywords reenter, yield and fork.
119 #include <boost/asio/unyield.hpp>
121 } // namespace server4