1 /*
2  * Copyright (C) 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 "compatible_bind_sub_session_util.h"
17 
18 #include "channel_manager.h"
19 #include "dev_auth_module_manager.h"
20 #include "group_operation_common.h"
21 #include "hc_log.h"
22 #include "hc_time.h"
23 #include "hitrace_adapter.h"
24 #include "performance_dumper.h"
25 
AddPinCode(const CJson * returnData,CJson * jsonParams)26 static int32_t AddPinCode(const CJson *returnData, CJson *jsonParams)
27 {
28     const char *pinCode = GetStringFromJson(returnData, FIELD_PIN_CODE);
29     if (pinCode == NULL) {
30         LOGE("Failed to get pinCode from returnData!");
31         return HC_ERR_JSON_GET;
32     }
33     if (AddStringToJson(jsonParams, FIELD_PIN_CODE, pinCode) != HC_SUCCESS) {
34         LOGE("Failed to add pinCode to jsonParams!");
35         return HC_ERR_JSON_ADD;
36     }
37     return HC_SUCCESS;
38 }
39 
AddAuthIdIfExist(const CJson * returnData,CJson * jsonParams)40 static int32_t AddAuthIdIfExist(const CJson *returnData, CJson *jsonParams)
41 {
42     const char *authId = GetStringFromJson(returnData, FIELD_DEVICE_ID);
43     if (authId != NULL && AddStringToJson(jsonParams, FIELD_DEVICE_ID, authId) != HC_SUCCESS) {
44         LOGE("Failed to add authId to jsonParams!");
45         return HC_ERR_JSON_ADD;
46     }
47     return HC_SUCCESS;
48 }
49 
AddUserTypeIfExistAndValid(const CJson * returnData,CJson * jsonParams)50 static int32_t AddUserTypeIfExistAndValid(const CJson *returnData, CJson *jsonParams)
51 {
52     int32_t userType = DEVICE_TYPE_ACCESSORY;
53     if (GetIntFromJson(returnData, FIELD_USER_TYPE, &userType) == HC_SUCCESS) {
54         if (!IsUserTypeValid(userType)) {
55             LOGE("The input userType is invalid!");
56             return HC_ERR_INVALID_PARAMS;
57         }
58         if (AddIntToJson(jsonParams, FIELD_USER_TYPE, userType) != HC_SUCCESS) {
59             LOGE("Failed to add userType to jsonParams!");
60             return HC_ERR_JSON_ADD;
61         }
62     }
63     return HC_SUCCESS;
64 }
65 
AddGroupVisibilityIfExistAndValid(const CJson * returnData,CJson * jsonParams)66 static int32_t AddGroupVisibilityIfExistAndValid(const CJson *returnData, CJson *jsonParams)
67 {
68     int32_t groupVisibility = GROUP_VISIBILITY_PUBLIC;
69     if (GetIntFromJson(returnData, FIELD_GROUP_VISIBILITY, &groupVisibility) == HC_SUCCESS) {
70         if (!IsGroupVisibilityValid(groupVisibility)) {
71             LOGE("The input groupVisibility invalid!");
72             return HC_ERR_INVALID_PARAMS;
73         }
74         if (AddIntToJson(jsonParams, FIELD_GROUP_VISIBILITY, groupVisibility) != HC_SUCCESS) {
75             LOGE("Failed to add groupVisibility to jsonParams!");
76             return HC_ERR_JSON_ADD;
77         }
78     }
79     return HC_SUCCESS;
80 }
81 
AddExpireTimeIfExistAndValid(const CJson * returnData,CJson * jsonParams)82 static int32_t AddExpireTimeIfExistAndValid(const CJson *returnData, CJson *jsonParams)
83 {
84     int32_t expireTime = DEFAULT_EXPIRE_TIME;
85     if (GetIntFromJson(returnData, FIELD_EXPIRE_TIME, &expireTime) == HC_SUCCESS) {
86         if (!IsExpireTimeValid(expireTime)) {
87             LOGE("The input expireTime invalid!");
88             return HC_ERR_INVALID_PARAMS;
89         }
90         if (AddIntToJson(jsonParams, FIELD_EXPIRE_TIME, expireTime) != HC_SUCCESS) {
91             LOGE("Failed to add expireTime to jsonParams!");
92             return HC_ERR_JSON_ADD;
93         }
94     }
95     return HC_SUCCESS;
96 }
97 
CombineInfoWhenInvite(const CJson * returnData,CJson * jsonParams)98 static int32_t CombineInfoWhenInvite(const CJson *returnData, CJson *jsonParams)
99 {
100     int32_t result;
101     if (((result = AddPinCode(returnData, jsonParams)) != HC_SUCCESS) ||
102         ((result = AddAuthIdIfExist(returnData, jsonParams)) != HC_SUCCESS) ||
103         ((result = AddUserTypeIfExistAndValid(returnData, jsonParams)) != HC_SUCCESS) ||
104         ((result = AddGroupVisibilityIfExistAndValid(returnData, jsonParams)) != HC_SUCCESS) ||
105         ((result = AddExpireTimeIfExistAndValid(returnData, jsonParams)) != HC_SUCCESS)) {
106         return result;
107     }
108     return HC_SUCCESS;
109 }
110 
AddGroupErrorInfo(int32_t errorCode,const CompatibleBindSubSession * session,CJson * errorData)111 static int32_t AddGroupErrorInfo(int32_t errorCode, const CompatibleBindSubSession *session,
112     CJson *errorData)
113 {
114     if (AddIntToJson(errorData, FIELD_GROUP_ERROR_MSG, errorCode) != HC_SUCCESS) {
115         LOGE("Failed to add errorCode to errorData!");
116         return HC_ERR_JSON_ADD;
117     }
118     if (AddStringToJson(errorData, FIELD_APP_ID, session->base.appId) != HC_SUCCESS) {
119         LOGE("Failed to add appId to errorData!");
120         return HC_ERR_JSON_ADD;
121     }
122     if (AddInt64StringToJson(errorData, FIELD_REQUEST_ID, session->reqId) != HC_SUCCESS) {
123         LOGE("Failed to add requestId to errorData!");
124         return HC_ERR_JSON_ADD;
125     }
126     return HC_SUCCESS;
127 }
128 
GenerateGroupErrorMsg(int32_t errorCode,int64_t requestId,const CJson * jsonParams,CJson ** errorData)129 static int32_t GenerateGroupErrorMsg(int32_t errorCode, int64_t requestId, const CJson *jsonParams, CJson **errorData)
130 {
131     const char *appId = GetStringFromJson(jsonParams, FIELD_APP_ID);
132     if (appId == NULL) {
133         LOGE("Failed to get appId from jsonParams!");
134         return HC_ERR_JSON_GET;
135     }
136     *errorData = CreateJson();
137     if (*errorData == NULL) {
138         LOGE("Failed to allocate errorData memory!");
139         return HC_ERR_JSON_CREATE;
140     }
141     if (AddIntToJson(*errorData, FIELD_GROUP_ERROR_MSG, errorCode) != HC_SUCCESS) {
142         LOGE("Failed to add errorCode to errorData!");
143         FreeJson(*errorData);
144         *errorData = NULL;
145         return HC_ERR_JSON_ADD;
146     }
147     if (AddStringToJson(*errorData, FIELD_APP_ID, appId) != HC_SUCCESS) {
148         LOGE("Failed to add appId to errorData!");
149         FreeJson(*errorData);
150         *errorData = NULL;
151         return HC_ERR_JSON_ADD;
152     }
153     if (AddInt64StringToJson(*errorData, FIELD_REQUEST_ID, requestId) != HC_SUCCESS) {
154         LOGE("Failed to add requestId to errorData!");
155         FreeJson(*errorData);
156         *errorData = NULL;
157         return HC_ERR_JSON_ADD;
158     }
159     return HC_SUCCESS;
160 }
161 
CreateAndProcessBindTask(CompatibleBindSubSession * session,const CJson * in,CJson * out,int32_t * status)162 int32_t CreateAndProcessBindTask(CompatibleBindSubSession *session, const CJson *in, CJson *out, int32_t *status)
163 {
164     LOGI("Start to create and process module task! [ModuleType]: %d", session->moduleType);
165     DEV_AUTH_START_TRACE(TRACE_TAG_CREATE_AUTH_TASK);
166     int32_t res = CreateTask(&(session->base.curTaskId), in, out, session->moduleType);
167     DEV_AUTH_FINISH_TRACE();
168     if (res != HC_SUCCESS) {
169         LOGE("Failed to create module task! res: %d", res);
170         return res;
171     }
172     DEV_AUTH_START_TRACE(TRACE_TAG_PROCESS_AUTH_TASK);
173     res = ProcessTask(session->base.curTaskId, in, out, status, session->moduleType);
174     DEV_AUTH_FINISH_TRACE();
175     if (res != HC_SUCCESS) {
176         LOGE("Failed to process module task! res: %d", res);
177         return res;
178     }
179     LOGI("Create and process module task successfully!");
180     return HC_SUCCESS;
181 }
182 
TransmitBindSessionData(const CompatibleBindSubSession * session,const CJson * sendData)183 int32_t TransmitBindSessionData(const CompatibleBindSubSession *session, const CJson *sendData)
184 {
185     char *sendDataStr = PackJsonToString(sendData);
186     if (sendDataStr == NULL) {
187         LOGE("An error occurred when converting json to string!");
188         return HC_ERR_PACKAGE_JSON_TO_STRING_FAIL;
189     }
190     DEV_AUTH_START_TRACE(TRACE_TAG_SEND_DATA);
191     UPDATE_PERFORM_DATA_BY_SELF_INDEX(session->reqId, HcGetCurTimeInMillis());
192     int32_t res = HcSendMsg(session->channelType, session->reqId, session->channelId,
193         session->base.callback, sendDataStr);
194     DEV_AUTH_FINISH_TRACE();
195     FreeJsonString(sendDataStr);
196     if (res != HC_SUCCESS) {
197         LOGE("Failed to send msg to peer device! res: %d", res);
198         return res;
199     }
200     return HC_SUCCESS;
201 }
202 
CombineConfirmData(int operationCode,const CJson * returnData,CJson * jsonParams)203 int32_t CombineConfirmData(int operationCode, const CJson *returnData, CJson *jsonParams)
204 {
205     if (operationCode == MEMBER_JOIN) {
206         return AddPinCode(returnData, jsonParams);
207     } else {
208         return CombineInfoWhenInvite(returnData, jsonParams);
209     }
210 }
211 
InformPeerGroupErrorIfNeeded(bool isNeedInform,int32_t errorCode,const CompatibleBindSubSession * session)212 void InformPeerGroupErrorIfNeeded(bool isNeedInform, int32_t errorCode, const CompatibleBindSubSession *session)
213 {
214     if (!isNeedInform) {
215         return;
216     }
217     CJson *errorData = CreateJson();
218     if (errorData == NULL) {
219         LOGE("Failed to allocate errorData memory!");
220         return;
221     }
222     int32_t res = AddGroupErrorInfo(errorCode, session, errorData);
223     if (res != HC_SUCCESS) {
224         FreeJson(errorData);
225         return;
226     }
227     res = TransmitBindSessionData(session, errorData);
228     FreeJson(errorData);
229     if (res != HC_SUCCESS) {
230         LOGE("Failed to transmit group error to peer!");
231         return;
232     }
233     LOGI("Notify the peer device that an error occurred at the local end successfully!");
234 }
235 
InformPeerProcessError(int64_t requestId,const CJson * jsonParams,const DeviceAuthCallback * callback,int32_t errorCode)236 void InformPeerProcessError(int64_t requestId, const CJson *jsonParams, const DeviceAuthCallback *callback,
237     int32_t errorCode)
238 {
239     int64_t channelId = DEFAULT_CHANNEL_ID;
240     ChannelType channelType = SOFT_BUS;
241     if (GetByteFromJson(jsonParams, FIELD_CHANNEL_ID, (uint8_t *)&channelId, sizeof(int64_t)) != HC_SUCCESS) {
242         channelType = SERVICE_CHANNEL;
243     }
244     CJson *errorData = NULL;
245     int32_t res = GenerateGroupErrorMsg(errorCode, requestId, jsonParams, &errorData);
246     if (res != HC_SUCCESS) {
247         return;
248     }
249     char *errorDataStr = PackJsonToString(errorData);
250     FreeJson(errorData);
251     if (errorDataStr == NULL) {
252         LOGE("An error occurred when converting json to string!");
253         return;
254     }
255     (void)HcSendMsg(channelType, requestId, channelId, callback, errorDataStr);
256     FreeJsonString(errorDataStr);
257 }