// Copyright 2021 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 "trunks/csme/mei_client_socket.h"

#include <error.h>
#include <fcntl.h>
#include <linux/mei.h>
#include <linux/uuid.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

#include <cstring>
#include <string>

#include <base/check.h>
#include <base/check_op.h>
#include <base/logging.h>

namespace trunks {
namespace csme {

MeiClientSocket::MeiClientSocket(const std::string& mei_path,
                                 const uuid_le& guid)
    : mei_path_(mei_path) {
  DCHECK(!mei_path_.empty());
  memcpy(&guid_, &guid, sizeof(guid));
}

MeiClientSocket::~MeiClientSocket() {
  Uninitialize();
}

bool MeiClientSocket::Initialize() {
  if (initialized_) {
    return true;
  }
  DCHECK_EQ(fd_, -1);

  if (!InitializeInternal()) {
    Uninitialize();
    return false;
  }

  initialized_ = true;

  return true;
}

void MeiClientSocket::Uninitialize() {
  if (fd_ != -1) {
    close(fd_);
    fd_ = -1;
  }
}

bool MeiClientSocket::Send(const std::string& data,
                           bool /*wait_for_response_ready*/) {
  if (!initialized_ && !Initialize()) {
    LOG(ERROR) << __func__ << ": Not initialized.";
    return false;
  }
  const uint32_t message_size = data.size();
  ssize_t wsize = write(fd_, &message_size, sizeof(message_size));
  if (wsize != sizeof(message_size)) {
    LOG(ERROR) << __func__ << ": Bad written size of message header: " << wsize;
    return false;
  }
  wsize = write(fd_, data.data(), data.size());
  if (wsize != data.size()) {
    LOG(ERROR) << __func__ << ": Bad written size of payload: " << wsize;
    return false;
  }
  return true;
}

bool MeiClientSocket::Receive(std::string* data) {
  if (!initialized_ && !Initialize()) {
    LOG(ERROR) << __func__ << ": Not initialized.";
    return false;
  }
  uint32_t message_size = 0;
  ssize_t rsize = read(fd_, &message_size, sizeof(message_size));
  if (rsize != sizeof(message_size)) {
    LOG(ERROR) << "Unexpected message header size: " << rsize;
    return false;
  }
  data->resize(message_size);
  char* buffer = const_cast<char*>(data->data());
  for (ssize_t remaining_size = message_size; remaining_size > 0;) {
    const ssize_t rsize = read(fd_, buffer, remaining_size);
    if (rsize < 0) {
      LOG(ERROR) << ": Error calling `read()`: " << errno;
      data->clear();
      return false;
    }
    buffer += rsize;
    remaining_size -= rsize;
  }
  return true;
}

bool MeiClientSocket::InitializeInternal() {
  DCHECK_EQ(fd_, -1);

  fd_ = socket(AF_UNIX, SOCK_STREAM, 0);
  if (fd_ == -1) {
    LOG(ERROR) << __func__ << ": Error calling `socket()`." << errno;
    return false;
  }
  struct sockaddr_un addr = {};
  addr.sun_family = AF_UNIX;
  CHECK_LT(mei_path_.size(), sizeof(addr.sun_path));
  strncpy(addr.sun_path, mei_path_.c_str(), sizeof(addr.sun_path));
  if (connect(fd_, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
    LOG(ERROR) << __func__ << ": Error when connecting socket: " << errno;
    return false;
  }
  return true;
}

}  // namespace csme
}  // namespace trunks
