// Copyright 2014 The Chromium 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 "net/socket/unix_domain_server_socket_posix.h"

#include <errno.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <utility>

#include "base/bind.h"
#include "base/logging.h"
#include "build/build_config.h"
#include "net/base/net_errors.h"
#include "net/base/sockaddr_storage.h"
#include "net/socket/socket_posix.h"
#include "net/socket/unix_domain_client_socket_posix.h"

namespace net {

UnixDomainServerSocket::UnixDomainServerSocket(
    const AuthCallback& auth_callback,
    bool use_abstract_namespace)
    : auth_callback_(auth_callback),
      use_abstract_namespace_(use_abstract_namespace) {
  DCHECK(!auth_callback_.is_null());
}

UnixDomainServerSocket::~UnixDomainServerSocket() = default;

// static
bool UnixDomainServerSocket::GetPeerCredentials(SocketDescriptor socket,
                                                Credentials* credentials) {
#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) || \
    defined(OS_FUCHSIA)
  struct ucred user_cred;
  socklen_t len = sizeof(user_cred);
  if (getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &user_cred, &len) < 0)
    return false;
  credentials->process_id = user_cred.pid;
  credentials->user_id = user_cred.uid;
  credentials->group_id = user_cred.gid;
  return true;
#else
  return getpeereid(
      socket, &credentials->user_id, &credentials->group_id) == 0;
#endif
}

int UnixDomainServerSocket::Listen(const IPEndPoint& address, int backlog) {
  NOTIMPLEMENTED();
  return ERR_NOT_IMPLEMENTED;
}

int UnixDomainServerSocket::ListenWithAddressAndPort(
    const std::string& address_string,
    uint16_t port,
    int backlog) {
  NOTIMPLEMENTED();
  return ERR_NOT_IMPLEMENTED;
}

int UnixDomainServerSocket::BindAndListen(const std::string& socket_path,
                                          int backlog) {
  DCHECK(!listen_socket_);

  SockaddrStorage address;
  if (!UnixDomainClientSocket::FillAddress(socket_path,
                                           use_abstract_namespace_,
                                           &address)) {
    return ERR_ADDRESS_INVALID;
  }

  std::unique_ptr<SocketPosix> socket(new SocketPosix);
  int rv = socket->Open(AF_UNIX);
  DCHECK_NE(ERR_IO_PENDING, rv);
  if (rv != OK)
    return rv;

  rv = socket->Bind(address);
  DCHECK_NE(ERR_IO_PENDING, rv);
  if (rv != OK) {
    PLOG(ERROR)
        << "Could not bind unix domain socket to " << socket_path
        << (use_abstract_namespace_ ? " (with abstract namespace)" : "");
    return rv;
  }

  rv = socket->Listen(backlog);
  DCHECK_NE(ERR_IO_PENDING, rv);
  if (rv != OK)
    return rv;

  listen_socket_.swap(socket);
  return rv;
}

int UnixDomainServerSocket::GetLocalAddress(IPEndPoint* address) const {
  DCHECK(address);

  // Unix domain sockets have no valid associated addr/port;
  // return address invalid.
  return ERR_ADDRESS_INVALID;
}

int UnixDomainServerSocket::Accept(std::unique_ptr<StreamSocket>* socket,
                                   CompletionOnceCallback callback) {
  DCHECK(socket);
  DCHECK(callback);
  DCHECK(!callback_ && !out_socket_.stream && !out_socket_.descriptor);

  out_socket_ = {socket, nullptr};
  int rv = DoAccept();
  if (rv == ERR_IO_PENDING)
    callback_ = std::move(callback);
  else
    CancelCallback();
  return rv;
}

int UnixDomainServerSocket::AcceptSocketDescriptor(
    SocketDescriptor* socket,
    CompletionOnceCallback callback) {
  DCHECK(socket);
  DCHECK(callback);
  DCHECK(!callback_ && !out_socket_.stream && !out_socket_.descriptor);

  out_socket_ = {nullptr, socket};
  int rv = DoAccept();
  if (rv == ERR_IO_PENDING)
    callback_ = std::move(callback);
  else
    CancelCallback();
  return rv;
}

int UnixDomainServerSocket::DoAccept() {
  DCHECK(listen_socket_);
  DCHECK(!accept_socket_);

  while (true) {
    int rv = listen_socket_->Accept(
        &accept_socket_,
        base::BindOnce(&UnixDomainServerSocket::AcceptCompleted,
                       base::Unretained(this)));
    if (rv != OK)
      return rv;
    if (AuthenticateAndGetStreamSocket())
      return OK;
    // Accept another socket because authentication error should be transparent
    // to the caller.
  }
}

void UnixDomainServerSocket::AcceptCompleted(int rv) {
  DCHECK(!callback_.is_null());

  if (rv != OK) {
    RunCallback(rv);
    return;
  }

  if (AuthenticateAndGetStreamSocket()) {
    RunCallback(OK);
    return;
  }

  // Accept another socket because authentication error should be transparent
  // to the caller.
  rv = DoAccept();
  if (rv != ERR_IO_PENDING)
    RunCallback(rv);
}

bool UnixDomainServerSocket::AuthenticateAndGetStreamSocket() {
  DCHECK(accept_socket_);

  Credentials credentials;
  if (!GetPeerCredentials(accept_socket_->socket_fd(), &credentials) ||
      !auth_callback_.Run(credentials)) {
    accept_socket_.reset();
    return false;
  }

  SetSocketResult(std::move(accept_socket_));
  return true;
}

void UnixDomainServerSocket::SetSocketResult(
    std::unique_ptr<SocketPosix> accepted_socket) {
  // Exactly one of the output pointers should be set.
  DCHECK_NE(!!out_socket_.stream, !!out_socket_.descriptor);

  // Pass ownership of |accepted_socket|.
  if (out_socket_.descriptor) {
    *out_socket_.descriptor = accepted_socket->ReleaseConnectedSocket();
    return;
  }
  *out_socket_.stream =
      std::make_unique<UnixDomainClientSocket>(std::move(accepted_socket));
}

void UnixDomainServerSocket::RunCallback(int rv) {
  out_socket_ = SocketDestination();
  std::move(callback_).Run(rv);
}

void UnixDomainServerSocket::CancelCallback() {
  out_socket_ = SocketDestination();
  callback_.Reset();
}

}  // namespace net
