//----------------------------------------------------------------------------
// Hi all,
// I have a program like below.
// Two questions:
//  1. The program can process multi connections, each connection is a
//  session that has some states. The program should catch signal SIGINT
//  and SIGTERM, then each session should do different actions according to
//  their state. But how to do this? Does it have to have a connection
//  manager?
//
//  2. When the function Server::handle_accept is called, a SessionController
//  object will be created. The constructor of SessionController will apply for
//  some resource, if failed, the constructor would throw an exception.
//  So, if there is an exception thrown, what should we do? I don't want to
//  exit the process, may be the resource will be available after some seconds,
//  then I hope the program continue to accept new connections.
//----------------------------------------------------------------------------
class SessionController;
typedef shared_ptr<SessionController> SessionController_Ptr;

Server::Server(boost::asio::io_service& io_service)
    : io_service_(io_service),
    acceptor_(io_service, tcp::endpoint(
                boost::asio::ip::address::from_string("0.0.0.0"), 10001))
{
    SessionController_Ptr new_connection(new SessionController(io_service_));
    acceptor_.async_accept(new_connection->socket(),
            boost::bind(&Server::handle_accept, this, new_connection,
                boost::asio::placeholders::error));
}

//----------------------------------------------------------------------------
void Server::handle_accept(SessionController_Ptr new_connection,
        const boost::system::error_code& error)
{
    if (!error)
    {
        new_connection->start();
        try
        {
            new_connection.reset(new SessionController(io_service_));
            acceptor_.async_accept(new_connection->socket(),
                    boost::bind(&Server::handle_accept,
                        this, new_connection, boost::asio::placeholders::error));
        }
        catch (...)
        {
            // What should we do?
        }
    }
}