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