// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef SRC_DEVELOPER_DEBUG_SHARED_MESSAGE_LOOP_FUCHSIA_H_
#define SRC_DEVELOPER_DEBUG_SHARED_MESSAGE_LOOP_FUCHSIA_H_

#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fdio/unsafe.h>
#include <lib/zx/event.h>
#include <lib/zx/port.h>
#include <lib/zx/thread.h>
#include <zircon/syscalls/exception.h>

#include <vector>

#include "src/developer/debug/shared/event_handlers.h"
#include "src/developer/debug/shared/message_loop.h"

namespace debug {

class ExceptionHandler;
class SignalHandler;
class SocketWatcher;
class ZirconExceptionWatcher;

enum class WatchType : uint32_t { kTask, kFdio, kProcessExceptions, kJobExceptions, kSocket };
const char* WatchTypeToString(WatchType);

// MessageLoop is a virtual class to enable tests to intercept watch messages.
// See debug_agent/debug_agent_unittest.cc for an example.
class MessageLoopFuchsia : public MessageLoop {
 public:
  // Associated struct to track information about what type of resource a watch handle is following.
  //
  // EventHandlers need access to the WatchInfo implementation, hence the reason for it to be
  // public.
  //
  // Definition at the end of the header.
  struct WatchInfo;

  using SignalHandlerMap = std::map<const async_wait_t*, SignalHandler>;
  using ChannelExceptionHandlerMap = std::map<const async_wait_t*, ChannelExceptionHandler>;

  MessageLoopFuchsia();
  ~MessageLoopFuchsia();

  bool Init(std::string* error_message) override;
  void Cleanup() override;

  // Returns the current message loop or null if there isn't one.
  static MessageLoopFuchsia* Current();

  // MessageLoop implementation.
  WatchHandle WatchFD(WatchMode mode, int fd, FDWatcher watcher) override;

  // Watches the given socket for read/write status. The watcher must outlive the returned
  // WatchHandle. Must only be called on the message loop thread.
  //
  // The WatchHandle must not unregister from a callback. The handle might become both readable and
  // writable at the same time which will necessitate calling both callbacks. The code does not
  // expect the SocketWatcher to disappear in between these callbacks.
  virtual zx_status_t WatchSocket(WatchMode mode, zx_handle_t socket_handle, SocketWatcher* watcher,
                                  WatchHandle* out);

  // Attaches to the exception port of the given process and issues callbacks on the given watcher.
  // The watcher must outlive the returned WatchHandle. Must only be called on the message loop
  // thread.
  struct WatchProcessConfig {
    std::string process_name;
    zx_handle_t process_handle;
    zx_koid_t process_koid;
    ZirconExceptionWatcher* watcher = nullptr;
  };
  virtual zx_status_t WatchProcessExceptions(WatchProcessConfig config, WatchHandle* out);

  // Attaches to the exception port of the given job and issues callbacks on the given watcher. The
  // watcher must outlive the returned WatchHandle. Must only be called on the message loop thread.
  struct WatchJobConfig {
    std::string job_name;
    zx_handle_t job_handle;
    zx_koid_t job_koid;
    ZirconExceptionWatcher* watcher;
  };
  virtual zx_status_t WatchJobExceptions(WatchJobConfig config, WatchHandle* out);

  void QuitNow() override;

  const SignalHandlerMap& signal_handlers() const { return signal_handlers_; }

  const ChannelExceptionHandlerMap& channel_exception_handlers() const {
    return channel_exception_handlers_;
  }

 private:
  const WatchInfo* FindWatchInfo(int id) const;

  // MessageLoop protected implementation.
  uint64_t GetMonotonicNowNS() const override;
  void RunImpl() override;
  void StopWatching(int id) override;
  // Triggers an event signaling that there is a pending event.
  void SetHasTasks() override;

  // Check for any pending C++ tasks and process them.
  // Returns true if there was an event pending to be processed.
  bool CheckAndProcessPendingTasks();

  // Handlers exceptions channel.
  void HandleChannelException(const ChannelExceptionHandler&, zx::exception exception,
                              zx_exception_info_t exception_info);

  // Handle an event of the given type.
  void OnFdioSignal(int watch_id, const WatchInfo& info, zx_signals_t observed);

  void OnJobException(const WatchInfo& info, zx::exception exception,
                      zx_exception_info_t exception_info);

  void OnProcessException(const WatchInfo& info, zx::exception exception,
                          zx_exception_info_t exception_info);

  void OnProcessTerminated(const WatchInfo&, zx_signals_t observed);

  void OnSocketSignal(int watch_id, const WatchInfo& info, zx_signals_t observed);

  std::map<int, WatchInfo> watches_;

  // ID used as an index into watches_.
  int next_watch_id_ = 1;

  async::Loop loop_;
  zx::event task_event_;

  SignalHandlerMap signal_handlers_;
  // See SignalHandler constructor.
  // |associated_info| needs to be updated with the fact that it has an associated SignalHandler.
  zx_status_t AddSignalHandler(int, zx_handle_t, zx_signals_t, WatchInfo* info);
  void RemoveSignalHandler(WatchInfo* info);

  // Channel Exception Handlers are similar to SignalHandlers, but have different handling
  // semantics. Particularly, they are meant to return out exception_tokens to their handlers.
  ChannelExceptionHandlerMap channel_exception_handlers_;

  // Listens to the exception channel. Will call |HandleChannelException| on this message loop.
  // |options| are the options to be passed to |zx_task_create_exception_channel|.
  zx_status_t AddChannelExceptionHandler(int id, zx_handle_t object, uint32_t options,
                                         WatchInfo* info);
  void RemoveChannelExceptionHandler(WatchInfo*);

  FXL_DISALLOW_COPY_AND_ASSIGN(MessageLoopFuchsia);

  friend class SignalHandler;
  friend class ChannelExceptionHandler;
};

// EventHandlers need access to the WatchInfo implementation.
struct MessageLoopFuchsia::WatchInfo {
  // Name of the resource being watched.
  // Mostly tracked for debugging purposes.
  std::string resource_name;

  WatchType type = WatchType::kFdio;

  // Used when the type is FDIO or socket.
  WatchMode mode = WatchMode::kReadWrite;

  // FDIO-specific watcher parameters.
  int fd = -1;
  fdio_t* fdio = nullptr;
  FDWatcher fd_watcher = nullptr;
  zx_handle_t fd_handle = ZX_HANDLE_INVALID;

  // Socket-specific parameters.
  SocketWatcher* socket_watcher = nullptr;
  zx_handle_t socket_handle = ZX_HANDLE_INVALID;

  // Task-exception-specific parameters, can be of job or process type.
  ZirconExceptionWatcher* exception_watcher = nullptr;
  zx_koid_t task_koid = 0;
  zx_handle_t task_handle = ZX_HANDLE_INVALID;

  // This makes easier the lookup of the associated ExceptionHandler with this watch id.
  const async_wait_t* signal_handler_key = nullptr;
  const async_wait_t* exception_channel_handler_key = nullptr;
};

}  // namespace debug

#endif  // SRC_DEVELOPER_DEBUG_SHARED_MESSAGE_LOOP_FUCHSIA_H_
