// Jackson Coxson #pragma once #include #include #include #include #include // Bring in the global C ABI (all C structs/functions are global) #include #include #include #include namespace IdeviceFFI { class DebugProxy { public: DebugProxy() = default; DebugProxy(const DebugProxy&) = delete; DebugProxy& operator=(const DebugProxy&) = delete; DebugProxy(DebugProxy&& other) noexcept : handle_(other.handle_) { other.handle_ = nullptr; } DebugProxy& operator=(DebugProxy&& other) noexcept { if (this != &other) { reset(); handle_ = other.handle_; other.handle_ = nullptr; } return *this; } ~DebugProxy() { reset(); } // Factory: connect over RSD (borrows adapter & handshake; does not consume // them) static Result connect_rsd(Adapter& adapter, RsdHandshake& rsd); // Factory: consume a ReadWrite stream (fat pointer) static Result from_readwrite_ptr(::ReadWriteOpaque* consumed); // Convenience: consume a C++ ReadWrite wrapper by releasing it into the ABI static Result from_readwrite(ReadWrite&& rw); // API Result, FfiError> send_command(const std::string& name, const std::vector& argv); Result, FfiError> read_response(); Result send_raw(const std::vector& data); // Reads up to `len` bytes; ABI returns a heap C string (we treat as bytes → // string) Result, FfiError> read(std::size_t len); // Sets argv, returns textual reply (OK/echo/etc) Result, FfiError> set_argv(const std::vector& argv); Result send_ack(); Result send_nack(); // No error object in ABI; immediate effect void set_ack_mode(bool enabled) { ::debug_proxy_set_ack_mode(handle_, enabled ? 1 : 0); } ::DebugProxyHandle* raw() const { return handle_; } private: explicit DebugProxy(::DebugProxyHandle* h) : handle_(h) {} void reset() { if (handle_) { ::debug_proxy_free(handle_); handle_ = nullptr; } } ::DebugProxyHandle* handle_ = nullptr; }; // Small helper that owns a DebugserverCommandHandle class DebugCommand { public: DebugCommand() = default; DebugCommand(const DebugCommand&) = delete; DebugCommand& operator=(const DebugCommand&) = delete; DebugCommand(DebugCommand&& other) noexcept : handle_(other.handle_) { other.handle_ = nullptr; } DebugCommand& operator=(DebugCommand&& other) noexcept { if (this != &other) { reset(); handle_ = other.handle_; other.handle_ = nullptr; } return *this; } ~DebugCommand() { reset(); } static Option make(const std::string& name, const std::vector& argv); ::DebugserverCommandHandle* raw() const { return handle_; } private: explicit DebugCommand(::DebugserverCommandHandle* h) : handle_(h) {} void reset() { if (handle_) { ::debugserver_command_free(handle_); handle_ = nullptr; } } ::DebugserverCommandHandle* handle_ = nullptr; }; } // namespace IdeviceFFI