/*
 * Copyright (C) 2017 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 "common/libs/utils/tcp_socket.h"

#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>

#include <cerrno>

#include <android-base/logging.h>

namespace cuttlefish {

ClientSocket::ClientSocket(int port)
    : fd_(SharedFD::SocketLocalClient(port, SOCK_STREAM)) {}

Message ClientSocket::RecvAny(std::size_t length) {
  Message buf(length);
  auto read_count = fd_->Read(buf.data(), buf.size());
  if (read_count < 0) {
    read_count = 0;
  }
  buf.resize(read_count);
  return buf;
}

bool ClientSocket::closed() const {
  std::lock_guard<std::mutex> guard(closed_lock_);
  return other_side_closed_;
}

Message ClientSocket::Recv(std::size_t length) {
  Message buf(length);
  ssize_t total_read = 0;
  while (total_read < static_cast<ssize_t>(length)) {
    auto just_read = fd_->Read(&buf[total_read], buf.size() - total_read);
    if (just_read <= 0) {
      if (just_read < 0) {
        LOG(ERROR) << "read() error: " << strerror(errno);
      }
      {
        std::lock_guard<std::mutex> guard(closed_lock_);
        other_side_closed_ = true;
      }
      return Message{};
    }
    total_read += just_read;
  }
  CHECK(total_read == static_cast<ssize_t>(length));
  return buf;
}

ssize_t ClientSocket::SendNoSignal(const uint8_t* data, std::size_t size) {
  std::lock_guard<std::mutex> lock(send_lock_);
  ssize_t written{};
  while (written < static_cast<ssize_t>(size)) {
    if (!fd_->IsOpen()) {
      LOG(ERROR) << "fd_ is closed";
    }
    auto just_written = fd_->Send(data + written, size - written, MSG_NOSIGNAL);
    if (just_written <= 0) {
      LOG(INFO) << "Couldn't write to client: " << strerror(errno);
      {
        std::lock_guard<std::mutex> guard(closed_lock_);
        other_side_closed_ = true;
      }
      return just_written;
    }
    written += just_written;
  }
  return written;
}

ssize_t ClientSocket::SendNoSignal(const Message& message) {
  return SendNoSignal(&message[0], message.size());
}

ServerSocket::ServerSocket(int port)
    : fd_{SharedFD::SocketLocalServer(port, SOCK_STREAM)} {
  if (!fd_->IsOpen()) {
    LOG(FATAL) << "Couldn't open streaming server on port " << port;
  }
}

ClientSocket ServerSocket::Accept() {
  SharedFD client = SharedFD::Accept(*fd_);
  if (!client->IsOpen()) {
    LOG(FATAL) << "Error attemping to accept: " << strerror(errno);
  }
  return ClientSocket{client};
}

void AppendInNetworkByteOrder(Message* msg, const std::uint8_t b) {
  msg->push_back(b);
}

void AppendInNetworkByteOrder(Message* msg, const std::uint16_t s) {
  const std::uint16_t n = htons(s);
  auto p = reinterpret_cast<const std::uint8_t*>(&n);
  msg->insert(msg->end(), p, p + sizeof n);
}

void AppendInNetworkByteOrder(Message* msg, const std::uint32_t w) {
  const std::uint32_t n = htonl(w);
  auto p = reinterpret_cast<const std::uint8_t*>(&n);
  msg->insert(msg->end(), p, p + sizeof n);
}

void AppendInNetworkByteOrder(Message* msg, const std::int32_t w) {
  std::uint32_t u{};
  std::memcpy(&u, &w, sizeof u);
  AppendInNetworkByteOrder(msg, u);
}

void AppendInNetworkByteOrder(Message* msg, const std::string& str) {
  msg->insert(msg->end(), str.begin(), str.end());
}

}
