// 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/server/http_server_external_process.h"

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

#include <memory>
#include <vector>

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

#include "p2p/common/constants.h"
#include "p2p/common/server_message.h"
#include "p2p/common/struct_serializer.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 {

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);
  }

  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
