1 //
2 // server.cpp
3 // ~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
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)
9 //
10 
11 #include "server.hpp"
12 #include <boost/bind.hpp>
13 
14 namespace http {
15 namespace server2 {
16 
server(const std::string & address,const std::string & port,const std::string & doc_root,std::size_t io_service_pool_size)17 server::server(const std::string& address, const std::string& port,
18     const std::string& doc_root, std::size_t io_service_pool_size)
19   : io_service_pool_(io_service_pool_size),
20     signals_(io_service_pool_.get_io_service()),
21     acceptor_(io_service_pool_.get_io_service()),
22     new_connection_(),
23     request_handler_(doc_root)
24 {
25   // Register to handle the signals that indicate when the server should exit.
26   // It is safe to register for the same signal multiple times in a program,
27   // provided all registration for the specified signal is made through Asio.
28   signals_.add(SIGINT);
29   signals_.add(SIGTERM);
30 #if defined(SIGQUIT)
31   signals_.add(SIGQUIT);
32 #endif // defined(SIGQUIT)
33   signals_.async_wait(boost::bind(&server::handle_stop, this));
34 
35   // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
36   boost::asio::ip::tcp::resolver resolver(acceptor_.get_io_service());
37   boost::asio::ip::tcp::resolver::query query(address, port);
38   boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
39   acceptor_.open(endpoint.protocol());
40   acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
41   acceptor_.bind(endpoint);
42   acceptor_.listen();
43 
44   start_accept();
45 }
46 
run()47 void server::run()
48 {
49   io_service_pool_.run();
50 }
51 
start_accept()52 void server::start_accept()
53 {
54   new_connection_.reset(new connection(
55         io_service_pool_.get_io_service(), request_handler_));
56   acceptor_.async_accept(new_connection_->socket(),
57       boost::bind(&server::handle_accept, this,
58         boost::asio::placeholders::error));
59 }
60 
handle_accept(const boost::system::error_code & e)61 void server::handle_accept(const boost::system::error_code& e)
62 {
63   if (!e)
64   {
65     new_connection_->start();
66   }
67 
68   start_accept();
69 }
70 
handle_stop()71 void server::handle_stop()
72 {
73   io_service_pool_.stop();
74 }
75 
76 } // namespace server2
77 } // namespace http
78