/*
 * Copyright (C) 2016 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.
 */

// TODO: We can't use std::shared_ptr on the older guests due to HALs.

#ifndef CUTTLEFISH_COMMON_COMMON_LIBS_FS_SHARED_FD_H_
#define CUTTLEFISH_COMMON_COMMON_LIBS_FS_SHARED_FD_H_

#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/timerfd.h>
#include <sys/uio.h>
#include <sys/un.h>

#include <memory>
#include <sstream>

#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>

#include <android-base/cmsg.h>

#include "vm_sockets.h"

/**
 * Classes to to enable safe access to files.
 * POSIX kernels have an unfortunate habit of recycling file descriptors.
 * That can cause problems like http://b/26121457 in code that doesn't manage
 * file lifetimes properly. These classes implement an alternate interface
 * that has some advantages:
 *
 * o References to files are tightly controlled
 * o Files are auto-closed if they go out of scope
 * o Files are life-time aware. It is impossible to close the instance twice.
 * o File descriptors are always initialized. By default the descriptor is
 *   set to a closed instance.
 *
 * These classes are designed to mimic to POSIX interface as closely as
 * possible. Specifically, they don't attempt to track the type of file
 * descriptors and expose only the valid operations. This is by design, since
 * it makes it easier to convert existing code to SharedFDs and avoids the
 * possibility that new POSIX functionality will lead to large refactorings.
 */
namespace cuttlefish {

class FileInstance;

/**
 * Counted reference to a FileInstance.
 *
 * This is also the place where most new FileInstances are created. The creation
 * mehtods correspond to the underlying POSIX calls.
 *
 * SharedFDs can be compared and stored in STL containers. The semantics are
 * slightly different from POSIX file descriptors:
 *
 * o The value of the SharedFD is the identity of its underlying FileInstance.
 *
 * o Each newly created SharedFD has a unique, closed FileInstance:
 *    SharedFD a, b;
 *    assert (a != b);
 *    a = b;
 *    asssert(a == b);
 *
 * o The identity of the FileInstance is not affected by closing the file:
 *   SharedFD a, b;
 *   set<SharedFD> s;
 *   s.insert(a);
 *   assert(s.count(a) == 1);
 *   assert(s.count(b) == 0);
 *   a->Close();
 *   assert(s.count(a) == 1);
 *   assert(s.count(b) == 0);
 *
 * o FileInstances are never visibly recycled.
 *
 * o If all of the SharedFDs referring to a FileInstance go out of scope the
 *   file is closed and the FileInstance is recycled.
 *
 * Creation methods must ensure that no references to the new file descriptor
 * escape. The underlying FileInstance should have the only reference to the
 * file descriptor. Any method that needs to know the fd must be in either
 * SharedFD or FileInstance.
 *
 * SharedFDs always have an underlying FileInstance, so all of the method
 * calls are safe in accordance with the null object pattern.
 *
 * Errors on system calls that create new FileInstances, such as Open, are
 * reported with a new, closed FileInstance with the errno set.
 */
class SharedFD {
  // Give WeakFD access to the underlying shared_ptr.
  friend class WeakFD;
 public:
  inline SharedFD();
  SharedFD(const std::shared_ptr<FileInstance>& in) : value_(in) {}
  // Reference the listener as a FileInstance to make this FD type agnostic.
  static SharedFD Accept(const FileInstance& listener, struct sockaddr* addr,
                         socklen_t* addrlen);
  static SharedFD Accept(const FileInstance& listener);
  static SharedFD Dup(int unmanaged_fd);
  // All SharedFDs have the O_CLOEXEC flag after creation. To remove use the
  // Fcntl or Dup functions.
  static SharedFD Open(const std::string& pathname, int flags, mode_t mode = 0);
  static SharedFD Creat(const std::string& pathname, mode_t mode);
  static bool Pipe(SharedFD* fd0, SharedFD* fd1);
  static SharedFD Event(int initval = 0, int flags = 0);
  static SharedFD MemfdCreate(const std::string& name, unsigned int flags = 0);
  static SharedFD Mkstemp(std::string* path);
  static bool SocketPair(int domain, int type, int protocol, SharedFD* fd0,
                         SharedFD* fd1);
  static SharedFD Socket(int domain, int socket_type, int protocol);
  static SharedFD SocketLocalClient(const std::string& name, bool is_abstract,
                                    int in_type);
  static SharedFD SocketLocalClient(const std::string& name, bool is_abstract,
                                    int in_type, int timeout_seconds);
  static SharedFD SocketLocalClient(int port, int type);
  static SharedFD SocketLocalServer(const std::string& name, bool is_abstract,
                                    int in_type, mode_t mode);
  static SharedFD SocketLocalServer(int port, int type);
  static SharedFD VsockServer(unsigned int port, int type,
                              unsigned int cid = VMADDR_CID_ANY);
  static SharedFD VsockServer(int type);
  static SharedFD VsockClient(unsigned int cid, unsigned int port, int type);

