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