1 /*
2 * Copyright (C) 2021-2022 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 "bind_session_client.h"
17 #include "bind_session_common_util.h"
18 #include "callback_manager.h"
19 #include "channel_manager.h"
20 #include "group_operation_common.h"
21 #include "hc_log.h"
22 #include "session_manager.h"
23
GenerateClientModuleParams(BindSession * session,CJson * moduleParams)24 static int32_t GenerateClientModuleParams(BindSession *session, CJson *moduleParams)
25 {
26 if (AddIntToJson(moduleParams, FIELD_OPERATION_CODE,
27 ((session->opCode == MEMBER_DELETE) ? OP_UNBIND : OP_BIND)) != HC_SUCCESS) {
28 LOGE("Failed to add operationCode to moduleParams!");
29 return HC_ERR_JSON_FAIL;
30 }
31 return GenerateBasicModuleParams(true, session, moduleParams);
32 }
33
GetClientModuleReturnData(BindSession * session,CJson * out)34 static int32_t GetClientModuleReturnData(BindSession *session, CJson *out)
35 {
36 CJson *moduleParams = CreateJson();
37 if (moduleParams == NULL) {
38 LOGE("Failed to allocate moduleParams memory!");
39 return HC_ERR_JSON_FAIL;
40 }
41
42 int32_t result = GenerateClientModuleParams(session, moduleParams);
43 if (result != HC_SUCCESS) {
44 LOGE("Failed to generate all params sent to the module!");
45 FreeJson(moduleParams);
46 return result;
47 }
48
49 result = CreateAndProcessModule(session, moduleParams, out);
50 FreeJson(moduleParams);
51 if (result != HC_SUCCESS) {
52 return result;
53 }
54 return HC_SUCCESS;
55 }
56
PrepareData(BindSession * session,CJson ** sendData)57 static int32_t PrepareData(BindSession *session, CJson **sendData)
58 {
59 CJson *out = CreateJson();
60 if (out == NULL) {
61 LOGE("Failed to allocate out memory!");
62 return HC_ERR_JSON_FAIL;
63 }
64 int32_t result = GetClientModuleReturnData(session, out);
65 if (result != HC_SUCCESS) {
66 FreeJson(out);
67 return result;
68 }
69
70 *sendData = DetachItemFromJson(out, FIELD_SEND_TO_PEER);
71 FreeJson(out);
72 if (*sendData == NULL) {
73 LOGE("Failed to get sendToPeer from out!");
74 return HC_ERR_JSON_GET;
75 }
76
77 result = AddInfoToSendData(false, session, *sendData);
78 if (result != HC_SUCCESS) {
79 LOGE("Failed to add information to sendData!");
80 FreeJson(*sendData);
81 *sendData = NULL;
82 return result;
83 }
84 return HC_SUCCESS;
85 }
86
PrepareAndSendData(BindSession * session)87 static int32_t PrepareAndSendData(BindSession *session)
88 {
89 CJson *sendData = NULL;
90 int32_t result = PrepareData(session, &sendData);
91 if (result != HC_SUCCESS) {
92 return result;
93 }
94
95 result = SendBindSessionData(session, sendData);
96 FreeJson(sendData);
97 return result;
98 }
99
DoubleCheckChannelId(int64_t channelId,int64_t oldChannelId)100 static int32_t DoubleCheckChannelId(int64_t channelId, int64_t oldChannelId)
101 {
102 if (oldChannelId != channelId) {
103 /* If the two channelIds are different, the soft bus channel must be used. */
104 LOGE("The channelId returned by the soft bus are inconsistent, causing a channel error!");
105 return HC_ERR_CHANNEL_NOT_EXIST;
106 }
107 return HC_SUCCESS;
108 }
109
OnBindChannelOpened(Session * session,int64_t channelId,int64_t requestId)110 static void OnBindChannelOpened(Session *session, int64_t channelId, int64_t requestId)
111 {
112 if (session == NULL) {
113 LOGE("The input session is NULL!");
114 return;
115 }
116
117 BindSession *realSession = (BindSession *)session;
118 /* Double check channelId. If the two channelIds are different, the channel fails to be established. */
119 int32_t result = DoubleCheckChannelId(channelId, realSession->channelId);
120 if (result != HC_SUCCESS) {
121 ProcessErrorCallback(requestId, realSession->opCode, result, NULL, realSession->base.callback);
122 DestroySession(requestId);
123 return;
124 }
125
126 result = PrepareAndSendData(realSession);
127 if (result != HC_SUCCESS) {
128 LOGI("An error occurs before the client send data to the server. We need to notify the service!");
129 if ((!NeedForceDelete(realSession)) || (ForceUnbindDevice(realSession) != HC_SUCCESS)) {
130 ProcessErrorCallback(requestId, realSession->opCode, result, NULL, realSession->base.callback);
131 }
132 CloseChannel(realSession->channelType, realSession->channelId);
133 DestroySession(requestId);
134 }
135 }
136
PrepareClient(const CJson * jsonParams,BindSession * session)137 static int32_t PrepareClient(const CJson *jsonParams, BindSession *session)
138 {
139 int32_t result = GenerateBindParams(session->osAccountId, CLIENT, jsonParams, session);
140 if (result != HC_SUCCESS) {
141 return result;
142 }
143 return OpenChannel(session->channelType, jsonParams, session->reqId, &session->channelId);
144 }
145
CreateClientBindSession(CJson * jsonParams,const DeviceAuthCallback * callback)146 Session *CreateClientBindSession(CJson *jsonParams, const DeviceAuthCallback *callback)
147 {
148 int32_t opCode = MEMBER_INVITE;
149 if (GetIntFromJson(jsonParams, FIELD_OPERATION_CODE, &opCode) != HC_SUCCESS) {
150 LOGE("Failed to get opCode from json!");
151 return NULL;
152 }
153 /*
154 * If service want to join the peer group,
155 * the identity key pair of the corresponding group needs to be generated here.
156 */
157 int32_t result;
158 if (NeedCreateGroup(CLIENT, opCode)) {
159 const char *groupId = GetStringFromJson(jsonParams, FIELD_GROUP_ID);
160 if (groupId == NULL) {
161 LOGE("Failed to get groupId from jsonParams!");
162 return NULL;
163 }
164 result = ProcessKeyPair(CREATE_KEY_PAIR, jsonParams, groupId);
165 if (result != HC_SUCCESS) {
166 return NULL;
167 }
168 }
169
170 BindSession *session = CreateBaseBindSession(TYPE_CLIENT_BIND_SESSION, opCode,
171 jsonParams, callback, ProcessBindSession);
172 if (session == NULL) {
173 return NULL;
174 }
175 InitClientChannel(callback, jsonParams, session);
176 /* The client bind session needs to receive a message indicating that the channel is open. */
177 session->onChannelOpened = OnBindChannelOpened;
178
179 result = PrepareClient(jsonParams, session);
180 if (result != HC_SUCCESS) {
181 ProcessErrorCallback(session->reqId, session->opCode, result, NULL, session->base.callback);
182 DestroyBindSession((Session *)session);
183 return NULL;
184 }
185 return (Session *)session;
186 }
187