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