From c6d63d1f5d3d7f7ebe1b5a95193c63a6f85b94df Mon Sep 17 00:00:00 2001 From: Jackson Coxson Date: Tue, 30 Sep 2025 19:02:56 -0600 Subject: [PATCH] Add heartbeat cpp bindings --- cpp/include/idevice++/heartbeat.hpp | 40 ++++++++++++++++++++++++ cpp/src/heartbeat.cpp | 48 +++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 cpp/include/idevice++/heartbeat.hpp create mode 100644 cpp/src/heartbeat.cpp diff --git a/cpp/include/idevice++/heartbeat.hpp b/cpp/include/idevice++/heartbeat.hpp new file mode 100644 index 0000000..48dae0a --- /dev/null +++ b/cpp/include/idevice++/heartbeat.hpp @@ -0,0 +1,40 @@ +#pragma once +#include +#include +#include +#include +#include + +namespace IdeviceFFI { + +using HeartbeatPtr = + std::unique_ptr>; + +class Heartbeat { + public: + // Factory: connect via Provider + static Result connect(Provider& provider); + + // Factory: wrap an existing Idevice socket (consumes it on success) + static Result from_socket(Idevice&& socket); + + // Ops + Result send_polo(); + Result get_marco(u_int64_t interval); + + // RAII / moves + ~Heartbeat() noexcept = default; + Heartbeat(Heartbeat&&) noexcept = default; + Heartbeat& operator=(Heartbeat&&) noexcept = default; + Heartbeat(const Heartbeat&) = delete; + Heartbeat& operator=(const Heartbeat&) = delete; + + HeartbeatClientHandle* raw() const noexcept { return handle_.get(); } + static Heartbeat adopt(HeartbeatClientHandle* h) noexcept { return Heartbeat(h); } + + private: + explicit Heartbeat(HeartbeatClientHandle* h) noexcept : handle_(h) {} + HeartbeatPtr handle_{}; +}; + +} // namespace IdeviceFFI diff --git a/cpp/src/heartbeat.cpp b/cpp/src/heartbeat.cpp new file mode 100644 index 0000000..04c2040 --- /dev/null +++ b/cpp/src/heartbeat.cpp @@ -0,0 +1,48 @@ +// Jackson Coxson + +#include +#include +#include +#include +#include + +namespace IdeviceFFI { + +Result Heartbeat::connect(Provider& provider) { + HeartbeatClientHandle* out = nullptr; + FfiError e(::heartbeat_connect(provider.raw(), &out)); + if (e) { + provider.release(); + return Err(e); + } + return Ok(Heartbeat::adopt(out)); +} + +Result Heartbeat::from_socket(Idevice&& socket) { + HeartbeatClientHandle* out = nullptr; + FfiError e(::heartbeat_new(socket.raw(), &out)); + if (e) { + return Err(e); + } + socket.release(); + return Ok(Heartbeat::adopt(out)); +} + +Result Heartbeat::send_polo() { + FfiError e(::heartbeat_send_polo(handle_.get())); + if (e) { + return Err(e); + } + return Ok(); +} + +Result Heartbeat::get_marco(u_int64_t interval) { + u_int64_t new_interval = 0; + FfiError e(::heartbeat_get_marco(handle_.get(), interval, &new_interval)); + if (e) { + return Err(e); + } + return Ok(new_interval); +} + +} // namespace IdeviceFFI