//
//  Copyright 2015 Google, Inc.
//
//  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 "service/ipc/ipc_handler_linux.h"

#include <sys/socket.h>
#include <sys/un.h>

#include <base/bind.h>

#include "osi/include/socket_utils/sockets.h"
#include "service/daemon.h"
#include "service/ipc/linux_ipc_host.h"
#include "service/settings.h"

namespace ipc {

IPCHandlerLinux::IPCHandlerLinux(bluetooth::Adapter* adapter,
                                 IPCManager::Delegate* delegate)
    : IPCHandler(adapter, delegate),
      running_(false),
      thread_("IPCHandlerLinux"),
      keep_running_(true) {}

IPCHandlerLinux::~IPCHandlerLinux() {
  // This will only be set if the Settings::create_ipc_socket_path() was
  // originally provided.
  if (!socket_path_.empty()) unlink(socket_path_.value().c_str());
}

bool IPCHandlerLinux::Run() {
  CHECK(!running_);

  const std::string& android_suffix =
      bluetooth::Daemon::Get()->GetSettings()->android_ipc_socket_suffix();
  const base::FilePath& path =
      bluetooth::Daemon::Get()->GetSettings()->create_ipc_socket_path();

  // Both flags cannot be set at the same time.
  CHECK(android_suffix.empty() || path.empty());
  if (android_suffix.empty() && path.empty()) {
    LOG(ERROR) << "No domain socket path provided";
    return false;
  }

  CHECK(base::MessageLoop::current());  // An origin event loop is required.
  origin_task_runner_ = base::MessageLoop::current()->task_runner();

  if (!android_suffix.empty()) {
    int server_fd = osi_android_get_control_socket(android_suffix.c_str());
    if (server_fd == -1) {
      LOG(ERROR) << "Unable to get Android socket from: " << android_suffix;
      return false;
    }
    LOG(INFO) << "Binding to Android server socket:" << android_suffix;
    socket_.reset(server_fd);
  } else {
    LOG(INFO) << "Creating a Unix domain socket:" << path.value();

    // TODO(armansito): This is opens the door to potentially unlinking files in
    // the current directory that we're not supposed to. For now we will have an
    // assumption that the daemon runs in a sandbox but we should generally do
    // this properly.
    unlink(path.value().c_str());

    base::ScopedFD server_socket(socket(PF_UNIX, SOCK_SEQPACKET, 0));
    if (!server_socket.is_valid()) {
      LOG(ERROR) << "Failed to open domain socket for IPC";
      return false;
    }

    struct sockaddr_un address;
    memset(&address, 0, sizeof(address));
    address.sun_family = AF_UNIX;
    strncpy(address.sun_path, path.value().c_str(),
            sizeof(address.sun_path) - 1);
    if (bind(server_socket.get(), (struct sockaddr*)&address, sizeof(address)) <
        0) {
      LOG(ERROR) << "Failed to bind IPC socket to address: " << strerror(errno);
      return false;
    }

    socket_.swap(server_socket);
    socket_path_ = path;
  }

  CHECK(socket_.is_valid());

  running_ = true;  // Set this here before launching the thread.

  // Start an IO thread and post the listening task.
  base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
  if (!thread_.StartWithOptions(options)) {
    LOG(ERROR) << "Failed to start IPCHandlerLinux thread";
    running_ = false;
    return false;
  }

  thread_.task_runner()->PostTask(
      FROM_HERE, base::Bind(&IPCHandlerLinux::StartListeningOnThread, this));

  return true;
}

void IPCHandlerLinux::Stop() {
  keep_running_ = false;

  // At this moment the listening thread might be blocking on the accept
  // syscall. Shutdown and close the server socket before joining the thread to
  // interrupt accept so that the main thread doesn't keep blocking.
  shutdown(socket_.get(), SHUT_RDWR);
  socket_.reset();

  // Join and clean up the thread.
  thread_.Stop();

  // Thread exited. Notify the delegate. Post this on the event loop so that the
  // callback isn't reentrant.
  NotifyStoppedOnOriginThread();
}

void IPCHandlerLinux::StartListeningOnThread() {
  CHECK(socket_.is_valid());
  CHECK(adapter());
  CHECK(running_);

  LOG(INFO) << "Listening to incoming connections";

  int status = listen(socket_.get(), SOMAXCONN);
  if (status < 0) {
    LOG(ERROR) << "Failed to listen on domain socket: " << strerror(errno);
    origin_task_runner_->PostTask(
        FROM_HERE, base::Bind(&IPCHandlerLinux::ShutDownOnOriginThread, this));
    return;
  }

  NotifyStartedOnOriginThread();

  // TODO(armansito): The code below can cause the daemon to run indefinitely if
  // the thread is joined while it's in the middle of the EventLoop() call. The
  // EventLoop() won't exit until a client terminates the connection, however
  // this can be fixed by using the |thread_|'s MessageLoopForIO instead (since
  // it gets stopped along with the thread).
  // TODO(icoolidge): accept simultaneous clients
  while (keep_running_.load()) {
    int client_socket = accept4(socket_.get(), nullptr, nullptr, SOCK_NONBLOCK);
    if (client_socket < 0) {
      LOG(ERROR) << "Failed to accept client connection: " << strerror(errno);
      continue;
    }

    LOG(INFO) << "Established client connection: fd=" << client_socket;

    LinuxIPCHost ipc_host(client_socket, adapter());

    // TODO(armansito): Use |thread_|'s MessageLoopForIO instead of using a
    // custom event loop to poll from the socket.
    ipc_host.EventLoop();
  }
}

void IPCHandlerLinux::ShutDownOnOriginThread() {
  LOG(INFO) << "Shutting down IPCHandlerLinux thread";
  thread_.Stop();
  running_ = false;

  NotifyStoppedOnCurrentThread();
}

void IPCHandlerLinux::NotifyStartedOnOriginThread() {
  if (!delegate()) return;

  origin_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&IPCHandlerLinux::NotifyStartedOnCurrentThread, this));
}

void IPCHandlerLinux::NotifyStartedOnCurrentThread() {
  if (delegate()) delegate()->OnIPCHandlerStarted(IPCManager::TYPE_LINUX);
}

void IPCHandlerLinux::NotifyStoppedOnOriginThread() {
  if (!delegate()) return;

  origin_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&IPCHandlerLinux::NotifyStoppedOnCurrentThread, this));
}

void IPCHandlerLinux::NotifyStoppedOnCurrentThread() {
  if (delegate()) delegate()->OnIPCHandlerStopped(IPCManager::TYPE_LINUX);
}

}  // namespace ipc
