/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * 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.
 */

#ifndef ART_ADBCONNECTION_ADBCONNECTION_H_
#define ART_ADBCONNECTION_ADBCONNECTION_H_

#include <stdint.h>
#include <vector>
#include <limits>

#include "android-base/unique_fd.h"

#include "base/mutex.h"
#include "base/array_ref.h"
#include "runtime_callbacks.h"

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

namespace adbconnection {

static constexpr char kJdwpControlName[] = "\0jdwp-control";
static constexpr char kAdbConnectionThreadName[] = "ADB-JDWP Connection Control Thread";

// The default jdwp agent name.
static constexpr char kDefaultJdwpAgentName[] = "libjdwp.so";

class AdbConnectionState;

struct AdbConnectionDebuggerController : public art::DebuggerControlCallback {
  explicit AdbConnectionDebuggerController(AdbConnectionState* connection)
      : connection_(connection) {}

  // Begin running the debugger.
  void StartDebugger() override;

  // The debugger should begin shutting down since the runtime is ending.
  void StopDebugger() override;

  bool IsDebuggerConfigured() override;

 private:
  AdbConnectionState* connection_;
};

enum class DdmPacketType : uint8_t { kReply = 0x80, kCmd = 0x00, };

struct AdbConnectionDdmCallback : public art::DdmCallback {
  explicit AdbConnectionDdmCallback(AdbConnectionState* connection) : connection_(connection) {}

  void DdmPublishChunk(uint32_t type,
                       const art::ArrayRef<const uint8_t>& data)
      REQUIRES_SHARED(art::Locks::mutator_lock_);

 private:
  AdbConnectionState* connection_;
};

class AdbConnectionState {
 public:
  explicit AdbConnectionState(const std::string& name);

  // Called on the listening thread to start dealing with new input. thr is used to attach the new
  // thread to the runtime.
  void RunPollLoop(art::Thread* self);

  // Sends ddms data over the socket, if there is one. This data is sent even if we haven't finished
  // hand-shaking yet.
  void PublishDdmData(uint32_t type, const art::ArrayRef<const uint8_t>& data);

  // Stops debugger threads during shutdown.
  void StopDebuggerThreads();

  // If StartDebuggerThreads was called successfully.
  bool DebuggerThreadsStarted() {
    return started_debugger_threads_;
  }

 private:
  uint32_t NextDdmId();

  void StartDebuggerThreads();

  // Tell adbd about the new runtime.
  bool SetupAdbConnection();

  std::string MakeAgentArg();

  android::base::unique_fd ReadFdFromAdb();

  void SendAgentFds(bool require_handshake);

  void CloseFds();

  void HandleDataWithoutAgent(art::Thread* self);

  void PerformHandshake();

  void AttachJdwpAgent(art::Thread* self);

  void NotifyDdms(bool active);

  void SendDdmPacket(uint32_t id,
                     DdmPacketType type,
                     uint32_t ddm_type,
                     art::ArrayRef<const uint8_t> data);

  std::string agent_name_;

  AdbConnectionDebuggerController controller_;
  AdbConnectionDdmCallback ddm_callback_;

  // Eventfd used to allow the StopDebuggerThreads function to wake up sleeping threads
  android::base::unique_fd sleep_event_fd_;

  // Socket that we use to talk to adbd.
  android::base::unique_fd control_sock_;

  // Socket that we use to talk to the agent (if it's loaded).
  android::base::unique_fd local_agent_control_sock_;

  // The fd of the socket the agent uses to talk to us. We need to keep it around in order to clean
  // it up when the runtime goes away.
  android::base::unique_fd remote_agent_control_sock_;

  // The fd that is forwarded through adb to the client. This is guarded by the
  // adb_write_event_fd_.
  android::base::unique_fd adb_connection_socket_;

  // The fd we send to the agent to let us synchronize access to the shared adb_connection_socket_.
  // This is also used as a general lock for the adb_connection_socket_ on any threads other than
  // the poll thread.
  android::base::unique_fd adb_write_event_fd_;

  std::atomic<bool> shutting_down_;

  // True if we have loaded the agent library.
  std::atomic<bool> agent_loaded_;

  // True if the dt_fd_forward transport is listening for a new communication channel.
  std::atomic<bool> agent_listening_;

  // True if the dt_fd_forward transport has the socket. If so we don't do anything to the agent or
  // the adb connection socket until connection goes away.
  std::atomic<bool> agent_has_socket_;

  std::atomic<bool> sent_agent_fds_;

  bool performed_handshake_;

  bool notified_ddm_active_;

  std::atomic<uint32_t> next_ddm_id_;

  bool started_debugger_threads_;

  socklen_t control_addr_len_;
  union {
    sockaddr_un controlAddrUn;
    sockaddr controlAddrPlain;
  } control_addr_;

  friend struct AdbConnectionDebuggerController;
};

}  // namespace adbconnection

#endif  // ART_ADBCONNECTION_ADBCONNECTION_H_
