forked from jkcoxson/idevice
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrsd.cpp
More file actions
151 lines (135 loc) · 4.38 KB
/
Copy pathrsd.cpp
File metadata and controls
151 lines (135 loc) · 4.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// Jackson Coxson
#include <idevice++/rsd.hpp>
namespace IdeviceFFI {
// ---------- helpers to copy/free CRsdService ----------
static RsdService to_cpp_and_free(CRsdService* c) {
RsdService s;
if (c->name) {
s.name = c->name;
}
if (c->entitlement) {
s.entitlement = c->entitlement;
}
s.port = c->port;
s.uses_remote_xpc = c->uses_remote_xpc;
s.service_version = c->service_version;
// features
if (c->features && c->features_count > 0) {
auto** arr = c->features;
s.features.reserve(c->features_count);
for (size_t i = 0; i < c->features_count; ++i) {
if (arr[i]) {
s.features.emplace_back(arr[i]);
}
}
}
// release the C allocation now that we've copied
rsd_free_service(c);
return s;
}
static std::vector<RsdService> to_cpp_and_free(CRsdServiceArray* arr) {
std::vector<RsdService> out;
if (!arr || !arr->services || arr->count == 0) {
if (arr) {
rsd_free_services(arr);
}
return out;
}
out.reserve(arr->count);
auto* begin = arr->services;
for (size_t i = 0; i < arr->count; ++i) {
out.emplace_back(RsdService{begin[i].name ? begin[i].name : "",
begin[i].entitlement ? begin[i].entitlement : "",
begin[i].port,
begin[i].uses_remote_xpc,
{}, // features, fill below
begin[i].service_version});
// features for this service
if (begin[i].features && begin[i].features_count > 0) {
auto** feats = begin[i].features;
out.back().features.reserve(begin[i].features_count);
for (size_t j = 0; j < begin[i].features_count; ++j) {
if (feats[j]) {
out.back().features.emplace_back(feats[j]);
}
}
}
}
// free the array + nested C strings now that we've copied
rsd_free_services(arr);
return out;
}
RsdHandshake::RsdHandshake(const RsdHandshake& other) {
if (other.handle_) {
// Call the Rust FFI to clone the underlying handle
handle_.reset(rsd_handshake_clone(other.handle_.get()));
}
// If other.handle_ is null, our new handle_ will also be null, which is correct.
}
RsdHandshake& RsdHandshake::operator=(const RsdHandshake& other) {
// Check for self-assignment
if (this != &other) {
// Create a temporary copy, then swap ownership
RsdHandshake temp(other);
std::swap(handle_, temp.handle_);
}
return *this;
}
// ---------- factory ----------
Result<RsdHandshake, FfiError> RsdHandshake::from_socket(ReadWrite&& rw) {
RsdHandshakeHandle* out = nullptr;
// Rust consumes the socket regardless of result ⇒ release BEFORE call.
ReadWriteOpaque* raw = rw.release();
FfiError e(rsd_handshake_new(raw, &out));
if (e) {
return Err(e);
}
return Ok(RsdHandshake::adopt(out));
}
// ---------- queries ----------
Result<size_t, FfiError> RsdHandshake::protocol_version() const {
size_t v = 0;
FfiError e(rsd_get_protocol_version(handle_.get(), &v));
if (e) {
return Err(e);
}
return Ok(v);
}
Result<std::string, FfiError> RsdHandshake::uuid() const {
char* c = nullptr;
FfiError e(rsd_get_uuid(handle_.get(), &c));
if (e) {
return Err(e);
}
std::string out;
if (c) {
out = c;
rsd_free_string(c);
}
return Ok(out);
}
Result<std::vector<RsdService>, FfiError> RsdHandshake::services() const {
CRsdServiceArray* arr = nullptr;
FfiError e(rsd_get_services(handle_.get(), &arr));
if (e) {
return Err(e);
}
return Ok(to_cpp_and_free(arr));
}
Result<bool, FfiError> RsdHandshake::service_available(const std::string& name) const {
bool avail = false;
FfiError e(rsd_service_available(handle_.get(), name.c_str(), &avail));
if (e) {
return Err(e);
}
return Ok(avail);
}
Result<RsdService, FfiError> RsdHandshake::service_info(const std::string& name) const {
CRsdService* svc = nullptr;
FfiError e(rsd_get_service_info(handle_.get(), name.c_str(), &svc));
if (e) {
return Err(e);
}
return Ok(to_cpp_and_free(svc));
}
} // namespace IdeviceFFI