  bool operator==(const SharedFD& rhs) const { return value_ == rhs.value_; }

  bool operator!=(const SharedFD& rhs) const { return value_ != rhs.value_; }

  bool operator<(const SharedFD& rhs) const { return value_ < rhs.value_; }

  bool operator<=(const SharedFD& rhs) const { return value_ <= rhs.value_; }

  bool operator>(const SharedFD& rhs) const { return value_ > rhs.value_; }

  bool operator>=(const SharedFD& rhs) const { return value_ >= rhs.value_; }

  std::shared_ptr<FileInstance> operator->() const { return value_; }

  const FileInstance& operator*() const { return *value_; }

  FileInstance& operator*() { return *value_; }

 private:
  static SharedFD ErrorFD(int error);

  std::shared_ptr<FileInstance> value_;
};

/**
 * A non-owning reference to a FileInstance. The referenced FileInstance needs
 * to be managed by a SharedFD. A WeakFD needs to be converted to a SharedFD to
 * access the underlying FileInstance.
 */
class WeakFD {
 public:
  WeakFD(SharedFD shared_fd) : value_(shared_fd.value_) {}

  // Creates a new SharedFD object that shares ownership of the underlying fd.
  // Callers need to check that the returned SharedFD is open before using it.
  SharedFD lock() const;

 private:
  std::weak_ptr<FileInstance> value_;
};

// Provides RAII semantics for memory mappings, preventing memory leaks. It does
// not however prevent use-after-free errors since the underlying pointer can be
// extracted and could survive this object.
class ScopedMMap {
 public:
  ScopedMMap();
  ScopedMMap(void* ptr, size_t size);
  ScopedMMap(const ScopedMMap& other) = delete;
  ScopedMMap& operator=(const ScopedMMap& other) = delete;
  ScopedMMap(ScopedMMap&& other);

  ~ScopedMMap();

  void* get() { return ptr_; }
  const void* get() const { return ptr_; }
  size_t len() const { return len_; }

  operator bool() const { return ptr_ != MAP_FAILED; }

 private:
  void* ptr_ = MAP_FAILED;
  size_t len_;
};

/**
 * Tracks the lifetime of a file descriptor and provides methods to allow
 * callers to use the file without knowledge of the underlying descriptor
 * number.
 *
 * FileInstances have two states: Open and Closed. They may start in either
 * state. However, once a FileIntance enters the Closed state it cannot be
 * reopened.
 *
 * Construction of FileInstances is limited to select classes to avoid
 * escaping file descriptors. At this point SharedFD is the only class
 * that has access. We may eventually have ScopedFD and WeakFD.
 */
class FileInstance {
  // Give SharedFD access to the aliasing constructor.
  friend class SharedFD;

 public:
  virtual ~FileInstance() { Close(); }

  // This can't be a singleton because our shared_ptr's aren't thread safe.
  static std::shared_ptr<FileInstance> ClosedInstance() {
    return std::shared_ptr<FileInstance>(new FileInstance(-1, EBADF));
  }

  int Bind(const struct sockaddr* addr, socklen_t addrlen) {
    errno = 0;
    int rval = bind(fd_, addr, addrlen);
    errno_ = errno;
    return rval;
  }

  int Connect(const struct sockaddr* addr, socklen_t addrlen) {
    errno = 0;
    int rval = connect(fd_, addr, addrlen);
    errno_ = errno;
    return rval;
  }

  int ConnectWithTimeout(const struct sockaddr* addr, socklen_t addrlen,
                         struct timeval* timeout);

