// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "p2p/server/http_server.h"

#include "p2p/common/constants.h"
#include "p2p/common/server_message.h"
#include "p2p/common/struct_serializer.h"

#include <glib.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>

#include <memory>
#include <vector>

#include <base/files/file_path.h>
#include <base/logging.h>

using std::string;
using std::vector;

using base::FilePath;

using p2p::util::P2PServerMessage;
using p2p::util::P2PServerMessageType;
using p2p::util::StructSerializerWatcher;

namespace p2p {

namespace server {

class HttpServerExternalProcess : public HttpServer {
 public:
  HttpServerExternalProcess(MetricsLibraryInterface* metrics_lib,
                            const FilePath& root_dir,
                            const FilePath& bin_dir,
                            uint16_t port);
  ~HttpServerExternalProcess();

  virtual bool Start();

  virtual bool Stop();

  virtual bool IsRunning();

  virtual uint16_t Port();

  virtual void SetNumConnectionsCallback(NumConnectionsCallback callback);

 private:
  // Helper function to update |num_connections_| and fire
  // |num_connections_callback_| if something has changed.
  void UpdateNumConnections(int num_connections);

  // Used for waking up and processing stdout from the child process.
  // If the output matches lines of the form "num-connections: %d",
  // calls UpdateNumConnections() with the parsed integer.

  static void OnMessageReceived(const P2PServerMessage& msg, void* user_data);

  // The metrics library object to report metrics to.
  MetricsLibraryInterface* metrics_lib_;

  // The path to serve files from.
  FilePath root_dir_;

  // The path to the http-server binary.
  FilePath http_binary_path_;

  // The TCP port number for the HTTP server is requested to run on. A value
  // of 0 means that the HTTP server should pick the port number.
  uint16_t requested_port_;

  // The TCP port number reported from the HTTP server. This is the actual
  // port number where the HTTP server is listening, while |requested_port_|
  // can be 0 to indicate the HTTP server should pick the port number.
  uint16_t port_;

  // The current number of connections to the HTTP server.
  int num_connections_;
  GPid pid_;
  int child_stdout_fd_;
  NumConnectionsCallback num_connections_callback_;

  // A message watch for child P2PServerMessages.
  std::unique_ptr<StructSerializerWatcher<P2PServerMessage>> child_watch_;

