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 const std::string SESSION_NAME = "DistributedFileService/mnt/hmdfs/100/account";
45 #ifdef SUPPORT_SAME_ACCOUNT
46 const uint32_t MAX_ONLINE_DEVICE_SIZE = 10000;
47 #endif
SoftbusAgent(weak_ptr<MountPoint> mountPoint)48 SoftbusAgent::SoftbusAgent(weak_ptr<MountPoint> mountPoint) : NetworkAgentTemplate(mountPoint)
49 {
50 sessionName_ = SESSION_NAME;
51 }
52
IsSameAccount(const std::string & networkId)53 bool SoftbusAgent::IsSameAccount(const std::string &networkId)
54 {
55 #ifdef SUPPORT_SAME_ACCOUNT
56 std::vector<DistributedHardware::DmDeviceInfo> deviceList;
57 DistributedHardware::DeviceManager::GetInstance().GetTrustedDeviceList(IDaemon::SERVICE_NAME, "", deviceList);
58 if (deviceList.size() == 0 || deviceList.size() > MAX_ONLINE_DEVICE_SIZE) {
59 LOGE("trust device list size is invalid, size=%zu", deviceList.size());
60 return false;
61 }
62 for (const auto &deviceInfo : deviceList) {
63 if (std::string(deviceInfo.networkId) == networkId) {
64 return (deviceInfo.authForm == DistributedHardware::DmAuthForm::IDENTICAL_ACCOUNT);
65 }
66 }
67 LOGI("The source and sink device is not same account, not support.");
68 return false;
69 #else
70 return true;
71 #endif
72 }
73
JudgeNetworkTypeIsWifi(const DeviceInfo & info)74 int32_t SoftbusAgent::JudgeNetworkTypeIsWifi(const DeviceInfo &info)
75 {
76 int32_t networkType;
77 auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
78 int errCode = deviceManager.GetNetworkTypeByNetworkId(IDaemon::SERVICE_NAME, info.GetCid(), networkType);
79 if (errCode) {
80 LOGE("failed to get network type by network id errCode = %{public}d", errCode);
81 return FileManagement::ERR_BAD_VALUE;
82 }
83 if (!(static_cast<uint32_t>(networkType) & (1 << DistributedHardware::BIT_NETWORK_TYPE_WIFI))) {
84 LOGI("not wifi network networkType = %{public}d == %{public}d", networkType,
85 1 << DistributedHardware::BIT_NETWORK_TYPE_WIFI);
86 return FileManagement::ERR_BAD_VALUE;
87 }
88 return FileManagement::ERR_OK;
89 }
90
JoinDomain()91 void SoftbusAgent::JoinDomain()
92 {
93 LOGI("JoinDomain Enter.");
94 ISocketListener sessionListener = {
95 .OnBind = SoftbusSessionDispatcher::OnSessionOpened,
96 .OnShutdown = SoftbusSessionDispatcher::OnSessionClosed,
97 .OnBytes = nullptr,
98 .OnMessage = nullptr,
99 .OnStream = nullptr,
100 };
101
102 SoftbusSessionDispatcher::RegisterSessionListener(sessionName_, shared_from_this());
103 SocketInfo serverInfo = {
104 .name = const_cast<char*>(sessionName_.c_str()),
105 .pkgName = const_cast<char*>(IDaemon::SERVICE_NAME.c_str()),
106 .dataType = DATA_TYPE_BYTES,
107 };
108 int32_t socketId = Socket(serverInfo);
109 if (socketId < 0) {
110 LOGE("Create Socket fail socketId, socketId = %{public}d", socketId);
111 return;
112 }
113 QosTV qos[] = {
114 {.qos = QOS_TYPE_MIN_BW, .value = DFS_QOS_TYPE_MIN_BW},
115 {.qos = QOS_TYPE_MAX_LATENCY, .value = DFS_QOS_TYPE_MAX_LATENCY},
116 {.qos = QOS_TYPE_MIN_LATENCY, .value = DFS_QOS_TYPE_MIN_LATENCY},
117 };
118
119 int32_t ret = Listen(socketId, qos, sizeof(qos) / sizeof(qos[0]), &sessionListener);
120 if (ret != FileManagement::E_OK) {
121 Shutdown(socketId);
122 stringstream ss;
123 ss << "Failed to CreateSessionServer, errno:" << ret;
124 LOGE("%{public}s, sessionName:%{public}s", ss.str().c_str(), sessionName_.c_str());
125 throw runtime_error(ss.str());
126 }
127 {
128 std::lock_guard<std::mutex> lock(serverIdMapMutex_);
129 serverIdMap_.insert(std::make_pair(sessionName_, socketId));
130 }
131 LOGI("Succeed to JoinDomain, busName:%{public}s", sessionName_.c_str());
132 }
133
QuitDomain()134 void SoftbusAgent::QuitDomain()
135 {
136 std::lock_guard<std::mutex> lock(serverIdMapMutex_);
137 if (!serverIdMap_.empty()) {
138 for (auto it = serverIdMap_.begin(); it != serverIdMap_.end(); it++) {
139 if ((it->first).find(sessionName_) != std::string::npos) {
140 int32_t serverId = serverIdMap_[sessionName_];
141 Shutdown(serverId);
142 LOGI("RemoveSessionServer success.");
143 }
144 }
145 }
146 SoftbusSessionDispatcher::UnregisterSessionListener(sessionName_.c_str());
147 LOGI("Succeed to QuitDomain, busName:%{public}s", sessionName_.c_str());
148 }
149
StopTopHalf()150 void SoftbusAgent::StopTopHalf()
151 {
152 QuitDomain();
153 }
154
StopBottomHalf()155 void SoftbusAgent::StopBottomHalf() {}
156
OpenSession(const DeviceInfo & info,const uint8_t & linkType)157 int32_t SoftbusAgent::OpenSession(const DeviceInfo &info, const uint8_t &linkType)
158 {
159 LOGI("Start to OpenSession, cid:%{public}s", Utils::GetAnonyString(info.GetCid()).c_str());
160 if (!IsSameAccount(info.GetCid())) {
161 return FileManagement::E_INVAL_ARG;
162 }
163 ISocketListener sessionListener = {
164 .OnBind = SoftbusSessionDispatcher::OnSessionOpened,
165 .OnShutdown = SoftbusSessionDispatcher::OnSessionClosed,
166 .OnBytes = nullptr,
167 .OnMessage = nullptr,
168 .OnStream = nullptr,
169 };
170 QosTV qos[] = {
171 {.qos = QOS_TYPE_MIN_BW, .value = DFS_QOS_TYPE_MIN_BW},
172 {.qos = QOS_TYPE_MAX_LATENCY, .value = DFS_QOS_TYPE_MAX_LATENCY},
173 {.qos = QOS_TYPE_MIN_LATENCY, .value = DFS_QOS_TYPE_MIN_LATENCY},
174 };
175 SocketInfo clientInfo = {
176 .name = const_cast<char*>((sessionName_.c_str())),
177 .peerName = const_cast<char*>(sessionName_.c_str()),
178 .peerNetworkId = const_cast<char*>(info.GetCid().c_str()),
179 .pkgName = const_cast<char*>(IDaemon::SERVICE_NAME.c_str()),
180 .dataType = DATA_TYPE_BYTES,
181 };
182 int32_t socketId = Socket(clientInfo);
183 if (socketId < FileManagement::E_OK) {
184 LOGE("Create OpenSoftbusChannel Socket error");
185 return FileManagement::E_CONTEXT;
186 }
187 if (FindSocketId(socketId)) {
188 LOGW("Has find socketId:%{public}d", socketId);
189 return FileManagement::E_OK;
190 }
191 int32_t ret = Bind(socketId, qos, sizeof(qos) / sizeof(qos[0]), &sessionListener);
192 if (ret != FileManagement::E_OK) {
193 LOGE("Bind SocketClient error");
194 RADAR_REPORT(RadarReporter::DFX_SET_DFS, RadarReporter::DFX_BUILD__LINK, RadarReporter::DFX_FAILED,
195 RadarReporter::BIZ_STATE, RadarReporter::DFX_END, RadarReporter::ERROR_CODE,
196 RadarReporter::BIND_SOCKET_ERROR, RadarReporter::PACKAGE_NAME, RadarReporter::dSoftBus + to_string(ret));
197 Shutdown(socketId);
198 return FileManagement::E_CONTEXT;
199 }
200 auto session = make_shared<SoftbusSession>(socketId, info.GetCid());
201 session->DisableSessionListener();
202 session->SetFromServer(false);
203 AcceptSession(session, "Client");
204 LOGI("Suc OpenSession socketId:%{public}d, cid:%{public}s", socketId, Utils::GetAnonyString(info.GetCid()).c_str());
205 return FileManagement::E_OK;
206 }
207
CloseSession(shared_ptr<BaseSession> session)208 void SoftbusAgent::CloseSession(shared_ptr<BaseSession> session)
209 {
210 if (session == nullptr) {
211 LOGE("Failed to close session, error:invalid session");
212 return;
213 }
214 session->Release();
215 }
216
IsContinueRetry(const string & cid)217 bool SoftbusAgent::IsContinueRetry(const string &cid)
218 {
219 auto retriedTimesMap = OpenSessionRetriedTimesMap_.find(cid);
220 if (retriedTimesMap != OpenSessionRetriedTimesMap_.end()) {
221 if (retriedTimesMap->second >= MAX_RETRY_COUNT) {
222 return false;
223 }
224 } else {
225 OpenSessionRetriedTimesMap_[cid] = 0;
226 }
227 OpenSessionRetriedTimesMap_[cid]++;
228 return true;
229 }
230
OnSessionOpened(const int32_t sessionId,PeerSocketInfo info)231 void SoftbusAgent::OnSessionOpened(const int32_t sessionId, PeerSocketInfo info)
232 {
233 LOGI("OnSessionOpened sessionId = %{public}d", sessionId);
234 std::string peerDeviceId = info.networkId;
235 auto session = make_shared<SoftbusSession>(sessionId, peerDeviceId);
236 session->DisableSessionListener();
237 session->SetFromServer(true);
238 AcceptSession(session, "Server");
239 }
240
OnSessionClosed(int32_t sessionId,const std::string peerDeviceId)241 void SoftbusAgent::OnSessionClosed(int32_t sessionId, const std::string peerDeviceId)
242 {
243 LOGI("OnSessionClosed Enter.");
244 Shutdown(sessionId);
245 }
246 } // namespace DistributedFile
247 } // namespace Storage
248 } // namespace OHOS
249