1 /*
2 * Copyright (C) 2021-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "peer_to_peer_group.h"
17
18 #include "alg_defs.h"
19 #include "callback_manager.h"
20 #include "channel_manager.h"
21 #include "data_manager.h"
22 #include "dev_auth_module_manager.h"
23 #include "group_operation_common.h"
24 #include "hc_dev_info.h"
25 #include "hc_log.h"
26 #include "hisysevent_adapter.h"
27 #include "hitrace_adapter.h"
28 #include "string_util.h"
29
IsSameNameGroupExist(int32_t osAccountId,const char * ownerName,const char * groupName)30 static bool IsSameNameGroupExist(int32_t osAccountId, const char *ownerName, const char *groupName)
31 {
32 if ((ownerName == NULL) || (groupName == NULL)) {
33 LOGE("The input ownerName or groupName is NULL!");
34 return false;
35 }
36 QueryGroupParams queryParams = InitQueryGroupParams();
37 queryParams.ownerName = ownerName;
38 queryParams.groupName = groupName;
39 GroupEntryVec groupEntryVec = CreateGroupEntryVec();
40 int32_t result = QueryGroups(osAccountId, &queryParams, &groupEntryVec);
41 if (result != HC_SUCCESS) {
42 ClearGroupEntryVec(&groupEntryVec);
43 return result;
44 }
45 if (HC_VECTOR_SIZE(&groupEntryVec) > 0) {
46 ClearGroupEntryVec(&groupEntryVec);
47 return true;
48 }
49 ClearGroupEntryVec(&groupEntryVec);
50 return false;
51 }
52
CheckGroupName(int32_t osAccountId,const char * appId,const CJson * jsonParams)53 static int32_t CheckGroupName(int32_t osAccountId, const char *appId, const CJson *jsonParams)
54 {
55 const char *groupName = GetStringFromJson(jsonParams, FIELD_GROUP_NAME);
56 if (groupName == NULL) {
57 LOGE("Failed to get groupName from jsonParams!");
58 return HC_ERR_JSON_GET;
59 }
60
61 if (IsSameNameGroupExist(osAccountId, appId, groupName)) {
62 LOGE("A group with the same group name has been created! [AppId]: %s, [GroupName]: %s", appId, groupName);
63 return HC_ERR_INVALID_PARAMS;
64 }
65 return HC_SUCCESS;
66 }
67
GenerateGroupId(const char * groupName,const char * appId,char ** returnGroupId)68 static int32_t GenerateGroupId(const char *groupName, const char *appId, char **returnGroupId)
69 {
70 /* peer to peer group: groupId = sha256(groupName | appId) */
71 uint8_t *hashMessage = NULL;
72 uint32_t messageSize = 0;
73 Uint8Buff groupNameBuff = {(uint8_t *)groupName, HcStrlen(groupName)};
74 Uint8Buff appIdBuff = {(uint8_t *)appId, HcStrlen(appId)};
75 int32_t result = GetHashMessage(&groupNameBuff, &appIdBuff, &hashMessage, &messageSize);
76 if (result != HC_SUCCESS) {
77 return result;
78 }
79 int hashStrLen = SHA256_LEN * BYTE_TO_HEX_OPER_LENGTH + 1;
80 *returnGroupId = (char *)HcMalloc(hashStrLen, 0);
81 if (*returnGroupId == NULL) {
82 LOGE("Failed to allocate returnGroupId memory!");
83 HcFree(hashMessage);
84 return HC_ERR_ALLOC_MEMORY;
85 }
86 result = GetHashResult(hashMessage, messageSize, *returnGroupId, hashStrLen);
87 HcFree(hashMessage);
88 if (result != HC_SUCCESS) {
89 LOGE("Failed to get hash for groupId! [AppId]: %s, [GroupName]: %s", appId, groupName);
90 HcFree(*returnGroupId);
91 *returnGroupId = NULL;
92 return HC_ERR_HASH_FAIL;
93 }
94 return HC_SUCCESS;
95 }
96
GeneratePeerToPeerGroupId(const CJson * jsonParams,char ** returnGroupId)97 static int32_t GeneratePeerToPeerGroupId(const CJson *jsonParams, char **returnGroupId)
98 {
99 const char *groupName = GetStringFromJson(jsonParams, FIELD_GROUP_NAME);
100 if (groupName == NULL) {
101 LOGE("Failed to get groupName from jsonParams!");
102 return HC_ERR_JSON_GET;
103 }
104 const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID);
105 if (appId == NULL) {
106 LOGE("Failed to get appId from jsonParams!");
107 return HC_ERR_JSON_GET;
108 }
109 int32_t result = GenerateGroupId(groupName, appId, returnGroupId);
110 if (result != HC_SUCCESS) {
111 LOGE("Failed to generate groupId! [GroupName]: %s, [AppId]: %s", groupName, appId);
112 return result;
113 }
114 return HC_SUCCESS;
115 }
116
CheckCreateParams(int32_t osAccountId,const CJson * jsonParams)117 static int32_t CheckCreateParams(int32_t osAccountId, const CJson *jsonParams)
118 {
119 const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID);
120 if (appId == NULL) {
121 LOGE("Failed to get appId from jsonParams!");
122 return HC_ERR_JSON_GET;
123 }
124 int32_t result;
125 if (((result = CheckGroupName(osAccountId, appId, jsonParams)) != HC_SUCCESS) ||
126 ((result = CheckUserTypeIfExist(jsonParams)) != HC_SUCCESS) ||
127 ((result = CheckGroupVisibilityIfExist(jsonParams)) != HC_SUCCESS) ||
128 ((result = CheckExpireTimeIfExist(jsonParams)) != HC_SUCCESS) ||
129 ((result = CheckGroupNumLimit(osAccountId, PEER_TO_PEER_GROUP, appId)) != HC_SUCCESS)) {
130 return result;
131 }
132 return HC_SUCCESS;
133 }
134
GenerateGroupParams(const CJson * jsonParams,const char * groupId,TrustedGroupEntry * groupParams)135 static int32_t GenerateGroupParams(const CJson *jsonParams, const char *groupId, TrustedGroupEntry *groupParams)
136 {
137 const char *groupName = GetStringFromJson(jsonParams, FIELD_GROUP_NAME);
138 if (groupName == NULL) {
139 LOGE("Failed to get groupName from jsonParams!");
140 return HC_ERR_JSON_GET;
141 }
142 const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID);
143 if (appId == NULL) {
144 LOGE("Failed to get appId from jsonParams!");
145 return HC_ERR_JSON_GET;
146 }
147 int32_t result;
148 if (((result = AddGroupTypeToParams(PEER_TO_PEER_GROUP, groupParams)) != HC_SUCCESS) ||
149 ((result = AddGroupNameToParams(groupName, groupParams)) != HC_SUCCESS) ||
150 ((result = AddGroupIdToParams(groupId, groupParams)) != HC_SUCCESS) ||
151 ((result = AddGroupOwnerToParams(appId, groupParams)) != HC_SUCCESS) ||
152 ((result = AddGroupVisibilityOrDefault(jsonParams, groupParams)) != HC_SUCCESS) ||
153 ((result = AddExpireTimeOrDefault(jsonParams, groupParams)) != HC_SUCCESS)) {
154 return result;
155 }
156 return HC_SUCCESS;
157 }
158
GenerateDevParams(const CJson * jsonParams,const char * groupId,TrustedDeviceEntry * devParams)159 static int32_t GenerateDevParams(const CJson *jsonParams, const char *groupId, TrustedDeviceEntry *devParams)
160 {
161 int32_t result;
162 if (((result = AddSelfUdidToParams(devParams)) != HC_SUCCESS) ||
163 ((result = AddAuthIdToParamsOrDefault(jsonParams, devParams)) != HC_SUCCESS) ||
164 ((result = AddSourceToParams(SELF_CREATED, devParams)) != HC_SUCCESS) ||
165 ((result = AddUserTypeToParamsOrDefault(jsonParams, devParams)) != HC_SUCCESS) ||
166 ((result = AddGroupIdToDevParams(groupId, devParams)) != HC_SUCCESS) ||
167 ((result = AddServiceTypeToParams(groupId, devParams)) != HC_SUCCESS)) {
168 return result;
169 }
170 return HC_SUCCESS;
171 }
172
CreateGroupInner(int32_t osAccountId,const CJson * jsonParams,char ** returnGroupId)173 static int32_t CreateGroupInner(int32_t osAccountId, const CJson *jsonParams, char **returnGroupId)
174 {
175 char *groupId = NULL;
176 int32_t result;
177 if (((result = CheckCreateParams(osAccountId, jsonParams)) != HC_SUCCESS) ||
178 ((result = GeneratePeerToPeerGroupId(jsonParams, &groupId)) != HC_SUCCESS) ||
179 ((result = ProcessKeyPair(CREATE_KEY_PAIR, jsonParams, groupId)) != HC_SUCCESS) ||
180 ((result = AddGroupToDatabaseByJson(osAccountId, GenerateGroupParams, jsonParams, groupId)) != HC_SUCCESS) ||
181 ((result = AddDeviceToDatabaseByJson(osAccountId, GenerateDevParams, jsonParams, groupId)) != HC_SUCCESS) ||
182 ((result = SaveOsAccountDb(osAccountId)) != HC_SUCCESS)) {
183 HcFree(groupId);
184 return result;
185 }
186 *returnGroupId = groupId;
187 return HC_SUCCESS;
188 }
189
GetPeerDevUserTypeFromDb(int32_t osAccountId,const char * groupId,const char * peerAuthId)190 static int32_t GetPeerDevUserTypeFromDb(int32_t osAccountId, const char *groupId, const char *peerAuthId)
191 {
192 int peerUserType = DEVICE_TYPE_ACCESSORY;
193 TrustedDeviceEntry *devAuthParams = CreateDeviceEntry();
194 if (devAuthParams == NULL) {
195 LOGE("Failed to allocate devEntry memory!");
196 return peerUserType;
197 }
198 if (GetTrustedDevInfoById(osAccountId, peerAuthId, false, groupId, devAuthParams) != HC_SUCCESS) {
199 LOGE("Failed to obtain the device information from the database!");
200 DestroyDeviceEntry(devAuthParams);
201 return peerUserType;
202 }
203 peerUserType = devAuthParams->devType;
204 DestroyDeviceEntry(devAuthParams);
205 return peerUserType;
206 }
207
DelPeerDevAndKeyInfo(int32_t osAccountId,const char * groupId,const char * peerAuthId)208 static int32_t DelPeerDevAndKeyInfo(int32_t osAccountId, const char *groupId, const char *peerAuthId)
209 {
210 int32_t peerUserType = GetPeerDevUserTypeFromDb(osAccountId, groupId, peerAuthId);
211 QueryDeviceParams queryDeviceParams = InitQueryDeviceParams();
212 queryDeviceParams.groupId = groupId;
213 queryDeviceParams.authId = peerAuthId;
214 int32_t result = DelTrustedDevice(osAccountId, &queryDeviceParams);
215 if (result != HC_SUCCESS) {
216 LOGE("Failed to delete peer device from database!");
217 return result;
218 }
219 /* Use the DeviceGroupManager package name. */
220 const char *appId = GROUP_MANAGER_PACKAGE_NAME;
221 Uint8Buff peerAuthIdBuff = {
222 .val = (uint8_t *)peerAuthId,
223 .length = HcStrlen(peerAuthId)
224 };
225 /*
226 * If the trusted device has been deleted from the database but the peer key fails to be deleted,
227 * the forcible unbinding is still considered successful. Only logs need to be printed.
228 */
229 result = DeletePeerAuthInfo(appId, groupId, &peerAuthIdBuff, peerUserType, DAS_MODULE);
230 if (result != HC_SUCCESS) {
231 LOGD("delete peer key fail! res: %d", result);
232 } else {
233 LOGD("delete peer key success!");
234 }
235 return HC_SUCCESS;
236 }
237
DelAllPeerDevAndKeyInfo(int32_t osAccountId,const char * groupId)238 static int32_t DelAllPeerDevAndKeyInfo(int32_t osAccountId, const char *groupId)
239 {
240 QueryDeviceParams queryParams = InitQueryDeviceParams();
241 queryParams.groupId = groupId;
242 DeviceEntryVec deviceEntryVec = CreateDeviceEntryVec();
243 int32_t result = QueryDevices(osAccountId, &queryParams, &deviceEntryVec);
244 if (result != HC_SUCCESS) {
245 ClearDeviceEntryVec(&deviceEntryVec);
246 return result;
247 }
248 uint32_t index;
249 TrustedDeviceEntry **entryPtr = NULL;
250 FOR_EACH_HC_VECTOR(deviceEntryVec, index, entryPtr) {
251 TrustedDeviceEntry *entry = (TrustedDeviceEntry *)(*entryPtr);
252 if (IsLocalDevice(StringGet(&entry->udid))) {
253 continue;
254 }
255 result = DelPeerDevAndKeyInfo(osAccountId, groupId, StringGet(&entry->authId));
256 if (result != HC_SUCCESS) {
257 ClearDeviceEntryVec(&deviceEntryVec);
258 return result;
259 }
260 }
261 ClearDeviceEntryVec(&deviceEntryVec);
262 return HC_SUCCESS;
263 }
264
AddAuthIdAndUserTypeToParams(int32_t osAccountId,const char * groupId,CJson * jsonParams)265 static int32_t AddAuthIdAndUserTypeToParams(int32_t osAccountId, const char *groupId, CJson *jsonParams)
266 {
267 TrustedDeviceEntry *deviceInfo = CreateDeviceEntry();
268 if (deviceInfo == NULL) {
269 LOGE("Failed to allocate deviceInfo memory!");
270 return HC_ERR_ALLOC_MEMORY;
271 }
272
273 char localUdid[INPUT_UDID_LEN] = { 0 };
274 int32_t res = HcGetUdid((uint8_t *)localUdid, INPUT_UDID_LEN);
275 if (res != HC_SUCCESS) {
276 LOGE("Failed to get local udid! res: %d", res);
277 DestroyDeviceEntry(deviceInfo);
278 return HC_ERR_DB;
279 }
280
281 if (GetTrustedDevInfoById(osAccountId, localUdid, true, groupId, deviceInfo) != HC_SUCCESS) {
282 LOGE("No local device information found in the group, udid changed.");
283 DestroyDeviceEntry(deviceInfo);
284 return HC_ERR_DB;
285 }
286
287 if (AddStringToJson(jsonParams, FIELD_DEVICE_ID, StringGet(&deviceInfo->authId)) != HC_SUCCESS) {
288 LOGE("Failed to add authId to params!");
289 DestroyDeviceEntry(deviceInfo);
290 return HC_ERR_JSON_FAIL;
291 }
292 if (AddIntToJson(jsonParams, FIELD_USER_TYPE, deviceInfo->devType) != HC_SUCCESS) {
293 LOGE("Failed to add userType to params!");
294 DestroyDeviceEntry(deviceInfo);
295 return HC_ERR_JSON_FAIL;
296 }
297 DestroyDeviceEntry(deviceInfo);
298 return HC_SUCCESS;
299 }
300
DelGroupAndSelfKeyInfo(int32_t osAccountId,const char * groupId,CJson * jsonParams)301 static int32_t DelGroupAndSelfKeyInfo(int32_t osAccountId, const char *groupId, CJson *jsonParams)
302 {
303 int32_t result = DelGroupFromDb(osAccountId, groupId);
304 if (result != HC_SUCCESS) {
305 return result;
306 }
307 /*
308 * If the group has been disbanded from the database but the key pair fails to be deleted,
309 * we still believe we succeeded in disbanding the group. Only logs need to be printed.
310 */
311 result = AddAuthIdAndUserTypeToParams(osAccountId, groupId, jsonParams);
312 if (result == HC_SUCCESS) {
313 result = ProcessKeyPair(DELETE_KEY_PAIR, jsonParams, groupId);
314 }
315 if (result != HC_SUCCESS) {
316 LOGW("delete self key fail! res: %d", result);
317 } else {
318 LOGI("delete self key success!");
319 }
320 return HC_SUCCESS;
321 }
322
HandleLocalUnbind(int64_t requestId,const CJson * jsonParams,const DeviceAuthCallback * callback)323 static int32_t HandleLocalUnbind(int64_t requestId, const CJson *jsonParams,
324 const DeviceAuthCallback *callback)
325 {
326 const char *peerAuthId = GetStringFromJson(jsonParams, FIELD_DELETE_ID);
327 if (peerAuthId == NULL) {
328 LOGE("Failed to get peerAuthId from jsonParams!");
329 return HC_ERR_JSON_GET;
330 }
331 const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID);
332 if (groupId == NULL) {
333 LOGE("Failed to get groupId from jsonParams!");
334 return HC_ERR_JSON_GET;
335 }
336 int32_t osAccountId;
337 if (GetIntFromJson(jsonParams, FIELD_OS_ACCOUNT_ID, &osAccountId) != HC_SUCCESS) {
338 LOGE("Failed to get osAccountId from jsonParams!");
339 return HC_ERR_JSON_GET;
340 }
341 int result = DelPeerDevAndKeyInfo(osAccountId, groupId, peerAuthId);
342 if (result != HC_SUCCESS) {
343 return result;
344 }
345 result = SaveOsAccountDb(osAccountId);
346 if (result != HC_SUCCESS) {
347 LOGE("Failed to save osAccountDb!");
348 return result;
349 }
350 char *returnDataStr = NULL;
351 result = GenerateUnbindSuccessData(peerAuthId, groupId, &returnDataStr);
352 if (result != HC_SUCCESS) {
353 return result;
354 }
355 ProcessFinishCallback(requestId, MEMBER_DELETE, returnDataStr, callback);
356 FreeJsonString(returnDataStr);
357 return HC_SUCCESS;
358 }
359
CheckPeerDeviceStatus(int32_t osAccountId,const char * groupId,const CJson * jsonParams)360 static int32_t CheckPeerDeviceStatus(int32_t osAccountId, const char *groupId, const CJson *jsonParams)
361 {
362 const char *peerAuthId = GetStringFromJson(jsonParams, FIELD_DELETE_ID);
363 if (peerAuthId == NULL) {
364 LOGE("Failed to get peerAuthId from jsonParams!");
365 return HC_ERR_JSON_GET;
366 }
367 PRINT_SENSITIVE_DATA("PeerAuthId", peerAuthId);
368 TrustedDeviceEntry *deviceInfo = CreateDeviceEntry();
369 if (deviceInfo == NULL) {
370 LOGE("Failed to allocate deviceInfo memory!");
371 return HC_ERR_ALLOC_MEMORY;
372 }
373 int32_t result = GetTrustedDevInfoById(osAccountId, peerAuthId, false, groupId, deviceInfo);
374 if (result != HC_SUCCESS) {
375 LOGE("Failed to obtain the peer device information from the database!");
376 DestroyDeviceEntry(deviceInfo);
377 return result;
378 }
379 result = AssertPeerDeviceNotSelf(StringGet(&deviceInfo->udid));
380 DestroyDeviceEntry(deviceInfo);
381 return result;
382 }
383
CheckDeletePeerStatus(const CJson * jsonParams)384 static int32_t CheckDeletePeerStatus(const CJson *jsonParams)
385 {
386 const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID);
387 if (groupId == NULL) {
388 LOGE("Failed to get groupId from jsonParams!");
389 return HC_ERR_JSON_GET;
390 }
391 const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID);
392 if (appId == NULL) {
393 LOGE("Failed to get appId from jsonParams!");
394 return HC_ERR_JSON_GET;
395 }
396 int32_t osAccountId;
397 if (GetIntFromJson(jsonParams, FIELD_OS_ACCOUNT_ID, &osAccountId) != HC_SUCCESS) {
398 LOGE("Failed to get osAccountId from jsonParams!");
399 return HC_ERR_JSON_GET;
400 }
401
402 int32_t groupType = PEER_TO_PEER_GROUP;
403 int32_t result;
404 if (((result = CheckGroupExist(osAccountId, groupId)) != HC_SUCCESS) ||
405 ((result = GetGroupTypeFromDb(osAccountId, groupId, &groupType)) != HC_SUCCESS) ||
406 ((result = AssertGroupTypeMatch(groupType, PEER_TO_PEER_GROUP)) != HC_SUCCESS) ||
407 ((result = CheckPermForGroup(osAccountId, MEMBER_DELETE, appId, groupId)) != HC_SUCCESS) ||
408 ((result = CheckPeerDeviceStatus(osAccountId, groupId, jsonParams)) != HC_SUCCESS)) {
409 return result;
410 }
411 return HC_SUCCESS;
412 }
413
IsLocalForceUnbind(const CJson * jsonParams)414 static bool IsLocalForceUnbind(const CJson *jsonParams)
415 {
416 bool isForceDelete = false;
417 (void)GetBoolFromJson(jsonParams, FIELD_IS_FORCE_DELETE, &isForceDelete);
418 bool isIgnoreChannel = false;
419 (void)GetBoolFromJson(jsonParams, FIELD_IS_IGNORE_CHANNEL, &isIgnoreChannel);
420 return (isForceDelete && isIgnoreChannel);
421 }
422
CreateGroup(int32_t osAccountId,CJson * jsonParams,char ** returnJsonStr)423 static int32_t CreateGroup(int32_t osAccountId, CJson *jsonParams, char **returnJsonStr)
424 {
425 LOGI("[Start]: Start to create a peer to peer group!");
426 if ((jsonParams == NULL) || (returnJsonStr == NULL)) {
427 LOGE("The input parameters contains NULL value!");
428 return HC_ERR_INVALID_PARAMS;
429 }
430 char *groupId = NULL;
431 int32_t result = CreateGroupInner(osAccountId, jsonParams, &groupId);
432 if (result != HC_SUCCESS) {
433 return result;
434 }
435 result = ConvertGroupIdToJsonStr(groupId, returnJsonStr);
436 HcFree(groupId);
437 if (result != HC_SUCCESS) {
438 return result;
439 }
440 LOGI("[End]: Create a peer to peer group successfully!");
441 return HC_SUCCESS;
442 }
443
DeleteGroup(int32_t osAccountId,CJson * jsonParams,char ** returnJsonStr)444 static int32_t DeleteGroup(int32_t osAccountId, CJson *jsonParams, char **returnJsonStr)
445 {
446 LOGI("[Start]: Start to delete a peer to peer group!");
447 if ((jsonParams == NULL) || (returnJsonStr == NULL)) {
448 LOGE("The input parameters contains NULL value!");
449 return HC_ERR_INVALID_PARAMS;
450 }
451 int32_t result;
452 const char *groupId = NULL;
453 if (((result = GetGroupIdFromJson(jsonParams, &groupId)) != HC_SUCCESS) ||
454 ((result = DelAllPeerDevAndKeyInfo(osAccountId, groupId)) != HC_SUCCESS) ||
455 ((result = DelGroupAndSelfKeyInfo(osAccountId, groupId, jsonParams)) != HC_SUCCESS) ||
456 ((result = ConvertGroupIdToJsonStr(groupId, returnJsonStr)) != HC_SUCCESS)) {
457 return result;
458 }
459 LOGI("[End]: Delete a peer to peer group successfully!");
460 return HC_SUCCESS;
461 }
462
DeleteMemberFromGroup(int32_t osAccountId,int64_t requestId,CJson * jsonParams,const DeviceAuthCallback * callback)463 static int32_t DeleteMemberFromGroup(int32_t osAccountId, int64_t requestId, CJson *jsonParams,
464 const DeviceAuthCallback *callback)
465 {
466 LOGI("[Start]: Start to delete member from a peer to peer group!");
467 if ((jsonParams == NULL) || (callback == NULL)) {
468 LOGE("The input parameters contains NULL value!");
469 return HC_ERR_INVALID_PARAMS;
470 }
471 AddIntToJson(jsonParams, FIELD_OS_ACCOUNT_ID, osAccountId);
472 int32_t result = CheckDeletePeerStatus(jsonParams);
473 if (result != HC_SUCCESS) {
474 ProcessErrorCallback(requestId, MEMBER_DELETE, result, NULL, callback);
475 return result;
476 }
477 if (!IsLocalForceUnbind(jsonParams)) {
478 ProcessErrorCallback(requestId, MEMBER_DELETE, HC_ERR_INVALID_PARAMS, NULL, callback);
479 return HC_ERR_INVALID_PARAMS;
480 }
481 result = HandleLocalUnbind(requestId, jsonParams, callback);
482 if (result != HC_SUCCESS) {
483 ProcessErrorCallback(requestId, MEMBER_DELETE, result, NULL, callback);
484 }
485 return result;
486 }
487
488 static PeerToPeerGroup g_peerToPeerGroup = {
489 .base.type = PEER_TO_PEER_GROUP,
490 .base.createGroup = CreateGroup,
491 .base.deleteGroup = DeleteGroup,
492 .deleteMember = DeleteMemberFromGroup,
493 };
494
GetPeerToPeerGroupInstance(void)495 BaseGroup *GetPeerToPeerGroupInstance(void)
496 {
497 return (BaseGroup *)&g_peerToPeerGroup;
498 }
499
IsPeerToPeerGroupSupported(void)500 bool IsPeerToPeerGroupSupported(void)
501 {
502 return true;
503 }
504