  void Close();

  // Returns true if the entire input was copied.
  // Otherwise an error will be set either on this file or the input.
  // The non-const reference is needed to avoid binding this to a particular
  // reference type.
  bool CopyFrom(FileInstance& in, size_t length);

  int UNMANAGED_Dup() {
    errno = 0;
    int rval = TEMP_FAILURE_RETRY(dup(fd_));
    errno_ = errno;
    return rval;
  }

  int UNMANAGED_Dup2(int newfd) {
    errno = 0;
    int rval = TEMP_FAILURE_RETRY(dup2(fd_, newfd));
    errno_ = errno;
    return rval;
  }

  int Fcntl(int command, int value) {
    errno = 0;
    int rval = TEMP_FAILURE_RETRY(fcntl(fd_, command, value));
    errno_ = errno;
    return rval;
  }

  int GetErrno() const { return errno_; }

  int GetSockName(struct sockaddr* addr, socklen_t* addrlen) {
    errno = 0;
    int rval = TEMP_FAILURE_RETRY(getsockname(fd_, addr, addrlen));
    if (rval == -1) {
      errno_ = errno;
    }
    return rval;
  }

  unsigned int VsockServerPort() {
    struct sockaddr_vm vm_socket;
    socklen_t length = sizeof(vm_socket);
    GetSockName(reinterpret_cast<struct sockaddr*>(&vm_socket), &length);
    return vm_socket.svm_port;
  }

  int Ioctl(int request, void* val = nullptr) {
    errno = 0;
    int rval = TEMP_FAILURE_RETRY(ioctl(fd_, request, val));
    errno_ = errno;
    return rval;
  }

  bool IsOpen() const { return fd_ != -1; }

  // in probably isn't modified, but the API spec doesn't have const.
  bool IsSet(fd_set* in) const;

  /**
   * Adds a hard link to a file descriptor, based on the current working
   * directory of the process or to some absolute path.
   *
   * https://www.man7.org/linux/man-pages/man2/linkat.2.html
   *
   * Using this on a file opened with O_TMPFILE can link it into the filesystem.
   */
  // Used with O_TMPFILE files to attach them to the filesystem.
  int LinkAtCwd(const std::string& path) {
    std::string name = "/proc/self/fd/";
    name += std::to_string(fd_);
    errno = 0;
    int rval = linkat(
        -1, name.c_str(), AT_FDCWD, path.c_str(), AT_SYMLINK_FOLLOW);
    errno_ = errno;
    return rval;
  }

  int Listen(int backlog) {
    errno = 0;
    int rval = listen(fd_, backlog);
    errno_ = errno;
    return rval;
  }

  static void Log(const char* message);

  off_t LSeek(off_t offset, int whence) {
    errno = 0;
    off_t rval = TEMP_FAILURE_RETRY(lseek(fd_, offset, whence));
    errno_ = errno;
    return rval;
  }

  ssize_t Recv(void* buf, size_t len, int flags) {
    errno = 0;
    ssize_t rval = TEMP_FAILURE_RETRY(recv(fd_, buf, len, flags));
    errno_ = errno;
    return rval;
  }

  ssize_t RecvMsg(struct msghdr* msg, int flags) {
    errno = 0;
    ssize_t rval = TEMP_FAILURE_RETRY(recvmsg(fd_, msg, flags));
    errno_ = errno;
    return rval;
  }

  ssize_t Read(void* buf, size_t count) {
    errno = 0;
    ssize_t rval = TEMP_FAILURE_RETRY(read(fd_, buf, count));
    errno_ = errno;
    return rval;
  }

  int EventfdRead(eventfd_t* value) {
    errno = 0;
    auto rval = eventfd_read(fd_, value);
    errno_ = errno;
    return rval;
  }

  ssize_t Send(const void* buf, size_t len, int flags) {
    errno = 0;
    ssize_t rval = TEMP_FAILURE_RETRY(send(fd_, buf, len, flags));
    errno_ = errno;
    return rval;
  }

  ssize_t SendMsg(const struct msghdr* msg, int flags) {
    errno = 0;
    ssize_t rval = TEMP_FAILURE_RETRY(sendmsg(fd_, msg, flags));
    errno_ = errno;
    return rval;
  }

