• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "network/softbus/softbus_agent.h"
17 
18 #include <sstream>
19 
20 #include "device_manager.h"
21 #include "dfs_daemon_event_dfx.h"
22 #include "dfs_error.h"
23 #include "dfsu_exception.h"
24 #include "dm_device_info.h"
25 #include "ipc_skeleton.h"
26 #include "ipc/i_daemon.h"
27 #include "network/softbus/softbus_session_dispatcher.h"
28 #include "network/softbus/softbus_session_name.h"
29 #include "network/softbus/softbus_session.h"
30 #include "softbus_error_code.h"
31 #include "utils_directory.h"
32 #include "utils_log.h"
33 
34 namespace OHOS {
35 namespace Storage {
36 namespace DistributedFile {
37 namespace {
38     constexpr int MAX_RETRY_COUNT = 7;
39 }
40 using namespace std;
41 const int32_t DFS_QOS_TYPE_MIN_BW = 90 * 1024 * 1024;
42 const int32_t DFS_QOS_TYPE_MAX_LATENCY = 10000;
43 const int32_t DFS_QOS_TYPE_MIN_LATENCY = 2000;
44 #ifdef SUPPORT_SAME_ACCOUNT
45 const uint32_t MAX_ONLINE_DEVICE_SIZE = 10000;
46 #endif
SoftbusAgent(weak_ptr<MountPoint> mountPoint)47 SoftbusAgent::SoftbusAgent(weak_ptr<MountPoint> mountPoint) : NetworkAgentTemplate(mountPoint)
48 {
49     auto spt = mountPoint.lock();
50     if (spt == nullptr) {
51         LOGE("mountPoint is not exist! bad weak_ptr");
52         sessionName_ = "";
53         return;
54     }
55 
56     string path = spt->GetMountArgument().GetFullDst();
57     SoftbusSessionName sessionName(path);
58     sessionName_ = sessionName.ToString();
59 }
60 
IsSameAccount(const std::string & networkId)61 bool SoftbusAgent::IsSameAccount(const std::string &networkId)
62 {
63 #ifdef SUPPORT_SAME_ACCOUNT
64     std::vector<DistributedHardware::DmDeviceInfo> deviceList;
65     DistributedHardware::DeviceManager::GetInstance().GetTrustedDeviceList(IDaemon::SERVICE_NAME, "", deviceList);
66     if (deviceList.size() == 0 || deviceList.size() > MAX_ONLINE_DEVICE_SIZE) {
67         LOGE("trust device list size is invalid, size=%zu", deviceList.size());
68         return false;
69     }
70     for (const auto &deviceInfo : deviceList) {
71         if (std::string(deviceInfo.networkId) == networkId) {
72             return (deviceInfo.authForm == DistributedHardware::DmAuthForm::IDENTICAL_ACCOUNT);
73         }
74     }
75     return false;
76 #else
77     return true;
78 #endif
79 }
80 
JudgeNetworkTypeIsWifi(const DeviceInfo & info)81 int32_t SoftbusAgent::JudgeNetworkTypeIsWifi(const DeviceInfo &info)
82 {
83     int32_t networkType;
84     auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
85     int errCode = deviceManager.GetNetworkTypeByNetworkId(IDaemon::SERVICE_NAME, info.GetCid(), networkType);
86     if (errCode) {
87         LOGE("failed to get network type by network id errCode = %{public}d", errCode);
88         return FileManagement::ERR_BAD_VALUE;
89     }
90     if (!(static_cast<uint32_t>(networkType) & (1 << DistributedHardware::BIT_NETWORK_TYPE_WIFI))) {
91         LOGI("not wifi network networkType = %{public}d == %{public}d", networkType,
92              1 << DistributedHardware::BIT_NETWORK_TYPE_WIFI);
93         return FileManagement::ERR_BAD_VALUE;
94     }
95     return FileManagement::ERR_OK;
96 }
97 
JoinDomain()98 void SoftbusAgent::JoinDomain()
99 {
100     LOGI("JoinDomain Enter.");
101     ISocketListener sessionListener = {
102         .OnBind = SoftbusSessionDispatcher::OnSessionOpened,
103         .OnShutdown = SoftbusSessionDispatcher::OnSessionClosed,
104         .OnBytes = nullptr,
105         .OnMessage = nullptr,
106         .OnStream = nullptr,
107     };
108 
109     SoftbusSessionDispatcher::RegisterSessionListener(sessionName_, shared_from_this());
110     SocketInfo serverInfo = {
111         .name = const_cast<char*>(sessionName_.c_str()),
112         .pkgName = const_cast<char*>(IDaemon::SERVICE_NAME.c_str()),
113         .dataType = DATA_TYPE_BYTES,
114     };
115     int32_t socketId = Socket(serverInfo);
116     if (socketId < 0) {
117         LOGE("Create Socket fail socketId, socketId = %{public}d", socketId);
118         return;
119     }
120     QosTV qos[] = {
121         {.qos = QOS_TYPE_MIN_BW,        .value = DFS_QOS_TYPE_MIN_BW},
122         {.qos = QOS_TYPE_MAX_LATENCY,        .value = DFS_QOS_TYPE_MAX_LATENCY},
123         {.qos = QOS_TYPE_MIN_LATENCY,        .value = DFS_QOS_TYPE_MIN_LATENCY},
124     };
125 
126     int32_t ret = Listen(socketId, qos, sizeof(qos) / sizeof(qos[0]), &sessionListener);
127     if (ret != FileManagement::E_OK) {
128         Shutdown(socketId);
129         stringstream ss;
130         ss << "Failed to CreateSessionServer, errno:" << ret;
131         LOGE("%{public}s, sessionName:%{public}s", ss.str().c_str(), sessionName_.c_str());
132         throw runtime_error(ss.str());
133     }
134     {
135         std::lock_guard<std::mutex> lock(serverIdMapMutex_);
136         serverIdMap_.insert(std::make_pair(sessionName_, socketId));
137     }
138     LOGI("Succeed to JoinDomain, busName:%{public}s", sessionName_.c_str());
139 }
140 
QuitDomain()141 void SoftbusAgent::QuitDomain()
142 {
143     std::lock_guard<std::mutex> lock(serverIdMapMutex_);
144     if (!serverIdMap_.empty()) {
145         for (auto it = serverIdMap_.begin(); it != serverIdMap_.end(); it++) {
146             if ((it->first).find(sessionName_) != std::string::npos) {
147                 int32_t serverId = serverIdMap_[sessionName_];
148                 Shutdown(serverId);
149                 LOGI("RemoveSessionServer success.");
150             }
151         }
152     }
153     SoftbusSessionDispatcher::UnregisterSessionListener(sessionName_.c_str());
154     LOGI("Succeed to QuitDomain, busName:%{public}s", sessionName_.c_str());
155 }
156 
StopTopHalf()157 void SoftbusAgent::StopTopHalf()
158 {
159     QuitDomain();
160 }
161 
StopBottomHalf()162 void SoftbusAgent::StopBottomHalf() {}
163 
OpenSession(const DeviceInfo & info,const uint8_t & linkType)164 int32_t SoftbusAgent::OpenSession(const DeviceInfo &info, const uint8_t &linkType)
165 {
166     LOGI("Start to OpenSession, cid:%{public}s, linkType:%{public}d",
167         Utils::GetAnonyString(info.GetCid()).c_str(), linkType);
168     if (!IsSameAccount(info.GetCid())) {
169         LOGI("The source and sink device is not same account, not support.");
170         return FileManagement::E_INVAL_ARG;
171     }
172     ISocketListener sessionListener = {
173         .OnBind = SoftbusSessionDispatcher::OnSessionOpened,
174         .OnShutdown = SoftbusSessionDispatcher::OnSessionClosed,
175         .OnBytes = nullptr,
176         .OnMessage = nullptr,
177         .OnStream = nullptr,
178     };
179     QosTV qos[] = {
180         {.qos = QOS_TYPE_MIN_BW,        .value = DFS_QOS_TYPE_MIN_BW},
181         {.qos = QOS_TYPE_MAX_LATENCY,        .value = DFS_QOS_TYPE_MAX_LATENCY},
182         {.qos = QOS_TYPE_MIN_LATENCY,        .value = DFS_QOS_TYPE_MIN_LATENCY},
183     };
184     SocketInfo clientInfo = {
185         .name = const_cast<char*>((sessionName_.c_str())),
186         .peerName = const_cast<char*>(sessionName_.c_str()),
187         .peerNetworkId = const_cast<char*>(info.GetCid().c_str()),
188         .pkgName = const_cast<char*>(IDaemon::SERVICE_NAME.c_str()),
189         .dataType = DATA_TYPE_BYTES,
190     };
191     int32_t socketId = Socket(clientInfo);
192     if (socketId < FileManagement::E_OK) {
193         LOGE("Create OpenSoftbusChannel Socket error");
194         return FileManagement::E_CONTEXT;
195     }
196     int32_t ret = Bind(socketId, qos, sizeof(qos) / sizeof(qos[0]), &sessionListener);
197     if (ret != FileManagement::E_OK) {
198         LOGE("Bind SocketClient error");
199         RADAR_REPORT(RadarReporter::DFX_SET_DFS, RadarReporter::DFX_BUILD__LINK, RadarReporter::DFX_FAILED,
200             RadarReporter::BIZ_STATE, RadarReporter::DFX_END, RadarReporter::ERROR_CODE,
201             RadarReporter::BIND_SOCKET_ERROR, RadarReporter::PACKAGE_NAME, RadarReporter::dSoftBus + to_string(ret));
202         Shutdown(socketId);
203         return FileManagement::E_CONTEXT;
204     }
205     OccupySession(socketId, linkType);
206     PeerSocketInfo peerSocketInfo = {
207         .name = const_cast<char*>(sessionName_.c_str()),
208         .networkId = const_cast<char*>(info.GetCid().c_str()),
209     };
210     SoftbusSessionDispatcher::OnSessionOpened(socketId, peerSocketInfo);
211     LOGI("Success to OpenSession, socketId:%{public}d, linkType:%{public}d, cid:%{public}s",
212         socketId, linkType, Utils::GetAnonyString(info.GetCid()).c_str());
213     return FileManagement::E_OK;
214 }
215 
OpenApSession(const DeviceInfo & info,const uint8_t & linkType)216 void SoftbusAgent::OpenApSession(const DeviceInfo &info, const uint8_t &linkType)
217 {
218     LOGI("Start to OpenApSession, cid:%{public}s, linkType:%{public}d",
219         Utils::GetAnonyString(info.GetCid()).c_str(), linkType);
220     if (!IsSameAccount(info.GetCid())) {
221         LOGI("The source and sink device is not same account, not support.");
222         return;
223     }
224     if (JudgeNetworkTypeIsWifi(info)) {
225         LOGI("networktype is not wifi");
226         return;
227     }
228     ISocketListener sessionListener = {
229         .OnBind = SoftbusSessionDispatcher::OnSessionOpened,
230         .OnShutdown = SoftbusSessionDispatcher::OnSessionClosed,
231         .OnBytes = nullptr,
232         .OnMessage = nullptr,
233         .OnStream = nullptr,
234     };
235     SocketInfo clientInfo = {
236         .name = const_cast<char*>((sessionName_.c_str())),
237         .peerName = const_cast<char*>(sessionName_.c_str()),
238         .peerNetworkId = const_cast<char*>(info.GetCid().c_str()),
239         .pkgName = const_cast<char*>(IDaemon::SERVICE_NAME.c_str()),
240         .dataType = DATA_TYPE_BYTES,
241     };
242     int32_t socketId = Socket(clientInfo);
243     if (socketId < FileManagement::E_OK) {
244         LOGE("Create OpenApSoftbusChannel Socket error");
245         return;
246     }
247     int32_t ret = DfsBind(socketId, &sessionListener);
248     if (ret == SOFTBUS_TRANS_SOCKET_IN_USE) {
249         LOGI("Bind Socket in use cid:%{public}s", Utils::GetAnonyString(info.GetCid()).c_str());
250         return;
251     }
252     if (ret != FileManagement::E_OK) {
253         LOGE("Bind SocketClient error cid:%{public}s", Utils::GetAnonyString(info.GetCid()).c_str());
254         Shutdown(socketId);
255         return;
256     }
257     OccupySession(socketId, linkType);
258     PeerSocketInfo peerSocketInfo = {
259         .name = const_cast<char*>(sessionName_.c_str()),
260         .networkId = const_cast<char*>(info.GetCid().c_str()),
261     };
262     SoftbusSessionDispatcher::OnSessionOpened(socketId, peerSocketInfo);
263     LOGI("Success to OpenApSession, socketId:%{public}d, linkType:%{public}d, cid:%{public}s",
264         socketId, linkType, Utils::GetAnonyString(info.GetCid()).c_str());
265 }
266 
CloseSession(shared_ptr<BaseSession> session)267 void SoftbusAgent::CloseSession(shared_ptr<BaseSession> session)
268 {
269     if (session == nullptr) {
270         LOGE("Failed to close session, error:invalid session");
271         return;
272     }
273     session->Release();
274 }
275 
IsContinueRetry(const string & cid)276 bool SoftbusAgent::IsContinueRetry(const string &cid)
277 {
278     auto retriedTimesMap = OpenSessionRetriedTimesMap_.find(cid);
279     if (retriedTimesMap != OpenSessionRetriedTimesMap_.end()) {
280         if (retriedTimesMap->second >= MAX_RETRY_COUNT) {
281             return false;
282         }
283     } else {
284         OpenSessionRetriedTimesMap_[cid] = 0;
285     }
286     OpenSessionRetriedTimesMap_[cid]++;
287     return true;
288 }
289 
OnSessionOpened(const int32_t sessionId,PeerSocketInfo info)290 void SoftbusAgent::OnSessionOpened(const int32_t sessionId, PeerSocketInfo info)
291 {
292     LOGI("OnSessionOpened sessionId = %{public}d", sessionId);
293     std::string peerDeviceId = info.networkId;
294     auto session = make_shared<SoftbusSession>(sessionId, peerDeviceId);
295     auto cid = session->GetCid();
296 
297     DeviceInfo deviceInfo;
298     deviceInfo.SetCid(cid);
299     auto retriedTimesMap = OpenSessionRetriedTimesMap_.find(cid);
300     if (retriedTimesMap != OpenSessionRetriedTimesMap_.end()) {
301         OpenSessionRetriedTimesMap_.erase(cid);
302     }
303     session->DisableSessionListener();
304     if (FindSession(sessionId)) {
305         std::string client = "Client";
306         AcceptSession(session, client);
307     } else {
308         std::string client = "Server";
309         AcceptSession(session, client);
310     }
311 
312     if (!FindSession(sessionId)) {
313         OccupySession(sessionId, 0);
314     }
315 }
316 
OnSessionClosed(int32_t sessionId,const std::string peerDeviceId)317 void SoftbusAgent::OnSessionClosed(int32_t sessionId, const std::string peerDeviceId)
318 {
319     LOGI("OnSessionClosed Enter.");
320     Shutdown(sessionId);
321 }
322 } // namespace DistributedFile
323 } // namespace Storage
324 } // namespace OHOS
325