1 /*
2 * Copyright (c) 2022-2024 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 "softbus_session.h"
17
18 #include "dm_anonymous.h"
19 #include "dm_constants.h"
20 #include "dm_dfx_constants.h"
21 #include "dm_hitrace.h"
22 #include "dm_log.h"
23 #include "nlohmann/json.hpp"
24 #include "softbus_connector.h"
25
26 namespace OHOS {
27 namespace DistributedHardware {
28 namespace {
29 static QosTV g_qosInfo[] = {
30 { .qos = QOS_TYPE_MIN_BW, .value = 64 * 1024 },
31 { .qos = QOS_TYPE_MAX_LATENCY, .value = 10000 },
32 { .qos = QOS_TYPE_MIN_LATENCY, .value = 2500 },
33 };
34 static uint32_t g_qosTVParamIndex = static_cast<uint32_t>(sizeof(g_qosInfo) / sizeof(g_qosInfo[0]));
35 }
36
37 std::shared_ptr<ISoftbusSessionCallback> SoftbusSession::sessionCallback_ = nullptr;
38 constexpr const char* DM_HITRACE_AUTH_TO_OPPEN_SESSION = "DM_HITRACE_AUTH_TO_OPPEN_SESSION";
39 constexpr int32_t INTERCEPT_STRING_LENGTH = 20;
40
OnShutdown(int32_t socket,ShutdownReason reason)41 static void OnShutdown(int32_t socket, ShutdownReason reason)
42 {
43 LOGI("[SOFTBUS]OnShutdown socket : %{public}d, reason: %{public}d", socket, (int32_t)reason);
44 SoftbusSession::OnSessionClosed(socket);
45 }
46
OnBytes(int32_t socket,const void * data,uint32_t dataLen)47 static void OnBytes(int32_t socket, const void *data, uint32_t dataLen)
48 {
49 LOGI("[SOFTBUS]OnBytes socket : %{public}d", socket);
50 SoftbusSession::OnBytesReceived(socket, data, dataLen);
51 }
52
OnQos(int32_t socket,QoSEvent eventId,const QosTV * qos,uint32_t qosCount)53 static void OnQos(int32_t socket, QoSEvent eventId, const QosTV *qos, uint32_t qosCount)
54 {
55 LOGI("[SOFTBUS]OnQos, socket: %{public}d, QoSEvent: %{public}d, qosCount: %{public}u", socket, (int32_t)eventId,
56 qosCount);
57 for (uint32_t idx = 0; idx < qosCount; idx++) {
58 LOGI("QosTV: type: %{public}d, value: %{public}d", (int32_t)qos[idx].qos, qos[idx].value);
59 }
60 }
61
SoftbusSession()62 SoftbusSession::SoftbusSession()
63 {
64 LOGD("SoftbusSession constructor.");
65 (void)memset_s(&iSocketListener_, sizeof(ISocketListener), 0, sizeof(ISocketListener));
66 iSocketListener_.OnShutdown = OnShutdown;
67 iSocketListener_.OnBytes = OnBytes;
68 iSocketListener_.OnQos = OnQos;
69 iSocketListener_.OnFile = nullptr;
70 iSocketListener_.OnMessage = nullptr;
71 iSocketListener_.OnBind = nullptr;
72 iSocketListener_.OnStream = nullptr;
73 iSocketListener_.OnError = nullptr;
74 iSocketListener_.OnNegotiate = nullptr;
75 }
76
~SoftbusSession()77 SoftbusSession::~SoftbusSession()
78 {
79 LOGD("SoftbusSession destructor.");
80 }
81
RegisterSessionCallback(std::shared_ptr<ISoftbusSessionCallback> callback)82 int32_t SoftbusSession::RegisterSessionCallback(std::shared_ptr<ISoftbusSessionCallback> callback)
83 {
84 sessionCallback_ = callback;
85 return DM_OK;
86 }
87
UnRegisterSessionCallback()88 int32_t SoftbusSession::UnRegisterSessionCallback()
89 {
90 sessionCallback_ = nullptr;
91 return DM_OK;
92 }
93
OpenAuthSession(const std::string & deviceId)94 int32_t SoftbusSession::OpenAuthSession(const std::string &deviceId)
95 {
96 DmTraceStart(std::string(DM_HITRACE_AUTH_TO_OPPEN_SESSION));
97 int32_t sessionId = -1;
98 std::string connectAddr;
99 ConnectionAddr *addrInfo = SoftbusConnector::GetConnectAddr(deviceId, connectAddr);
100 if (addrInfo == nullptr) {
101 LOGE("[SOFTBUS]addrInfo is nullptr. sessionId: %{public}d.", sessionId);
102 return sessionId;
103 }
104 sessionId = ::OpenAuthSession(DM_SESSION_NAME, addrInfo, 1, nullptr);
105 if (sessionId < 0) {
106 LOGE("[SOFTBUS]open session error, sessionId: %{public}d.", sessionId);
107 return sessionId;
108 }
109 DmTraceEnd();
110 LOGI("OpenAuthSession success. sessionId: %{public}d.", sessionId);
111 return sessionId;
112 }
113
CloseAuthSession(int32_t sessionId)114 int32_t SoftbusSession::CloseAuthSession(int32_t sessionId)
115 {
116 LOGI("CloseAuthSession.");
117 ::CloseSession(sessionId);
118 return DM_OK;
119 }
120
CloseUnbindSession(int32_t socket)121 int32_t SoftbusSession::CloseUnbindSession(int32_t socket)
122 {
123 LOGI("CloseUnbindSession.");
124 Shutdown(socket);
125 return DM_OK;
126 }
127
GetPeerDeviceId(int32_t sessionId,std::string & peerDevId)128 int32_t SoftbusSession::GetPeerDeviceId(int32_t sessionId, std::string &peerDevId)
129 {
130 char peerDeviceId[DEVICE_UUID_LENGTH] = {0};
131 int32_t ret = ::GetPeerDeviceId(sessionId, &peerDeviceId[0], DEVICE_UUID_LENGTH);
132 if (ret == DM_OK) {
133 peerDevId = peerDeviceId;
134 LOGI("[SOFTBUS]GetPeerDeviceId success for session: %{public}d, peerDeviceId: %{public}s.", sessionId,
135 GetAnonyString(peerDevId).c_str());
136 return DM_OK;
137 }
138 LOGE("[SOFTBUS]GetPeerDeviceId failed for session: %{public}d, ret: %{public}d.", sessionId, ret);
139 peerDevId = "";
140 return ret;
141 }
142
SendData(int32_t sessionId,std::string & message)143 int32_t SoftbusSession::SendData(int32_t sessionId, std::string &message)
144 {
145 nlohmann::json jsonObject = nlohmann::json::parse(message, nullptr, false);
146 if (jsonObject.is_discarded()) {
147 LOGE("extrasJson error, message: %{public}s.", GetAnonyString(message).c_str());
148 return ERR_DM_FAILED;
149 }
150 if (!IsInt32(jsonObject, TAG_MSG_TYPE)) {
151 LOGE("SoftbusSession::SendData err json string.");
152 return ERR_DM_FAILED;
153 }
154 int32_t msgType = jsonObject[TAG_MSG_TYPE].get<int32_t>();
155 LOGI("start, msgType: %{public}d.", msgType);
156 if (sessionCallback_->GetIsCryptoSupport()) {
157 LOGI("SendData Start encryption.");
158 }
159 int32_t ret = SendBytes(sessionId, message.c_str(), strlen(message.c_str()));
160 if (ret != DM_OK) {
161 LOGE("[SOFTBUS]SendBytes failed.");
162 return ret;
163 }
164 return DM_OK;
165 }
166
SendHeartbeatData(int32_t sessionId,std::string & message)167 int32_t SoftbusSession::SendHeartbeatData(int32_t sessionId, std::string &message)
168 {
169 int32_t ret = SendBytes(sessionId, message.c_str(), strlen(message.c_str()));
170 if (ret != DM_OK) {
171 LOGE("[SOFTBUS]SendHeartbeatData failed.");
172 return ret;
173 }
174 return DM_OK;
175 }
176
OnSessionOpened(int sessionId,int result)177 int SoftbusSession::OnSessionOpened(int sessionId, int result)
178 {
179 int32_t sessionSide = GetSessionSide(sessionId);
180 sessionCallback_->OnSessionOpened(sessionId, sessionSide, result);
181 LOGD("OnSessionOpened, success, sessionId: %{public}d.", sessionId);
182 return DM_OK;
183 }
184
OnSessionClosed(int sessionId)185 void SoftbusSession::OnSessionClosed(int sessionId)
186 {
187 LOGD("OnSessionClosed, sessionId: %{public}d.", sessionId);
188 }
189
OnBytesReceived(int sessionId,const void * data,unsigned int dataLen)190 void SoftbusSession::OnBytesReceived(int sessionId, const void *data, unsigned int dataLen)
191 {
192 if (sessionId < 0 || data == nullptr || dataLen <= 0) {
193 LOGI("[SOFTBUS]fail to receive data from softbus with sessionId: %{public}d, dataLen: %{public}d.", sessionId,
194 dataLen);
195 return;
196 }
197 LOGI("start, sessionId: %{public}d, dataLen: %{public}d.", sessionId, dataLen);
198 if (sessionCallback_->GetIsCryptoSupport()) {
199 LOGI("Start decryption.");
200 }
201 std::string message = std::string(reinterpret_cast<const char *>(data), dataLen);
202 nlohmann::json jsonObject = nlohmann::json::parse(message, nullptr, false);
203 if (jsonObject.is_discarded()) {
204 LOGE("DecodeRequestAuth jsonStr error");
205 return;
206 }
207 if (!IsInt32(jsonObject, TAG_MSG_TYPE)) {
208 LOGE("err json string, first time");
209 return;
210 }
211 if (jsonObject[TAG_MSG_TYPE].get<int32_t>() == AUTH_DEVICE_REQ_NEGOTIATE ||
212 jsonObject[TAG_MSG_TYPE].get<int32_t>() == AUTH_DEVICE_RESP_NEGOTIATE) {
213 sessionCallback_->OnAuthDeviceDataReceived(sessionId, message);
214 } else {
215 sessionCallback_->OnDataReceived(sessionId, message);
216 }
217 LOGI("completed.");
218 }
219
OnUnbindSessionOpened(int32_t socket,PeerSocketInfo info)220 void SoftbusSession::OnUnbindSessionOpened(int32_t socket, PeerSocketInfo info)
221 {
222 sessionCallback_->OnUnbindSessionOpened(socket, info);
223 LOGI("SoftbusSession::OnUnbindSessionOpened success, socket: %{public}d.", socket);
224 }
225
OpenUnbindSession(const std::string & netWorkId)226 int32_t SoftbusSession::OpenUnbindSession(const std::string &netWorkId)
227 {
228 std::string localSessionName = DM_UNBIND_SESSION_NAME + netWorkId.substr(0, INTERCEPT_STRING_LENGTH);
229 SocketInfo info = {
230 .name = const_cast<char*>(localSessionName.c_str()),
231 .peerName = const_cast<char*>(DM_UNBIND_SESSION_NAME),
232 .peerNetworkId = const_cast<char*>(netWorkId.c_str()),
233 .pkgName = const_cast<char*>(DM_PKG_NAME),
234 .dataType = DATA_TYPE_BYTES
235 };
236
237 int32_t socket = Socket(info);
238 if (socket <= 0) {
239 LOGE("[SOFTBUS]create socket failed, socket: %{public}d", socket);
240 return socket;
241 }
242
243 int32_t ret = Bind(socket, g_qosInfo, g_qosTVParamIndex, &iSocketListener_);
244 if (ret < DM_OK) {
245 LOGE("[SOFTBUS]OpenUnbindSession failed, netWorkId: %{public}s, socket: %{public}d",
246 GetAnonyString(netWorkId).c_str(), socket);
247 sessionCallback_->BindSocketFail();
248 Shutdown(socket);
249 return ret;
250 }
251 LOGI("OpenUnbindSession success. socket: %{public}d.", socket);
252 sessionCallback_->BindSocketSuccess(socket);
253 return socket;
254 }
255 } // namespace DistributedHardware
256 } // namespace OHOS
257