//
// process_per_connection.cpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2016 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 <asio/io_context.hpp>
#include <asio/ip/tcp.hpp>
#include <asio/signal_set.hpp>
#include <asio/write.hpp>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <cstdlib>
#include <iostream>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

using asio::ip::tcp;

class server
{
public:
  server(asio::io_context& io_context, unsigned short port)
    : io_context_(io_context),
      signal_(io_context, SIGCHLD),
      acceptor_(io_context, tcp::endpoint(tcp::v4(), port)),
      socket_(io_context)
  {
    start_signal_wait();
    start_accept();
  }

private:
  void start_signal_wait()
  {
    signal_.async_wait(boost::bind(&server::handle_signal_wait, this));
  }

  void handle_signal_wait()
  {
    // Only the parent process should check for this signal. We can determine
    // whether we are in the parent by checking if the acceptor is still open.
    if (acceptor_.is_open())
    {
      // Reap completed child processes so that we don't end up with zombies.
      int status = 0;
      while (waitpid(-1, &status, WNOHANG) > 0) {}

      start_signal_wait();
    }
  }

  void start_accept()
  {
    acceptor_.async_accept(socket_,
        boost::bind(&server::handle_accept, this, _1));
  }

  void handle_accept(const asio::error_code& ec)
  {
    if (!ec)
    {
      // Inform the io_context that we are about to fork. The io_context cleans
      // up any internal resources, such as threads, that may interfere with
      // forking.
      io_context_.notify_fork(asio::io_context::fork_prepare);

      if (fork() == 0)
      {
        // Inform the io_context that the fork is finished and that this is the
        // child process. The io_context uses this opportunity to create any
        // internal file descriptors that must be private to the new process.
        io_context_.notify_fork(asio::io_context::fork_child);

        // The child won't be accepting new connections, so we can close the
        // acceptor. It remains open in the parent.
        acceptor_.close();

        // The child process is not interested in processing the SIGCHLD signal.
        signal_.cancel();

        start_read();
      }
      else
      {
        // Inform the io_context that the fork is finished (or failed) and that
        // this is the parent process. The io_context uses this opportunity to
        // recreate any internal resources that were cleaned up during
        // preparation for the fork.
        io_context_.notify_fork(asio::io_context::fork_parent);

        socket_.close();
        start_accept();
      }
    }
    else
    {
      std::cerr << "Accept error: " << ec.message() << std::endl;
      start_accept();
    }
  }

  void start_read()
  {
    socket_.async_read_some(asio::buffer(data_),
        boost::bind(&server::handle_read, this, _1, _2));
  }

  void handle_read(const asio::error_code& ec, std::size_t length)
  {
    if (!ec)
      start_write(length);
  }

  void start_write(std::size_t length)
  {
    asio::async_write(socket_, asio::buffer(data_, length),
        boost::bind(&server::handle_write, this, _1));
  }

  void handle_write(const asio::error_code& ec)
  {
    if (!ec)
      start_read();
  }

  asio::io_context& io_context_;
  asio::signal_set signal_;
  tcp::acceptor acceptor_;
  tcp::socket socket_;
  boost::array<char, 1024> data_;
};

int main(int argc, char* argv[])
{
  try
  {
    if (argc != 2)
    {
      std::cerr << "Usage: process_per_connection <port>\n";
      return 1;
    }

    asio::io_context io_context;

    using namespace std; // For atoi.
    server s(io_context, atoi(argv[1]));

    io_context.run();
  }
  catch (std::exception& e)
  {
    std::cerr << "Exception: " << e.what() << std::endl;
  }
}
