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/network_agent_template.h"
17
18 #include "connect_count/connect_count.h"
19 #include "device/device_manager_agent.h"
20 #include "dfs_error.h"
21 #include "dfsu_exception.h"
22 #include "utils_log.h"
23
24 namespace OHOS {
25 namespace Storage {
26 namespace DistributedFile {
27 using namespace std;
28 namespace {
29 constexpr int32_t DEVICE_OS_TYPE_OH = 10;
30 constexpr int OPEN_SESSSION_DELAY_TIME = 100;
31 constexpr int32_t NOTIFY_GET_SESSION_WAITING_TIME = 2;
32 constexpr const char* PARAM_KEY_OS_TYPE = "OS_TYPE";
33 } // namespace
34
Start()35 void NetworkAgentTemplate::Start()
36 {
37 if (kernerlTalker_ == nullptr) {
38 LOGE("kernerlTalker_ is nullptr.");
39 return;
40 }
41 LOGI("Start Enter");
42 JoinDomain();
43 kernerlTalker_->CreatePollThread();
44 ConnectOnlineDevices();
45 }
46
Stop()47 void NetworkAgentTemplate::Stop()
48 {
49 if (kernerlTalker_ == nullptr) {
50 LOGE("kernerlTalker_ is nullptr.");
51 return;
52 }
53 LOGI("Stop Enter");
54 StopTopHalf();
55 StopBottomHalf();
56 kernerlTalker_->WaitForPollThreadExited();
57 }
58
ConnectDeviceByP2PAsync(const DeviceInfo info)59 void NetworkAgentTemplate::ConnectDeviceByP2PAsync(const DeviceInfo info)
60 {
61 LOGI("ConnectDeviceByP2PAsync Enter");
62 std::this_thread::sleep_for(std::chrono::milliseconds(OPEN_SESSSION_DELAY_TIME));
63 OpenSession(info, LINK_TYPE_P2P);
64 }
65
ConnectOnlineDevices()66 void NetworkAgentTemplate::ConnectOnlineDevices()
67 {
68 string pkgName = IDaemon::SERVICE_NAME;
69 auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
70
71 auto dma = DeviceManagerAgent::GetInstance();
72 auto infos = dma->GetRemoteDevicesInfo();
73 LOGI("Have %{public}zu devices Online", infos.size());
74 for (const auto &info : infos) {
75 if (info.GetExtraData().empty()) {
76 LOGE("extraData is empty.");
77 return;
78 }
79 nlohmann::json entraDataJson = nlohmann::json::parse(info.GetExtraData(), nullptr, false);
80 if (entraDataJson.is_discarded()) {
81 LOGE("entraDataJson parse failed.");
82 return;
83 }
84 if (!Utils::IsInt32(entraDataJson, PARAM_KEY_OS_TYPE)) {
85 LOGE("error json int32_t param.");
86 return;
87 }
88 int32_t osType = entraDataJson[PARAM_KEY_OS_TYPE].get<int32_t>();
89 if (osType != DEVICE_OS_TYPE_OH) {
90 LOGE("%{private}s the device os type = %{private}d is not openharmony.",
91 Utils::GetAnonyString(info.GetCid()).c_str(), osType);
92 return;
93 }
94
95 int32_t networkType;
96 int errCode = deviceManager.GetNetworkTypeByNetworkId(pkgName, info.GetCid(), networkType);
97 if (errCode) {
98 LOGE("failed to get network type by network id errCode = %{public}d", errCode);
99 continue;
100 }
101 if (!(static_cast<uint32_t>(networkType) & (1 << DistributedHardware::BIT_NETWORK_TYPE_WIFI))) {
102 LOGI("not wifi network networkType = %{public}d == %{public}d", networkType,
103 1 << DistributedHardware::BIT_NETWORK_TYPE_WIFI);
104 continue;
105 }
106 }
107 }
108
DisconnectAllDevices()109 void NetworkAgentTemplate::DisconnectAllDevices()
110 {
111 sessionPool_.ReleaseAllSession();
112 ConnectCount::GetInstance()->RemoveAllConnect();
113 }
114
DisconnectDeviceByP2P(const DeviceInfo info)115 void NetworkAgentTemplate::DisconnectDeviceByP2P(const DeviceInfo info)
116 {
117 LOGI("CloseP2P, cid:%{public}s", Utils::GetAnonyString(info.GetCid()).c_str());
118 sessionPool_.ReleaseSession(info.GetCid(), false);
119 }
120
DisconnectDeviceByP2PHmdfs(const DeviceInfo info)121 void NetworkAgentTemplate::DisconnectDeviceByP2PHmdfs(const DeviceInfo info)
122 {
123 LOGI("DeviceOffline, cid:%{public}s", Utils::GetAnonyString(info.GetCid()).c_str());
124 sessionPool_.ReleaseSession(info.GetCid(), true);
125 ConnectCount::GetInstance()->NotifyRemoteReverseObj(info.GetCid(), ON_STATUS_OFFLINE);
126 ConnectCount::GetInstance()->RemoveConnect(info.GetCid());
127 }
128
CloseSessionForOneDevice(const string & cid)129 void NetworkAgentTemplate::CloseSessionForOneDevice(const string &cid)
130 {
131 auto cmd = make_unique<DfsuCmd<NetworkAgentTemplate, std::string>>(
132 &NetworkAgentTemplate::CloseSessionForOneDeviceInner, cid);
133 cmd->UpdateOption({.tryTimes_ = 1});
134 Recv(move(cmd));
135 }
136
CloseSessionForOneDeviceInner(std::string cid)137 void NetworkAgentTemplate::CloseSessionForOneDeviceInner(std::string cid)
138 {
139 sessionPool_.ReleaseSession(cid, true);
140 ConnectCount::GetInstance()->NotifyRemoteReverseObj(cid, ON_STATUS_OFFLINE);
141 ConnectCount::GetInstance()->RemoveConnect(cid);
142 }
143
AcceptSession(shared_ptr<BaseSession> session,const std::string backStage)144 void NetworkAgentTemplate::AcceptSession(shared_ptr<BaseSession> session, const std::string backStage)
145 {
146 if (session == nullptr) {
147 LOGE("session is nullptr.");
148 return;
149 }
150 auto cid = session->GetCid();
151 LOGI("AcceptSesion, cid:%{public}s", Utils::GetAnonyString(cid).c_str());
152 sessionPool_.HoldSession(session, backStage);
153 }
154
FindSocketId(int32_t socketId)155 bool NetworkAgentTemplate::FindSocketId(int32_t socketId)
156 {
157 return sessionPool_.FindSocketId(socketId);
158 }
159
GetSessionProcess(NotifyParam & param)160 void NetworkAgentTemplate::GetSessionProcess(NotifyParam ¶m)
161 {
162 auto cmd = make_unique<DfsuCmd<NetworkAgentTemplate, NotifyParam>>(
163 &NetworkAgentTemplate::GetSessionProcessInner, param);
164 cmd->UpdateOption({.tryTimes_ = 1});
165 Recv(move(cmd));
166 }
167
GetSessionProcessInner(NotifyParam param)168 void NetworkAgentTemplate::GetSessionProcessInner(NotifyParam param)
169 {
170 string cidStr(param.remoteCid, CID_MAX_LEN);
171 int fd = param.fd;
172 LOGI("NOTIFY_GET_SESSION, old fd %{public}d, remote cid %{public}s", fd, Utils::GetAnonyString(cidStr).c_str());
173 bool ifGetSession = sessionPool_.CheckIfGetSession(fd);
174 sessionPool_.ReleaseSession(fd);
175 if (ifGetSession && ConnectCount::GetInstance()->CheckCount(cidStr)) {
176 GetSession(cidStr);
177 } else {
178 sessionPool_.SinkOffline(cidStr);
179 }
180 }
181
GetSession(const string & cid)182 void NetworkAgentTemplate::GetSession(const string &cid)
183 {
184 std::this_thread::sleep_for(std::chrono::seconds(NOTIFY_GET_SESSION_WAITING_TIME));
185 DeviceInfo deviceInfo;
186 deviceInfo.SetCid(cid);
187 try {
188 if (OpenSession(deviceInfo, LINK_TYPE_P2P) == FileManagement::E_OK) {
189 return;
190 }
191 LOGE("reget session failed");
192 sessionPool_.SinkOffline(cid);
193 ConnectCount::GetInstance()->NotifyRemoteReverseObj(cid, ON_STATUS_OFFLINE);
194 ConnectCount::GetInstance()->RemoveConnect(cid);
195 auto deviceManager = DeviceManagerAgent::GetInstance();
196 auto deviceId = deviceManager->GetDeviceIdByNetworkId(cid);
197 if (!deviceId.empty()) {
198 deviceManager->UMountDfsDocs(cid, deviceId, true);
199 }
200 } catch (const DfsuException &e) {
201 LOGE("reget session failed, code: %{public}d", e.code());
202 }
203 }
204 } // namespace DistributedFile
205 } // namespace Storage
206 } // namespace OHOS
207