JayBeams  0.1
Another project to have fun coding.
acceptor.cpp
Go to the documentation of this file.
1 #include "jb/ehs/acceptor.hpp"
2 
3 #include <jb/log.hpp>
4 
5 namespace jb {
6 namespace ehs {
7 
9  boost::asio::io_service& io, boost::asio::ip::tcp::endpoint const& ep,
10  std::shared_ptr<request_dispatcher> dispatcher)
11  : acceptor_(io)
12  , dispatcher_(dispatcher)
13  , sock_(io) {
14  acceptor_.open(ep.protocol());
15  acceptor_.bind(ep);
16  acceptor_.listen(boost::asio::socket_base::max_connections);
17  // ... schedule an asynchronous accept() operation into the new
18  // socket ...
19  acceptor_.async_accept(sock_, [this](boost::system::error_code const& ec) {
20  this->on_accept(ec);
21  });
22  JB_LOG(info) << "accepting connections on " << ep << " [" << local_endpoint()
23  << "]";
24 }
25 
27  acceptor_.close();
28  JB_LOG(info) << "shutdown: acceptor close successful";
29 }
30 
31 void acceptor::on_accept(boost::system::error_code const& ec) {
32  if (not acceptor_.is_open()) {
33  // The accept socket is closed, this is a normal condition, used
34  // to shutdown the application, so we simply return and do not
35  // schedule any additional work ...
36  JB_LOG(info) << "on_accept: acceptor is not open";
37  dispatcher_->count_accept_closed();
38  return;
39  }
40  // ... move the newly created socket to a stack variable so we can
41  // schedule a new asynchronous accept ...
42  boost::asio::ip::tcp::socket sock(std::move(sock_));
43  if (not ec) {
44  // ... create a new connection for the newly created socket and
45  // schedule it ...
46  auto c = std::make_shared<connection>(std::move(sock), dispatcher_);
47  c->run();
48  dispatcher_->count_accept_ok();
49  } else {
50  // ... this is a very rare condition, the acceptor is still open,
51  // but the accept() call failed, typically that would indicate a
52  // temporary error, such as running out of file descriptors. We
53  // log the issue, increment the counters, and reschedule another
54  // async accept. Unit testing this condition reliably is
55  // extremely hard, so the code is unreached in tests ...
56  JB_LOG(info) << "on_accept: " << ec.message() << " ["
57  << ec.category().name() << "/" << ec.value() << "]";
58  dispatcher_->count_accept_error();
59  }
60  // ... error or not, schedule a new accept() request ..
61  acceptor_.async_accept(sock_, [this](boost::system::error_code const& ec) {
62  this->on_accept(ec);
63  });
64 }
65 
66 } // namespace ehs
67 } // namespace jb
void shutdown()
Gracefully shutdown the acceptor.
Definition: acceptor.cpp:26
std::shared_ptr< request_dispatcher > dispatcher_
Definition: acceptor.hpp:47
void on_accept(boost::system::error_code const &ec)
Handle a completed asynchronous accept() call.
Definition: acceptor.cpp:31
boost::asio::ip::tcp::socket sock_
Definition: acceptor.hpp:49
boost::asio::ip::tcp::endpoint local_endpoint() const
Return the local listening endpoint.
Definition: acceptor.hpp:32
acceptor(boost::asio::io_service &io, boost::asio::ip::tcp::endpoint const &ep, std::shared_ptr< request_dispatcher > dispatcher)
Create an acceptor a Embedded HTTP Server and start accepting connections.
Definition: acceptor.cpp:8
#define JB_LOG(lvl)
Definition: log.hpp:70
boost::asio::ip::tcp::acceptor acceptor_
Definition: acceptor.hpp:46
The top-level namespace for the JayBeams library.
Definition: as_hhmmss.hpp:7