/*
 * Copyright (C) 2018 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 "tools/base/deploy/common/socket.h"

#include <poll.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>

#include "tools/base/deploy/common/env.h"
#include "tools/base/deploy/common/event.h"
#include "tools/base/deploy/common/log.h"

namespace deploy {

namespace {

socklen_t InitAddr(const std::string& socket_name, struct sockaddr_un* addr) {
  addr->sun_family = AF_UNIX;
#ifdef __APPLE__
  // Mac does not support abstract sockets, use a named one for testing
  std::string name = Env::root() + "/.abstract_" + socket_name;
  strncpy(addr->sun_path, name.c_str(), sizeof(addr->sun_path) - 1);
  return SUN_LEN(addr);
#else
  // Abstract socket paths start with a null terminator and don't need to
  // include an ending null.
  addr->sun_path[0] = '\0';
  addr->sun_path[1] = '\0';

  // Make sure we account for the fact that strncat adds a null terminator so we
  // don't overflow the buffer. We don't count this null terminator when
  // returning the length of the address struct.
  strncat(addr->sun_path + 1, socket_name.c_str(), sizeof(addr->sun_path) - 2);
  return sizeof(sa_family_t) +
         std::min(socket_name.size() + 1, sizeof(addr->sun_path) - 1);
#endif  // __APPLE__
}

}  // namespace

bool Socket::Open() {
  fd_ = socket(AF_UNIX, SOCK_STREAM, 0);
  return fd_ != -1;
}

bool Socket::BindAndListen(const std::string& socket_name) {
  if (fd_ == -1) {
    return false;
  }

  struct sockaddr_un addr = {0};
  socklen_t len = InitAddr(socket_name, &addr);
  if (bind(fd_, (const struct sockaddr*)&addr, len) == -1) {
    return false;
  }

  // If we have more than 127 pending connections, we have bigger issues.
  if (listen(fd_, 128) == -1) {
    return false;
  }

  return true;
}

bool Socket::Accept(Socket* socket, int timeout_ms) {
  if (fd_ == -1) {
    return false;
  }

  // If the other socket has already been opened, don't modify it.
  if (socket->fd_ != -1) {
    return false;
  }

  pollfd pfd = {fd_, POLLIN, 0};
  if (poll(&pfd, 1, timeout_ms) != 1) {
    return false;
  }

  socket->fd_ = accept(fd_, NULL, NULL);
  return socket->fd_ != -1;
}

bool Socket::Connect(const std::string& socket_name) {
  if (fd_ == -1) {
    return false;
  }

  struct sockaddr_un addr = {0};
  socklen_t len = InitAddr(socket_name, &addr);
  size_t retries = 0;
  while (connect(fd_, (const struct sockaddr*)&addr, len) != 0) {
    // Connection refusal means the server might have been slow to start, so
    // allow for retries.
    if (errno != ECONNREFUSED) {
      std::string error = "Error connecting to server: ";
      error.append(strerror(errno));
      ErrEvent(error);
      return false;
    }

    if (retries >= kConnectRetries) {
      ErrEvent("Error connectiong to server: timed out waiting for connection");
      return false;
    }

    // A failed connect() leaves the socket in an invalid state, so we need to
    // close and reopen the socket before retrying.
    Close();
    if (!Open()) {
      ErrEvent("Error connecting to server: could not open socket");
      return false;
    }

    usleep(kConnectRetryMs * 1000);
    retries++;
  }

  return true;
}

}  // namespace deploy
