// 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 "shill/socket_info_reader.h"

#include <algorithm>
#include <limits>

#include <base/strings/string_number_conversions.h>
#include <base/strings/string_split.h>

#include "shill/file_reader.h"
#include "shill/logging.h"

using base::FilePath;
using std::string;
using std::vector;

namespace shill {

namespace Logging {
static auto kModuleLogScope = ScopeLogger::kLink;
static string ObjectID(SocketInfoReader *s) { return "(socket_info_reader)"; }
}

namespace {

const char kTcpv4SocketInfoFilePath[] = "/proc/net/tcp";
const char kTcpv6SocketInfoFilePath[] = "/proc/net/tcp6";

}  // namespace

SocketInfoReader::SocketInfoReader() {}

SocketInfoReader::~SocketInfoReader() {}

FilePath SocketInfoReader::GetTcpv4SocketInfoFilePath() const {
  return FilePath(kTcpv4SocketInfoFilePath);
}

FilePath SocketInfoReader::GetTcpv6SocketInfoFilePath() const {
  return FilePath(kTcpv6SocketInfoFilePath);
}

bool SocketInfoReader::LoadTcpSocketInfo(vector<SocketInfo> *info_list) {
  info_list->clear();
  bool v4_loaded = AppendSocketInfo(GetTcpv4SocketInfoFilePath(), info_list);
  bool v6_loaded = AppendSocketInfo(GetTcpv6SocketInfoFilePath(), info_list);
  // Return true if we can load either /proc/net/tcp or /proc/net/tcp6
  // successfully.
  return v4_loaded || v6_loaded;
}

bool SocketInfoReader::AppendSocketInfo(const FilePath &info_file_path,
                                        vector<SocketInfo> *info_list) {
  FileReader file_reader;
  if (!file_reader.Open(info_file_path)) {
    SLOG(this, 2) << __func__ << ": Failed to open '"
                  << info_file_path.value() << "'.";
    return false;
  }

  string line;
  while (file_reader.ReadLine(&line)) {
    SocketInfo socket_info;
    if (ParseSocketInfo(line, &socket_info))
      info_list->push_back(socket_info);
  }
  return true;
}

bool SocketInfoReader::ParseSocketInfo(const string &input,
                                       SocketInfo *socket_info) {
  vector<string> tokens;
  base::SplitStringAlongWhitespace(input, &tokens);
  if (tokens.size() < 10) {
    return false;
  }

  IPAddress ip_address(IPAddress::kFamilyUnknown);
  uint16_t port = 0;

  if (!ParseIPAddressAndPort(tokens[1], &ip_address, &port)) {
    return false;
  }
  socket_info->set_local_ip_address(ip_address);
  socket_info->set_local_port(port);

  if (!ParseIPAddressAndPort(tokens[2], &ip_address, &port)) {
    return false;
  }
  socket_info->set_remote_ip_address(ip_address);
  socket_info->set_remote_port(port);

  SocketInfo::ConnectionState connection_state =
      SocketInfo::kConnectionStateUnknown;
  if (!ParseConnectionState(tokens[3], &connection_state)) {
    return false;
  }
  socket_info->set_connection_state(connection_state);

  uint64_t transmit_queue_value = 0, receive_queue_value = 0;
  if (!ParseTransimitAndReceiveQueueValues(
      tokens[4], &transmit_queue_value, &receive_queue_value)) {
    return false;
  }
  socket_info->set_transmit_queue_value(transmit_queue_value);
  socket_info->set_receive_queue_value(receive_queue_value);

  SocketInfo::TimerState timer_state = SocketInfo::kTimerStateUnknown;
  if (!ParseTimerState(tokens[5], &timer_state)) {
    return false;
  }
  socket_info->set_timer_state(timer_state);

  return true;
}

bool SocketInfoReader::ParseIPAddressAndPort(
    const string &input, IPAddress *ip_address, uint16_t *port) {
  vector<string> tokens;

  base::SplitString(input, ':', &tokens);
  if (tokens.size() != 2 ||
      !ParseIPAddress(tokens[0], ip_address) ||
      !ParsePort(tokens[1], port)) {
    return false;
  }

  return true;
}

bool SocketInfoReader::ParseIPAddress(const string &input,
                                      IPAddress *ip_address) {
  ByteString byte_string = ByteString::CreateFromHexString(input);
  if (byte_string.IsEmpty())
    return false;

  IPAddress::Family family;
  if (byte_string.GetLength() ==
      IPAddress::GetAddressLength(IPAddress::kFamilyIPv4)) {
    family = IPAddress::kFamilyIPv4;
  } else if (byte_string.GetLength() ==
             IPAddress::GetAddressLength(IPAddress::kFamilyIPv6)) {
    family = IPAddress::kFamilyIPv6;
  } else {
    return false;
  }

  // Linux kernel prints out IP addresses in network order via
  // /proc/net/tcp{,6}.
  byte_string.ConvertFromNetToCPUUInt32Array();

  *ip_address = IPAddress(family, byte_string);
  return true;
}

bool SocketInfoReader::ParsePort(const string &input, uint16_t *port) {
  int result = 0;

  if (input.size() != 4 || !base::HexStringToInt(input, &result) ||
      result < 0 || result > std::numeric_limits<uint16_t>::max()) {
    return false;
  }

  *port = result;
  return true;
}

bool SocketInfoReader::ParseTransimitAndReceiveQueueValues(
    const string &input,
    uint64_t *transmit_queue_value, uint64_t *receive_queue_value) {
  vector<string> tokens;
  int64_t signed_transmit_queue_value = 0, signed_receive_queue_value = 0;

  base::SplitString(input, ':', &tokens);
  if (tokens.size() != 2 ||
      !base::HexStringToInt64(tokens[0], &signed_transmit_queue_value) ||
      !base::HexStringToInt64(tokens[1], &signed_receive_queue_value)) {
    return false;
  }

  *transmit_queue_value = static_cast<uint64_t>(signed_transmit_queue_value);
  *receive_queue_value = static_cast<uint64_t>(signed_receive_queue_value);
  return true;
}

bool SocketInfoReader::ParseConnectionState(
    const string &input, SocketInfo::ConnectionState *connection_state) {
  int result = 0;

  if (input.size() != 2 || !base::HexStringToInt(input, &result)) {
    return false;
  }

  if (result > 0 && result < SocketInfo::kConnectionStateMax) {
    *connection_state = static_cast<SocketInfo::ConnectionState>(result);
  } else {
    *connection_state = SocketInfo::kConnectionStateUnknown;
  }
  return true;
}

bool SocketInfoReader::ParseTimerState(
    const string &input, SocketInfo::TimerState *timer_state) {
  vector<string> tokens;
  int result = 0;

  base::SplitString(input, ':', &tokens);
  if (tokens.size() != 2 || tokens[0].size() != 2 ||
      !base::HexStringToInt(tokens[0], &result)) {
    return false;
  }

  if (result < SocketInfo::kTimerStateMax) {
    *timer_state = static_cast<SocketInfo::TimerState>(result);
  } else {
    *timer_state = SocketInfo::kTimerStateUnknown;
  }
  return true;
}

}  // namespace shill
