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