/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2016, Regents of the University of California.
 *
 * This file is part of ChronoShare, a decentralized file sharing application over NDN.
 *
 * ChronoShare is free software: you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation, either
 * version 3 of the License, or (at your option) any later version.
 *
 * ChronoShare is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received copies of the GNU General Public License along with
 * ChronoShare, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ChronoShare authors and contributors.
 */
//
// server.cpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2012 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 "core/logging.hpp"

#include <signal.h>

namespace http {
namespace server {

using namespace ndn::chronoshare;

INIT_LOGGER("HttpServer");

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(std::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();

  _LOG_DEBUG("Listen on [" << address << ": " << port << "] with doc_root = " << doc_root);
}

server::~server()
{
  // handle_stop();
}

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(),
                         std::bind(&server::handle_accept, this, std::placeholders::_1));
}

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();
  // although they say io_service::run() would stop, but it didn't happen..
  // the thread join was blocking, waiting for io_service::run() to finish
  // even after handle_stop() call..
  // so just force it quit, no harm here.
  io_service_.stop();
}

} // namespace server
} // namespace http
