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