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 std::shared_ptr<ISoftbusSessionCallback> SoftbusSession::sessionCallback_ = nullptr;
29 constexpr const char* DM_HITRACE_AUTH_TO_OPPEN_SESSION = "DM_HITRACE_AUTH_TO_OPPEN_SESSION";
30 constexpr int32_t MAX_DATA_LEN = 65535;
31 
OnShutdown(int32_t socket, ShutdownReason reason)32 static void OnShutdown(int32_t socket, ShutdownReason reason)
33 {
34     LOGI("[SOFTBUS]OnShutdown socket : %{public}d, reason: %{public}d", socket, (int32_t)reason);
35     SoftbusSession::OnSessionClosed(socket);
36 }
37 
OnBytes(int32_t socket, const void *data, uint32_t dataLen)38 static void OnBytes(int32_t socket, const void *data, uint32_t dataLen)
39 {
40     LOGI("[SOFTBUS]OnBytes socket : %{public}d", socket);
41     SoftbusSession::OnBytesReceived(socket, data, dataLen);
42 }
43 
OnQos(int32_t socket, QoSEvent eventId, const QosTV *qos, uint32_t qosCount)44 static void OnQos(int32_t socket, QoSEvent eventId, const QosTV *qos, uint32_t qosCount)
45 {
46     LOGI("[SOFTBUS]OnQos, socket: %{public}d, QoSEvent: %{public}d, qosCount: %{public}u", socket, (int32_t)eventId,
47         qosCount);
48     if (qosCount > QOS_TYPE_BUTT) {
49         LOGE("OnQos invalid qosCount");
50         return;
51     }
52     for (uint32_t idx = 0; idx < qosCount; idx++) {
53         LOGI("QosTV: type: %{public}d, value: %{public}d", (int32_t)qos[idx].qos, qos[idx].value);
54     }
55 }
56 
SoftbusSession()57 SoftbusSession::SoftbusSession()
58 {
59     LOGD("SoftbusSession constructor.");
60     if (memset_s(&iSocketListener_, sizeof(ISocketListener), 0, sizeof(ISocketListener)) != DM_OK) {
61         LOGE("SoftbusSession::SoftbusSession memset_s failed.");
62     }
63 
64     iSocketListener_.OnShutdown = OnShutdown;
65     iSocketListener_.OnBytes = OnBytes;
66     iSocketListener_.OnQos = OnQos;
67     iSocketListener_.OnFile = nullptr;
68     iSocketListener_.OnMessage = nullptr;
69     iSocketListener_.OnBind = nullptr;
70     iSocketListener_.OnStream = nullptr;
71     iSocketListener_.OnError = nullptr;
72     iSocketListener_.OnNegotiate = nullptr;
73 }
74 
~SoftbusSession()75 SoftbusSession::~SoftbusSession()
76 {
77     LOGD("SoftbusSession destructor.");
78 }
79 
RegisterSessionCallback(std::shared_ptr<ISoftbusSessionCallback> callback)80 int32_t SoftbusSession::RegisterSessionCallback(std::shared_ptr<ISoftbusSessionCallback> callback)
81 {
82     sessionCallback_ = callback;
83     return DM_OK;
84 }
85 
UnRegisterSessionCallback()86 int32_t SoftbusSession::UnRegisterSessionCallback()
87 {
88     sessionCallback_ = nullptr;
89     return DM_OK;
90 }
91 
OpenAuthSession(const std::string &deviceId)92 int32_t SoftbusSession::OpenAuthSession(const std::string &deviceId)
93 {
94     DmTraceStart(std::string(DM_HITRACE_AUTH_TO_OPPEN_SESSION));
95     int32_t sessionId = -1;
96     std::string connectAddr;
97     ConnectionAddr *addrInfo = SoftbusConnector::GetConnectAddr(deviceId, connectAddr);
98     if (addrInfo == nullptr) {
99         LOGE("[SOFTBUS]addrInfo is nullptr. sessionId: %{public}d.", sessionId);
100         return sessionId;
101     }
102     sessionId = ::OpenAuthSession(DM_SESSION_NAME, addrInfo, 1, nullptr);
103     if (sessionId < 0) {
104         LOGE("[SOFTBUS]open session error, sessionId: %{public}d.", sessionId);
105         return sessionId;
106     }
107     DmTraceEnd();
108     LOGI("OpenAuthSession success. sessionId: %{public}d.", sessionId);
109     return sessionId;
110 }
111 
CloseAuthSession(int32_t sessionId)112 int32_t SoftbusSession::CloseAuthSession(int32_t sessionId)
113 {
114     LOGI("CloseAuthSession.");
115     ::CloseSession(sessionId);
116     return DM_OK;
117 }
118 
GetPeerDeviceId(int32_t sessionId, std::string &peerDevId)119 int32_t SoftbusSession::GetPeerDeviceId(int32_t sessionId, std::string &peerDevId)
120 {
121     char peerDeviceId[DEVICE_UUID_LENGTH] = {0};
122     int32_t ret = ::GetPeerDeviceId(sessionId, &peerDeviceId[0], DEVICE_UUID_LENGTH);
123     if (ret == DM_OK) {
124         peerDevId = peerDeviceId;
125         LOGI("[SOFTBUS]GetPeerDeviceId success for session: %{public}d, peerDeviceId: %{public}s.", sessionId,
126             GetAnonyString(peerDevId).c_str());
127         return DM_OK;
128     }
129     LOGE("[SOFTBUS]GetPeerDeviceId failed for session: %{public}d, ret: %{public}d.", sessionId, ret);
130     peerDevId = "";
131     return ret;
132 }
133 
SendData(int32_t sessionId, std::string &message)134 int32_t SoftbusSession::SendData(int32_t sessionId, std::string &message)
135 {
136     nlohmann::json jsonObject = nlohmann::json::parse(message, nullptr, false);
137     if (jsonObject.is_discarded()) {
138         LOGE("extrasJson error, message: %{public}s.", GetAnonyString(message).c_str());
139         return ERR_DM_FAILED;
140     }
141     if (!IsInt32(jsonObject, TAG_MSG_TYPE)) {
142         LOGE("SoftbusSession::SendData err json string.");
143         return ERR_DM_FAILED;
144     }
145     int32_t msgType = jsonObject[TAG_MSG_TYPE].get<int32_t>();
146     LOGI("start, msgType: %{public}d.", msgType);
147     if (sessionCallback_->GetIsCryptoSupport()) {
148         LOGI("SendData Start encryption.");
149     }
150     int32_t ret = SendBytes(sessionId, message.c_str(), strlen(message.c_str()));
151     if (ret != DM_OK) {
152         LOGE("[SOFTBUS]SendBytes failed.");
153         return ret;
154     }
155     return DM_OK;
156 }
157 
SendHeartbeatData(int32_t sessionId, std::string &message)158 int32_t SoftbusSession::SendHeartbeatData(int32_t sessionId, std::string &message)
159 {
160     int32_t ret = SendBytes(sessionId, message.c_str(), strlen(message.c_str()));
161     if (ret != DM_OK) {
162         LOGE("[SOFTBUS]SendHeartbeatData failed.");
163         return ret;
164     }
165     return DM_OK;
166 }
167 
OnSessionOpened(int sessionId, int result)168 int SoftbusSession::OnSessionOpened(int sessionId, int result)
169 {
170     int32_t sessionSide = GetSessionSide(sessionId);
171     sessionCallback_->OnSessionOpened(sessionId, sessionSide, result);
172     LOGD("OnSessionOpened, success, sessionId: %{public}d.", sessionId);
173     return DM_OK;
174 }
175 
OnSessionClosed(int sessionId)176 void SoftbusSession::OnSessionClosed(int sessionId)
177 {
178     LOGD("OnSessionClosed, sessionId: %{public}d.", sessionId);
179 }
180 
OnBytesReceived(int sessionId, const void *data, unsigned int dataLen)181 void SoftbusSession::OnBytesReceived(int sessionId, const void *data, unsigned int dataLen)
182 {
183     if (sessionId < 0 || data == nullptr || dataLen <= 0 || dataLen > MAX_DATA_LEN) {
184         LOGI("[SOFTBUS]fail to receive data from softbus with sessionId: %{public}d, dataLen: %{public}d.", sessionId,
185             dataLen);
186         return;
187     }
188     LOGI("start, sessionId: %{public}d, dataLen: %{public}d.", sessionId, dataLen);
189     if (sessionCallback_->GetIsCryptoSupport()) {
190         LOGI("Start decryption.");
191     }
192     std::string message = std::string(reinterpret_cast<const char *>(data), dataLen);
193     nlohmann::json jsonObject = nlohmann::json::parse(message, nullptr, false);
194     if (jsonObject.is_discarded()) {
195         LOGE("DecodeRequestAuth jsonStr error");
196         return;
197     }
198     if (!IsInt32(jsonObject, TAG_MSG_TYPE)) {
199         LOGE("err json string, first time");
200         return;
201     }
202     if (jsonObject[TAG_MSG_TYPE].get<int32_t>() == AUTH_DEVICE_REQ_NEGOTIATE ||
203         jsonObject[TAG_MSG_TYPE].get<int32_t>() == AUTH_DEVICE_RESP_NEGOTIATE) {
204         sessionCallback_->OnAuthDeviceDataReceived(sessionId, message);
205     } else {
206         sessionCallback_->OnDataReceived(sessionId, message);
207     }
208     LOGI("completed.");
209 }
210 } // namespace DistributedHardware
211 } // namespace OHOS
212