  DISALLOW_COPY_AND_ASSIGN(HttpServerExternalProcess);
};

HttpServerExternalProcess::HttpServerExternalProcess(
    MetricsLibraryInterface* metrics_lib,
    const FilePath& root_dir,
    const FilePath& bin_dir,
    uint16_t port)
    : metrics_lib_(metrics_lib),
      root_dir_(root_dir),
      http_binary_path_(bin_dir.Append(p2p::constants::kHttpServerBinaryName)),
      requested_port_(port),
      port_(0),
      num_connections_(0),
      pid_(0),
      child_stdout_fd_(-1) {}

HttpServerExternalProcess::~HttpServerExternalProcess() {
  child_watch_.reset(nullptr);

  if (child_stdout_fd_ != -1) {
    close(child_stdout_fd_);
  }
  if (pid_ != 0) {
    kill(pid_, SIGTERM);
  }
}

bool HttpServerExternalProcess::Start() {
  string command_line;

  if (pid_ != 0) {
    LOG(ERROR) << "Server is already running with pid " << pid_;
    return false;
  }
  CHECK_EQ(child_stdout_fd_, -1);

  vector<const char*> args;
  string dir_arg = string("--directory=") + root_dir_.value();
  string requested_port_arg = string("--port=") +
      std::to_string(requested_port_);

  args.push_back(http_binary_path_.value().c_str());
  args.push_back(dir_arg.c_str());
  args.push_back(requested_port_arg.c_str());
  args.push_back(NULL);

  GError* error = NULL;
  if (!g_spawn_async_with_pipes(NULL,  // working_dir
                                const_cast<gchar**>(args.data()),
                                NULL,  // envp
                                (GSpawnFlags) 0,
                                NULL,
                                NULL,  // child_setup, user_data
                                &pid_,
                                NULL,  // standard_input
                                &child_stdout_fd_,
                                NULL,  // standard_error
                                &error)) {
    LOG(ERROR) << "Error launching process: " << error->message;
    g_error_free(error);
    return false;
  }

  // Setup the watch class for child messages.
  child_watch_.reset(new StructSerializerWatcher<P2PServerMessage>(
      child_stdout_fd_, OnMessageReceived, reinterpret_cast<void*>(this)));

  return true;
}

void HttpServerExternalProcess::OnMessageReceived(const P2PServerMessage& msg,
                                                  void* user_data) {
  HttpServerExternalProcess* server =
      reinterpret_cast<HttpServerExternalProcess*>(user_data);
  P2PServerMessageType message_type;
  string metric;

  if (!p2p::util::ValidP2PServerMessageMagic(msg) ||
      !p2p::util::ParseP2PServerMessageType(msg.message_type, &message_type)) {
    LOG(ERROR) << "Received invalid message: " << p2p::util::ToString(msg);
    LOG(ERROR) << "Attempting to restarting P2P service.";
    // Stop the child and abort ourselves.
    server->Stop();
    exit(1);

    // Just in case exit(2) returns.
    return;
  }

  switch (message_type) {
    case p2p::util::kP2PServerNumConnections:
      if (msg.value >= 0)
        server->UpdateNumConnections(msg.value);
      break;

    case p2p::util::kP2PServerRequestResult:
      metric = "P2P.Server.RequestResult";
      p2p::util::P2PServerRequestResult req_res;
      if (p2p::util::ParseP2PServerRequestResult(msg.value, &req_res)) {
        LOG(INFO) << "Uploading " << ToString(req_res)
                  << " for metric " <<  metric;
        server->metrics_lib_->SendEnumToUMA(metric,
                                   req_res,
                                   p2p::util::kNumP2PServerRequestResults);
      } else {
        LOG(ERROR) << "Received invalid message: " << p2p::util::ToString(msg);
      }
      break;

    case p2p::util::kP2PServerServedSuccessfullyMB:
      metric = "P2P.Server.ContentServedSuccessfullyMB";
      LOG(INFO) << "Uploading " << msg.value
                << " (count) for metric " <<  metric;
      server->metrics_lib_->SendToUMA(
          metric, msg.value, 0 /* min */, 1000 /* max */, 50);
      break;

    case p2p::util::kP2PServerServedInterruptedMB:
      metric = "P2P.Server.ContentServedInterruptedMB";
      LOG(INFO) << "Uploading " << msg.value
                << " (count) for metric " <<  metric;
      server->metrics_lib_->SendToUMA(
          metric, msg.value, 0 /* min */, 1000 /* max */, 50);
      break;

    case p2p::util::kP2PServerRangeBeginPercentage:
      metric = "P2P.Server.RangeBeginPercentage";
      LOG(INFO) << "Uploading " << msg.value
                << " (count) for metric " <<  metric;
      server->metrics_lib_->SendToUMA(
          metric, msg.value, 0 /* min */, 100 /* max */, 100);
      break;

    case p2p::util::kP2PServerDownloadSpeedKBps:
      metric = "P2P.Server.DownloadSpeedKBps";
      LOG(INFO) << "Uploading " << msg.value
                << " (count) for metric " <<  metric;
      server->metrics_lib_->SendToUMA(
          metric, msg.value, 0 /* min */, 10000 /* max */, 100);
      break;

    case p2p::util::kP2PServerPeakDownloadSpeedKBps:
      metric = "P2P.Server.PeakDownloadSpeedKBps";
      LOG(INFO) << "Uploading " << msg.value
                << " (count) for metric " <<  metric;
      server->metrics_lib_->SendToUMA(
          metric, msg.value, 0 /* min */, 10000 /* max */, 100);
      break;

    case p2p::util::kP2PServerClientCount:
      metric = "P2P.Server.ClientCount";
      LOG(INFO) << "Uploading " << msg.value
                << " (count) for metric " <<  metric;
      server->metrics_lib_->SendToUMA(
          metric, msg.value, 0 /* min */, 50 /* max */, 50);
      break;

    case p2p::util::kP2PServerPortNumber:
      server->port_ = msg.value;
      break;

    // ParseP2PServerMessageType ensures this case is not reached.
    case p2p::util::kNumP2PServerMessageTypes:
      NOTREACHED();
  }
}

void HttpServerExternalProcess::UpdateNumConnections(int num_connections) {
  if (num_connections_ == num_connections)
    return;

  num_connections_ = num_connections;

  if (!num_connections_callback_.is_null())
    num_connections_callback_.Run(num_connections);
}

bool HttpServerExternalProcess::Stop() {
  if (pid_ == 0) {
    LOG(ERROR) << "Server is not running";
    return false;
  }

  child_watch_.reset(nullptr);

  if (child_stdout_fd_ != -1) {
    close(child_stdout_fd_);
  }
  child_stdout_fd_ = -1;

  if (pid_ != 0) {
    kill(pid_, SIGTERM);
  }
  pid_ = 0;

  port_ = 0;

  return true;
}

bool HttpServerExternalProcess::IsRunning() { return pid_ != 0; }

uint16_t HttpServerExternalProcess::Port() { return port_; }

void HttpServerExternalProcess::SetNumConnectionsCallback(
    NumConnectionsCallback callback) {
  num_connections_callback_ = callback;
}

// ----------------------------------------------------------------------------

HttpServer* HttpServer::Construct(MetricsLibraryInterface* metrics_lib,
                                  const FilePath& root_dir,
                                  const FilePath& bin_dir,
                                  uint16_t port) {
  return new HttpServerExternalProcess(metrics_lib, root_dir, bin_dir, port);
}

}  // namespace server

}  // namespace p2p