  template <typename... Args>
  ssize_t SendFileDescriptors(const void* buf, size_t len, Args&&... sent_fds) {
    std::vector<int> fds;
    android::base::Append(fds, std::forward<int>(sent_fds->fd_)...);
    errno = 0;
    auto ret = android::base::SendFileDescriptorVector(fd_, buf, len, fds);
    errno_ = errno;
    return ret;
  }

  int Shutdown(int how) {
    errno = 0;
    int rval = shutdown(fd_, how);
    errno_ = errno;
    return rval;
  }

  void Set(fd_set* dest, int* max_index) const;

  int SetSockOpt(int level, int optname, const void* optval, socklen_t optlen) {
    errno = 0;
    int rval = setsockopt(fd_, level, optname, optval, optlen);
    errno_ = errno;
    return rval;
  }

  int GetSockOpt(int level, int optname, void* optval, socklen_t* optlen) {
    errno = 0;
    int rval = getsockopt(fd_, level, optname, optval, optlen);
    errno_ = errno;
    return rval;
  }

  int SetTerminalRaw() {
    errno = 0;
    termios terminal_settings;
    int rval = tcgetattr(fd_, &terminal_settings);
    errno_ = errno;
    if (rval < 0) {
      return rval;
    }
    cfmakeraw(&terminal_settings);
    rval = tcsetattr(fd_, TCSANOW, &terminal_settings);
    errno_ = errno;
    return rval;
  }

  const char* StrError() const {
    errno = 0;
    FileInstance* s = const_cast<FileInstance*>(this);
    char* out = strerror_r(errno_, s->strerror_buf_, sizeof(strerror_buf_));

    // From man page:
    //  strerror_r() returns a pointer to a string containing the error message.
    //  This may be either a pointer to a string that the function stores in
    //  buf, or a pointer to some (immutable) static string (in which case buf
    //  is unused).
    if (out != s->strerror_buf_) {
      strncpy(s->strerror_buf_, out, sizeof(strerror_buf_));
    }
    return strerror_buf_;
  }

  ScopedMMap MMap(void* addr, size_t length, int prot, int flags,
                  off_t offset) {
    errno = 0;
    auto ptr = mmap(addr, length, prot, flags, fd_, offset);
    errno_ = errno;
    return ScopedMMap(ptr, length);
  }

  ssize_t Truncate(off_t length) {
    errno = 0;
    ssize_t rval = TEMP_FAILURE_RETRY(ftruncate(fd_, length));
    errno_ = errno;
    return rval;
  }

  ssize_t Write(const void* buf, size_t count) {
    errno = 0;
    ssize_t rval = TEMP_FAILURE_RETRY(write(fd_, buf, count));
    errno_ = errno;
    return rval;
  }

  int EventfdWrite(eventfd_t value) {
    errno = 0;
    int rval = eventfd_write(fd_, value);
    errno_ = errno;
    return rval;
  }

  bool IsATTY() {
    errno = 0;
    int rval = isatty(fd_);
    errno_ = errno;
    return rval;
  }

 private:
  FileInstance(int fd, int in_errno) : fd_(fd), errno_(in_errno) {
    // Ensure every file descriptor managed by a FileInstance has the CLOEXEC
    // flag
    TEMP_FAILURE_RETRY(fcntl(fd, F_SETFD, FD_CLOEXEC));
    std::stringstream identity;
    identity << "fd=" << fd << " @" << this;
    identity_ = identity.str();
  }

  FileInstance* Accept(struct sockaddr* addr, socklen_t* addrlen) const {
    int fd = TEMP_FAILURE_RETRY(accept(fd_, addr, addrlen));
    if (fd == -1) {
      return new FileInstance(fd, errno);
    } else {
      return new FileInstance(fd, 0);
    }
  }

  int fd_;
  int errno_;
  std::string identity_;
  char strerror_buf_[160];
};

/* Methods that need both a fully defined SharedFD and a fully defined
   FileInstance. */

inline SharedFD::SharedFD() : value_(FileInstance::ClosedInstance()) {}

}  // namespace cuttlefish

#endif  // CUTTLEFISH_COMMON_COMMON_LIBS_FS_SHARED_FD_H_
