mirror of
https://github.com/jkcoxson/idevice.git
synced 2026-03-02 14:36:16 +01:00
Separate headers into cpp source files
This commit is contained in:
17
cpp/src/ffi.cpp
Normal file
17
cpp/src/ffi.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
// Jackson Coxson
|
||||
|
||||
#include <idevice++/bindings.hpp>
|
||||
#include <idevice++/ffi.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace IdeviceFFI {
|
||||
FfiError::FfiError(const IdeviceFfiError* err)
|
||||
: code(err ? err->code : 0), message(err && err->message ? err->message : "") {
|
||||
if (err) {
|
||||
idevice_error_free(const_cast<IdeviceFfiError*>(err));
|
||||
}
|
||||
}
|
||||
|
||||
FfiError::FfiError() : code(0), message("") {
|
||||
}
|
||||
} // namespace IdeviceFFI
|
||||
56
cpp/src/idevice.cpp
Normal file
56
cpp/src/idevice.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
// Jackson Coxson
|
||||
|
||||
#include <idevice++/idevice.hpp>
|
||||
|
||||
namespace IdeviceFFI {
|
||||
|
||||
std::optional<Idevice>
|
||||
Idevice::create(IdeviceSocketHandle* socket, const std::string& label, FfiError& err) {
|
||||
IdeviceHandle* h = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_new(socket, label.c_str(), &h)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return Idevice(h);
|
||||
}
|
||||
|
||||
std::optional<Idevice> Idevice::create_tcp(const sockaddr* addr,
|
||||
socklen_t addr_len,
|
||||
const std::string& label,
|
||||
FfiError& err) {
|
||||
IdeviceHandle* h = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_new_tcp_socket(addr, addr_len, label.c_str(), &h)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return Idevice(h);
|
||||
}
|
||||
|
||||
std::optional<std::string> Idevice::get_type(FfiError& err) const {
|
||||
char* cstr = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_get_type(handle_.get(), &cstr)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
std::string out(cstr);
|
||||
idevice_string_free(cstr);
|
||||
return out;
|
||||
}
|
||||
|
||||
bool Idevice::rsd_checkin(FfiError& err) {
|
||||
if (IdeviceFfiError* e = idevice_rsd_checkin(handle_.get())) {
|
||||
err = FfiError(e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Idevice::start_session(const PairingFile& pairing_file, FfiError& err) {
|
||||
if (IdeviceFfiError* e = idevice_start_session(handle_.get(), pairing_file.raw())) {
|
||||
err = FfiError(e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace IdeviceFFI
|
||||
67
cpp/src/lockdown.cpp
Normal file
67
cpp/src/lockdown.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
// Jackson Coxson
|
||||
|
||||
#include <idevice++/bindings.hpp>
|
||||
#include <idevice++/ffi.hpp>
|
||||
#include <idevice++/lockdown.hpp>
|
||||
#include <idevice++/provider.hpp>
|
||||
|
||||
namespace IdeviceFFI {
|
||||
|
||||
std::optional<Lockdown> Lockdown::connect(Provider& provider, FfiError& err) {
|
||||
LockdowndClientHandle* out = nullptr;
|
||||
|
||||
if (IdeviceFfiError* e = ::lockdownd_connect(provider.raw(), &out)) {
|
||||
// Rust freed the provider on error -> abandon our ownership to avoid double free.
|
||||
// Your Provider wrapper should expose release().
|
||||
provider.release();
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
// Success: provider is NOT consumed; keep ownership.
|
||||
return Lockdown::adopt(out);
|
||||
}
|
||||
|
||||
std::optional<Lockdown> Lockdown::from_socket(Idevice&& socket, FfiError& err) {
|
||||
LockdowndClientHandle* out = nullptr;
|
||||
|
||||
if (IdeviceFfiError* e = ::lockdownd_new(socket.raw(), &out)) {
|
||||
// Error: Rust did NOT consume the socket (it returns early for invalid args),
|
||||
// so keep ownership; report error.
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
// Success: Rust consumed the socket -> abandon our ownership.
|
||||
socket.release();
|
||||
return Lockdown::adopt(out);
|
||||
}
|
||||
|
||||
bool Lockdown::start_session(const PairingFile& pf, FfiError& err) {
|
||||
if (IdeviceFfiError* e = ::lockdownd_start_session(handle_.get(), pf.raw())) {
|
||||
err = FfiError(e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<std::pair<uint16_t, bool>> Lockdown::start_service(const std::string& identifier,
|
||||
FfiError& err) {
|
||||
uint16_t port = 0;
|
||||
bool ssl = false;
|
||||
if (IdeviceFfiError* e =
|
||||
::lockdownd_start_service(handle_.get(), identifier.c_str(), &port, &ssl)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return std::make_pair(port, ssl);
|
||||
}
|
||||
|
||||
std::optional<plist_t> Lockdown::get_value(const char* key, const char* domain, FfiError& err) {
|
||||
plist_t out = nullptr;
|
||||
if (IdeviceFfiError* e = ::lockdownd_get_value(handle_.get(), key, domain, &out)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return out; // caller now owns `out` and must free with the plist API
|
||||
}
|
||||
|
||||
} // namespace IdeviceFFI
|
||||
53
cpp/src/pairing_file.cpp
Normal file
53
cpp/src/pairing_file.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
// Jackson Coxson
|
||||
|
||||
#include <idevice++/bindings.hpp>
|
||||
#include <idevice++/ffi.hpp>
|
||||
#include <idevice++/pairing_file.hpp>
|
||||
|
||||
namespace IdeviceFFI {
|
||||
|
||||
// Deleter definition (out-of-line)
|
||||
void PairingFileDeleter::operator()(IdevicePairingFile* p) const noexcept {
|
||||
if (p)
|
||||
idevice_pairing_file_free(p);
|
||||
}
|
||||
|
||||
// Static member definitions
|
||||
std::optional<PairingFile> PairingFile::read(const std::string& path, FfiError& err) {
|
||||
IdevicePairingFile* ptr = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_pairing_file_read(path.c_str(), &ptr)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return PairingFile(ptr);
|
||||
}
|
||||
|
||||
std::optional<PairingFile>
|
||||
PairingFile::from_bytes(const uint8_t* data, size_t size, FfiError& err) {
|
||||
IdevicePairingFile* raw = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_pairing_file_from_bytes(data, size, &raw)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return PairingFile(raw);
|
||||
}
|
||||
|
||||
std::optional<std::vector<uint8_t>> PairingFile::serialize(FfiError& err) const {
|
||||
if (!ptr_) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
uint8_t* data = nullptr;
|
||||
size_t size = 0;
|
||||
|
||||
if (IdeviceFfiError* e = idevice_pairing_file_serialize(ptr_.get(), &data, &size)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> out(data, data + size);
|
||||
idevice_data_free(data, size);
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace IdeviceFFI
|
||||
52
cpp/src/provider.cpp
Normal file
52
cpp/src/provider.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
// Jackson Coxson
|
||||
|
||||
#include <idevice++/bindings.hpp>
|
||||
#include <idevice++/ffi.hpp>
|
||||
#include <idevice++/provider.hpp>
|
||||
|
||||
namespace IdeviceFFI {
|
||||
|
||||
std::optional<Provider> Provider::tcp_new(const idevice_sockaddr* ip,
|
||||
PairingFile&& pairing,
|
||||
const std::string& label,
|
||||
FfiError& err) {
|
||||
IdeviceProviderHandle* out = nullptr;
|
||||
|
||||
// Call with exact types; do NOT cast to void*
|
||||
if (IdeviceFfiError* e = idevice_tcp_provider_new(
|
||||
ip, static_cast<IdevicePairingFile*>(pairing.raw()), label.c_str(), &out)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Success: Rust consumed the pairing file -> abandon our ownership
|
||||
pairing.release(); // implement as: ptr_.release() in PairingFile
|
||||
|
||||
return Provider::adopt(out);
|
||||
}
|
||||
|
||||
std::optional<Provider> Provider::usbmuxd_new(UsbmuxdAddr&& addr,
|
||||
uint32_t tag,
|
||||
const std::string& udid,
|
||||
uint32_t device_id,
|
||||
const std::string& label,
|
||||
FfiError& err) {
|
||||
IdeviceProviderHandle* out = nullptr;
|
||||
|
||||
if (IdeviceFfiError* e = usbmuxd_provider_new(static_cast<UsbmuxdAddrHandle*>(addr.raw()),
|
||||
tag,
|
||||
udid.c_str(),
|
||||
device_id,
|
||||
label.c_str(),
|
||||
&out)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Success: Rust consumed the addr -> abandon our ownership
|
||||
addr.release(); // implement as: ptr_.release() in UsbmuxdAddr
|
||||
|
||||
return Provider::adopt(out);
|
||||
}
|
||||
|
||||
} // namespace IdeviceFFI
|
||||
161
cpp/src/usbmuxd.cpp
Normal file
161
cpp/src/usbmuxd.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
// Jackson Coxson
|
||||
|
||||
#include <idevice++/ffi.hpp>
|
||||
#include <idevice++/usbmuxd.hpp>
|
||||
|
||||
namespace IdeviceFFI {
|
||||
|
||||
// ---------- UsbmuxdAddr ----------
|
||||
std::optional<UsbmuxdAddr>
|
||||
UsbmuxdAddr::tcp_new(const sockaddr* addr, socklen_t addr_len, FfiError& err) {
|
||||
UsbmuxdAddrHandle* h = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_usbmuxd_tcp_addr_new(addr, addr_len, &h)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return UsbmuxdAddr(h);
|
||||
}
|
||||
|
||||
#if defined(__unix__) || defined(__APPLE__)
|
||||
std::optional<UsbmuxdAddr> UsbmuxdAddr::unix_new(const std::string& path, FfiError& err) {
|
||||
UsbmuxdAddrHandle* h = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_usbmuxd_unix_addr_new(path.c_str(), &h)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return UsbmuxdAddr(h);
|
||||
}
|
||||
#endif
|
||||
|
||||
UsbmuxdAddr UsbmuxdAddr::default_new() {
|
||||
UsbmuxdAddrHandle* h = nullptr;
|
||||
idevice_usbmuxd_default_addr_new(&h);
|
||||
return UsbmuxdAddr::adopt(h);
|
||||
}
|
||||
|
||||
// ---------- UsbmuxdConnectionType ----------
|
||||
std::string UsbmuxdConnectionType::to_string() const {
|
||||
switch (_value) {
|
||||
case Value::Usb:
|
||||
return "USB";
|
||||
case Value::Network:
|
||||
return "Network";
|
||||
case Value::Unknown:
|
||||
return "Unknown";
|
||||
default:
|
||||
return "UnknownEnumValue";
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- UsbmuxdDevice ----------
|
||||
std::optional<std::string> UsbmuxdDevice::get_udid() const {
|
||||
char* c = idevice_usbmuxd_device_get_udid(handle_.get());
|
||||
if (!c)
|
||||
return std::nullopt;
|
||||
std::string out(c);
|
||||
idevice_string_free(c);
|
||||
return out;
|
||||
}
|
||||
|
||||
std::optional<uint32_t> UsbmuxdDevice::get_id() const {
|
||||
uint32_t id = idevice_usbmuxd_device_get_device_id(handle_.get());
|
||||
if (id == 0)
|
||||
return std::nullopt; // adjust if 0 can be valid
|
||||
return id;
|
||||
}
|
||||
|
||||
std::optional<UsbmuxdConnectionType> UsbmuxdDevice::get_connection_type() const {
|
||||
uint8_t t = idevice_usbmuxd_device_get_connection_type(handle_.get());
|
||||
if (t == 0)
|
||||
return std::nullopt; // adjust to your API contract
|
||||
return UsbmuxdConnectionType(t);
|
||||
}
|
||||
|
||||
// ---------- UsbmuxdConnection ----------
|
||||
std::optional<UsbmuxdConnection> UsbmuxdConnection::tcp_new(const idevice_sockaddr* addr,
|
||||
idevice_socklen_t addr_len,
|
||||
uint32_t tag,
|
||||
FfiError& err) {
|
||||
UsbmuxdConnectionHandle* h = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_usbmuxd_new_tcp_connection(addr, addr_len, tag, &h)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return UsbmuxdConnection(h);
|
||||
}
|
||||
|
||||
#if defined(__unix__) || defined(__APPLE__)
|
||||
std::optional<UsbmuxdConnection>
|
||||
UsbmuxdConnection::unix_new(const std::string& path, uint32_t tag, FfiError& err) {
|
||||
UsbmuxdConnectionHandle* h = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_usbmuxd_new_unix_socket_connection(path.c_str(), tag, &h)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return UsbmuxdConnection(h);
|
||||
}
|
||||
#endif
|
||||
|
||||
std::optional<UsbmuxdConnection> UsbmuxdConnection::default_new(uint32_t tag, FfiError& err) {
|
||||
UsbmuxdConnectionHandle* h = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_usbmuxd_new_default_connection(tag, &h)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return UsbmuxdConnection(h);
|
||||
}
|
||||
|
||||
std::optional<std::vector<UsbmuxdDevice>> UsbmuxdConnection::get_devices(FfiError& err) const {
|
||||
UsbmuxdDeviceHandle** list = nullptr;
|
||||
int count = 0;
|
||||
if (IdeviceFfiError* e = idevice_usbmuxd_get_devices(handle_.get(), &list, &count)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
std::vector<UsbmuxdDevice> out;
|
||||
out.reserve(count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
out.emplace_back(UsbmuxdDevice::adopt(list[i]));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::optional<std::string> UsbmuxdConnection::get_buid(FfiError& err) const {
|
||||
char* c = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_usbmuxd_get_buid(handle_.get(), &c)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
std::string out(c);
|
||||
idevice_string_free(c);
|
||||
return out;
|
||||
}
|
||||
|
||||
std::optional<PairingFile> UsbmuxdConnection::get_pair_record(const std::string& udid,
|
||||
FfiError& err) {
|
||||
IdevicePairingFile* pf = nullptr;
|
||||
if (IdeviceFfiError* e = idevice_usbmuxd_get_pair_record(handle_.get(), udid.c_str(), &pf)) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return PairingFile(pf);
|
||||
}
|
||||
|
||||
std::optional<Idevice> UsbmuxdConnection::connect_to_device(uint32_t device_id,
|
||||
uint16_t port,
|
||||
const std::string& path,
|
||||
FfiError& err) && {
|
||||
UsbmuxdConnectionHandle* raw = handle_.release();
|
||||
|
||||
IdeviceHandle* out = nullptr;
|
||||
IdeviceFfiError* e =
|
||||
idevice_usbmuxd_connect_to_device(raw, device_id, port, path.c_str(), &out);
|
||||
|
||||
if (e) {
|
||||
err = FfiError(e);
|
||||
return std::nullopt;
|
||||
}
|
||||
return Idevice::adopt(out);
|
||||
}
|
||||
|
||||
} // namespace IdeviceFFI
|
||||
Reference in New Issue
Block a user