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