//
//  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) {
      PLOG(ERROR) << "Failed to bind IPC socket to address";
      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) {
    PLOG(ERROR) << "Failed to listen on domain socket";
    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) {
      PLOG(ERROR) << "Failed to accept client connection";
      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
