28
std::string P2PDeviceStub::StatusToString(Status status) {
30
case Status::kSucccesAcceptedByUser:
31
case Status::kSuccess:
33
case Status::kInformationIsCurrentlyUnavailable:
34
return "Information is currently unavailable";
35
case Status::kIncompatibleParameters:
36
return "Incompatible parameters";
37
case Status::kLimitReached:
38
return "Limit reached";
39
case Status::kInvalidParameter:
40
return "Invalid parameter";
41
case Status::kUnableToAccommodateRequest:
42
return "Unable to accommodate request";
43
case Status::kProtcolErrorOrDisruptiveBehavior:
44
return "Protocol error or disruptive behavior";
45
case Status::kNoCommonChannel:
46
return "No common channels";
47
case Status::kUnknownP2PGroup:
48
return "Unknown P2P group";
49
case Status::kBothGOIntent15:
50
return "Both P2P devices indicated an intent of 15 in group owner negotiation";
51
case Status::kIncompatibleProvisioningMethod:
52
return "Incompatible provisioning method";
53
case Status::kRejectByUser:
54
return "Rejected by user";
59
return "Failed: unknown error";
62
std::string P2PDeviceStub::PropertyToString(Property property) {
64
case Property::kPeerObject:
66
case Property::kStatus:
68
case Property::kFrequency:
70
case Property::kFrequencyList:
71
return "frequency_list";
72
case Property::kWpsMethod:
80
P2PDeviceStub::WpsMethod P2PDeviceStub::WpsMethodFromString(const std::string &wps_method) {
81
if (wps_method == "pin")
82
return WpsMethod::kPin;
83
// In all other cases we directly fallback to PBC
84
return WpsMethod::kPbc;
87
std::string P2PDeviceStub::WpsMethodToString(WpsMethod wps_method) {
28
99
P2PDeviceStub::Ptr P2PDeviceStub::Create(const std::string &object_path, const std::weak_ptr<P2PDeviceStub::Delegate> &delegate) {
29
100
return std::shared_ptr<P2PDeviceStub>(new P2PDeviceStub(delegate))->FinalizeConstruction(object_path);
110
181
auto inst = static_cast<mcs::WeakKeepAlive<P2PDeviceStub>*>(user_data)->GetInstance().lock();
112
183
std::string peer_path;
184
GroupOwnerNegotiationResult result;
114
186
mcs::DBusHelpers::ParseDictionary(properties, [&](const std::string &name, GVariant *value) {
115
if (name == "peer_object")
116
peer_path = g_variant_get_string(g_variant_get_variant(value), nullptr);
187
if (name == PropertyToString(Property::kStatus)) {
188
const auto v = g_variant_get_variant(value);
189
if (g_variant_is_of_type(v, G_VARIANT_TYPE("i")))
190
result.status = static_cast<Status>(g_variant_get_int32(v));
192
else if (name == PropertyToString(Property::kPeerObject)) {
193
const auto v = g_variant_get_variant(value);
194
if (g_variant_is_of_type(v, G_VARIANT_TYPE("s")))
195
peer_path = g_variant_get_string(v, nullptr);
197
else if (name == PropertyToString(Property::kFrequency)) {
198
const auto v = g_variant_get_variant(value);
199
if (g_variant_is_of_type(v, G_VARIANT_TYPE("i")))
200
result.oper_freq = g_variant_get_int32(v);
202
else if (name == PropertyToString(Property::kFrequencyList)) {
203
const auto v = g_variant_get_variant(value);
204
for (int n = 0; n < g_variant_n_children(v); n++) {
206
g_variant_get_child(v, n, "i", &freq);
207
result.frequencies.insert(freq);
210
else if (name == PropertyToString(Property::kWpsMethod)) {
211
const auto v = g_variant_get_variant(value);
212
if (g_variant_is_of_type(v, G_VARIANT_TYPE("s")))
213
result.wps_method = WpsMethodFromString(g_variant_get_string(v, nullptr));
119
217
if (peer_path.length() == 0)
122
220
if (auto sp = inst->delegate_.lock())
123
sp->OnGroupOwnerNegotiationSuccess(peer_path);
221
sp->OnGroupOwnerNegotiationSuccess(peer_path, result);
126
224
void P2PDeviceStub::OnGONegotiationFailure(WpaSupplicantInterfaceP2PDevice *device, GVariant *properties, gpointer user_data) {
129
227
auto inst = static_cast<mcs::WeakKeepAlive<P2PDeviceStub>*>(user_data)->GetInstance().lock();
131
229
std::string peer_path;
230
GroupOwnerNegotiationResult result;
134
232
mcs::DBusHelpers::ParseDictionary(properties, [&](const std::string &name, GVariant *value) {
135
233
if (name == "peer_object")
136
234
peer_path = g_variant_get_string(g_variant_get_variant(value), nullptr);
137
235
else if (name == "status")
138
status = g_variant_get_int32(g_variant_get_variant(value));
236
result.status = static_cast<Status>(g_variant_get_int32(g_variant_get_variant(value)));
141
239
if (peer_path.length() == 0)
144
242
if (auto sp = inst->delegate_.lock())
145
sp->OnGroupOwnerNegotiationFailure(peer_path);
243
sp->OnGroupOwnerNegotiationFailure(peer_path, result);
148
246
void P2PDeviceStub::OnGroupStarted(WpaSupplicantInterfaceP2PDevice *device, GVariant *properties, gpointer user_data) {
216
314
void P2PDeviceStub::StartFindTimeout() {
217
315
scan_timeout_source_ = g_timeout_add_seconds(scan_timeout_.count(), [](gpointer user_data) {
218
auto inst = static_cast<mcs::SharedKeepAlive<P2PDeviceStub>*>(user_data)->ShouldDie();
220
inst->StopFindTimeout();
316
auto inst = static_cast<mcs::WeakKeepAlive<P2PDeviceStub>*>(user_data)->GetInstance().lock();
321
inst->scan_timeout_source_ = 0;
324
if (auto sp = inst->delegate_.lock())
325
sp->OnP2PDeviceChanged();
223
}, new mcs::SharedKeepAlive<P2PDeviceStub>{shared_from_this()});
328
}, new mcs::WeakKeepAlive<P2PDeviceStub>{shared_from_this()});
226
331
void P2PDeviceStub::StopFindTimeout() {
227
332
if (scan_timeout_source_ == 0)
335
g_source_remove(scan_timeout_source_);
230
336
scan_timeout_source_ = 0;
231
337
scan_timeout_ = std::chrono::seconds{0};
234
339
if (auto sp = delegate_.lock())
235
340
sp->OnP2PDeviceChanged();
290
395
g_error_free(error);
294
398
}, new mcs::SharedKeepAlive<P2PDeviceStub>{shared_from_this()});
296
400
StopFindTimeout();
299
bool P2PDeviceStub::Connect(const std::string &path) {
403
bool P2PDeviceStub::Connect(const std::string &path, const std::int32_t intent) {
302
406
if (!proxy_ || path.length() == 0)
307
411
auto builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
413
MCS_DEBUG("Using GO intent %d", intent);
309
415
g_variant_builder_add(builder, "{sv}", "peer", g_variant_new_object_path(path.c_str()));
310
416
// We support only WPS PBC for now
311
g_variant_builder_add(builder, "{sv}", "wps_method", g_variant_new_string("pbc"));
417
g_variant_builder_add(builder, "{sv}", "wps_method", g_variant_new_string(WpsMethodToString(WpsMethod::kPbc).c_str()));
418
g_variant_builder_add(builder, "{sv}", "go_intent", g_variant_new_int32(intent));
313
420
auto arguments = g_variant_builder_end(builder);