//
// server.cpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2015 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 "request.hpp"
#include "reply.hpp"

namespace http {
namespace server4 {

server::server(asio::io_context& io_context,
    const std::string& address, const std::string& port,
    boost::function<void(const request&, reply&)> request_handler)
  : request_handler_(request_handler)
{
  tcp::resolver resolver(io_context);
  asio::ip::tcp::endpoint endpoint =
    *resolver.resolve(address, port).begin();
  acceptor_.reset(new tcp::acceptor(io_context, endpoint));
}

// Enable the pseudo-keywords reenter, yield and fork.
#include <asio/yield.hpp>

void server::operator()(asio::error_code ec, std::size_t length)
{
  // In this example we keep the error handling code in one place by
  // hoisting it outside the coroutine. An alternative approach would be to
  // check the value of ec after each yield for an asynchronous operation.
  if (!ec)
  {
    // On reentering a coroutine, control jumps to the location of the last
    // yield or fork. The argument to the "reenter" pseudo-keyword can be a
    // pointer or reference to an object of type coroutine.
    reenter (this)
    {
      // Loop to accept incoming connections.
      do
      {
        // Create a new socket for the next incoming connection.
        socket_.reset(new tcp::socket(acceptor_->get_executor().context()));

        // Accept a new connection. The "yield" pseudo-keyword saves the current
        // line number and exits the coroutine's "reenter" block. We use the
        // server coroutine as the completion handler for the async_accept
        // operation. When the asynchronous operation completes, the io_context
        // invokes the function call operator, we "reenter" the coroutine, and
        // then control resumes at the following line.
        yield acceptor_->async_accept(*socket_, *this);

        // We "fork" by cloning a new server coroutine to handle the connection.
        // After forking we have a parent coroutine and a child coroutine. Both
        // parent and child continue execution at the following line. They can
        // be distinguished using the functions coroutine::is_parent() and
        // coroutine::is_child().
        fork server(*this)();

        // The parent continues looping to accept the next incoming connection.
        // The child exits the loop and processes the connection.
      } while (is_parent());

      // Create the objects needed to receive a request on the connection.
      buffer_.reset(new boost::array<char, 8192>);
      request_.reset(new request);

      // Loop until a complete request (or an invalid one) has been received.
      do
      {
        // Receive some more data. When control resumes at the following line,
        // the ec and length parameters reflect the result of the asynchronous
        // operation.
        yield socket_->async_read_some(asio::buffer(*buffer_), *this);

        // Parse the data we just received.
        boost::tie(valid_request_, boost::tuples::ignore)
          = request_parser_.parse(*request_,
              buffer_->data(), buffer_->data() + length);

        // An indeterminate result means we need more data, so keep looping.
      } while (boost::indeterminate(valid_request_));

      // Create the reply object that will be sent back to the client.
      reply_.reset(new reply);

      if (valid_request_)
      {
        // A valid request was received. Call the user-supplied function object
        // to process the request and compose a reply.
        request_handler_(*request_, *reply_);
      }
      else
      {
        // The request was invalid.
        *reply_ = reply::stock_reply(reply::bad_request);
      }

      // Send the reply back to the client.
      yield asio::async_write(*socket_, reply_->to_buffers(), *this);

      // Initiate graceful connection closure.
      socket_->shutdown(tcp::socket::shutdown_both, ec);
    }
  }

  // If an error occurs then the coroutine is not reentered. Consequently, no
  // new asynchronous operations are started. This means that all shared_ptr
  // references will disappear and the resources associated with the coroutine
  // will be destroyed automatically after this function call returns.
}

// Disable the pseudo-keywords reenter, yield and fork.
#include <asio/unyield.hpp>

} // namespace server4
} // namespace http
