//
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "shill/passive_link_monitor.h"

#include <string>

#include <base/bind.h>

#include "shill/connection.h"
#include "shill/event_dispatcher.h"
#include "shill/logging.h"
#include "shill/net/arp_client.h"
#include "shill/net/arp_packet.h"
#include "shill/net/byte_string.h"

using base::Bind;
using base::Unretained;
using std::string;

namespace shill {

namespace Logging {
static auto kModuleLogScope = ScopeLogger::kLink;
static string ObjectID(Connection* c) { return c->interface_name(); }
}

namespace {

// The number of milliseconds per cycle.
constexpr int kCyclePeriodMilliseconds = 25000;

// Minimum number of ARP requests expected per cycle.
constexpr int kMinArpRequestsPerCycle = 5;

}  // namespace

// static.
const int PassiveLinkMonitor::kDefaultMonitorCycles = 40;

PassiveLinkMonitor::PassiveLinkMonitor(const ConnectionRefPtr& connection,
                                       EventDispatcher* dispatcher,
                                       const ResultCallback& result_callback)
    : connection_(connection),
      dispatcher_(dispatcher),
      // Connection is not provided when this is used as a mock for testing
      // purpose.
      arp_client_(
          new ArpClient(connection ? connection->interface_index() : 0)),
      result_callback_(result_callback),
      num_cycles_to_monitor_(kDefaultMonitorCycles),
      num_requests_received_(0),
      num_cycles_passed_(0) {
}

PassiveLinkMonitor::~PassiveLinkMonitor() {
  Stop();
}

bool PassiveLinkMonitor::Start(int num_cycles) {
  SLOG(connection_.get(), 2) << "In " << __func__ << ".";
  Stop();

  if (!StartArpClient()) {
    return false;
  }
  // Start the monitor cycle.
  monitor_cycle_timeout_callback_.Reset(
      Bind(&PassiveLinkMonitor::CycleTimeoutHandler, Unretained(this)));
  dispatcher_->PostDelayedTask(FROM_HERE,
                               monitor_cycle_timeout_callback_.callback(),
                               kCyclePeriodMilliseconds);
  num_cycles_to_monitor_ = num_cycles;
  return true;
}

void PassiveLinkMonitor::Stop() {
  SLOG(connection_.get(), 2) << "In " << __func__ << ".";
  StopArpClient();
  num_requests_received_ = 0;
  num_cycles_passed_ = 0;
  monitor_cycle_timeout_callback_.Cancel();
  monitor_completed_callback_.Cancel();
}

bool PassiveLinkMonitor::StartArpClient() {
  if (!arp_client_->StartRequestListener()) {
    return false;
  }
  receive_request_handler_.reset(
      dispatcher_->CreateReadyHandler(
          arp_client_->socket(),
          IOHandler::kModeInput,
          Bind(&PassiveLinkMonitor::ReceiveRequest, Unretained(this))));
  return true;
}

void PassiveLinkMonitor::StopArpClient() {
  arp_client_->Stop();
  receive_request_handler_.reset();
}

void PassiveLinkMonitor::ReceiveRequest(int fd) {
  SLOG(connection_.get(), 2) << "In " << __func__ << ".";
  ArpPacket packet;
  ByteString sender;

  if (!arp_client_->ReceivePacket(&packet, &sender)) {
    return;
  }

  if (packet.IsReply()) {
    SLOG(connection_.get(), 4) << "This is not a request packet.  Ignoring.";
    return;
  }

  num_requests_received_++;
  // Stop ARP client if we receive enough requests for the current cycle.
  if (num_requests_received_ >= kMinArpRequestsPerCycle) {
    StopArpClient();
  }
}

void PassiveLinkMonitor::CycleTimeoutHandler() {
  bool status = false;
  if (num_requests_received_ >= kMinArpRequestsPerCycle) {
    num_requests_received_ = 0;
    num_cycles_passed_++;
    if (num_cycles_passed_ < num_cycles_to_monitor_) {
      // Continue on with the next cycle.
      StartArpClient();
      dispatcher_->PostDelayedTask(FROM_HERE,
                                   monitor_cycle_timeout_callback_.callback(),
                                   kCyclePeriodMilliseconds);
      return;
    }
    // Monitor completed.
    status = true;
  }

  // Post a task to perform cleanup and invoke result callback, since this
  // function is invoked from the callback that will be cancelled during
  // cleanup.
  monitor_completed_callback_.Reset(
      Bind(&PassiveLinkMonitor::MonitorCompleted, Unretained(this), status));
  dispatcher_->PostTask(FROM_HERE, monitor_completed_callback_.callback());
}

void PassiveLinkMonitor::MonitorCompleted(bool status) {
  // Stop the monitoring before invoking result callback, so that the ARP client
  // is stopped by the time result callback is invoked.
  Stop();
  result_callback_.Run(status);
}

}  // namespace shill
