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 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
ConnectDeviceByP2PAsync(const DeviceInfo info)51 void NetworkAgentTemplate::ConnectDeviceByP2PAsync(const DeviceInfo info)
52 {
53 LOGI("ConnectDeviceByP2PAsync Enter");
54 std::this_thread::sleep_for(std::chrono::milliseconds(OPEN_SESSSION_DELAY_TIME));
55 OpenSession(info, LINK_TYPE_P2P);
56 }
57
ConnectOnlineDevices()58 void NetworkAgentTemplate::ConnectOnlineDevices()
59 {
60 string pkgName = IDaemon::SERVICE_NAME;
61 auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
62
63 auto dma = DeviceManagerAgent::GetInstance();
64 auto infos = dma->GetRemoteDevicesInfo();
65 LOGI("Have %{public}zu devices Online", infos.size());
66 for (const auto &info : infos) {
67 if (info.GetExtraData().empty()) {
68 LOGE("extraData is empty.");
69 return;
70 }
71 nlohmann::json entraDataJson = nlohmann::json::parse(info.GetExtraData(), nullptr, false);
72 if (entraDataJson.is_discarded()) {
73 LOGE("entraDataJson parse failed.");
74 return;
75 }
76 if (!Utils::IsInt32(entraDataJson, PARAM_KEY_OS_TYPE)) {
77 LOGE("error json int32_t param.");
78 return;
79 }
80 int32_t osType = entraDataJson[PARAM_KEY_OS_TYPE].get<int32_t>();
81 if (osType != DEVICE_OS_TYPE_OH) {
82 LOGE("%{private}s the device os type = %{private}d is not openharmony.",
83 Utils::GetAnonyString(info.GetCid()).c_str(), osType);
84 return;
85 }
86
87 int32_t networkType;
88 int errCode = deviceManager.GetNetworkTypeByNetworkId(pkgName, info.GetCid(), networkType);
89 if (errCode) {
90 LOGE("failed to get network type by network id errCode = %{public}d", errCode);
91 continue;
92 }
93 if (!(static_cast<uint32_t>(networkType) & (1 << DistributedHardware::BIT_NETWORK_TYPE_WIFI))) {
94 LOGI("not wifi network networkType = %{public}d == %{public}d", networkType,
95 1 << DistributedHardware::BIT_NETWORK_TYPE_WIFI);
96 continue;
97 }
98 }
99 }
100
DisconnectAllDevices()101 void NetworkAgentTemplate::DisconnectAllDevices()
102 {
103 sessionPool_.ReleaseAllSession();
104 ConnectCount::GetInstance()->RemoveAllConnect();
105 }
106
DisconnectDeviceByP2P(const DeviceInfo info)107 void NetworkAgentTemplate::DisconnectDeviceByP2P(const DeviceInfo info)
108 {
109 LOGI("CloseP2P, cid:%{public}s", Utils::GetAnonyString(info.GetCid()).c_str());
110 sessionPool_.ReleaseSession(info.GetCid(), false);
111 }
112
DisconnectDeviceByP2PHmdfs(const DeviceInfo info)113 void NetworkAgentTemplate::DisconnectDeviceByP2PHmdfs(const DeviceInfo info)
114 {
115 LOGI("DeviceOffline, cid:%{public}s", Utils::GetAnonyString(info.GetCid()).c_str());
116 sessionPool_.ReleaseSession(info.GetCid(), true);
117 ConnectCount::GetInstance()->NotifyRemoteReverseObj(info.GetCid(), ON_STATUS_OFFLINE);
118 ConnectCount::GetInstance()->RemoveConnect(info.GetCid());
119 }
120
CloseSessionForOneDevice(const string & cid)121 void NetworkAgentTemplate::CloseSessionForOneDevice(const string &cid)
122 {
123 LOGI("NOTIFY_OFFLINE, cid:%{public}s", Utils::GetAnonyString(cid).c_str());
124 sessionPool_.ReleaseSession(cid, true);
125 ConnectCount::GetInstance()->NotifyRemoteReverseObj(cid, ON_STATUS_OFFLINE);
126 ConnectCount::GetInstance()->RemoveConnect(cid);
127 }
128
AcceptSession(shared_ptr<BaseSession> session,const std::string backStage)129 void NetworkAgentTemplate::AcceptSession(shared_ptr<BaseSession> session, const std::string backStage)
130 {
131 auto cid = session->GetCid();
132 LOGI("AcceptSesion, cid:%{public}s", Utils::GetAnonyString(cid).c_str());
133 sessionPool_.HoldSession(session, backStage);
134 }
135
FindSocketId(int32_t socketId)136 bool NetworkAgentTemplate::FindSocketId(int32_t socketId)
137 {
138 return sessionPool_.FindSocketId(socketId);
139 }
140
GetSessionProcess(NotifyParam & param)141 void NetworkAgentTemplate::GetSessionProcess(NotifyParam ¶m)
142 {
143 auto cmd = make_unique<DfsuCmd<NetworkAgentTemplate, NotifyParam>>(
144 &NetworkAgentTemplate::GetSessionProcessInner, param);
145 cmd->UpdateOption({.tryTimes_ = 1});
146 Recv(move(cmd));
147 }
148
GetSessionProcessInner(NotifyParam param)149 void NetworkAgentTemplate::GetSessionProcessInner(NotifyParam param)
150 {
151 string cidStr(param.remoteCid, CID_MAX_LEN);
152 int fd = param.fd;
153 LOGI("NOTIFY_GET_SESSION, old fd %{public}d, remote cid %{public}s", fd, Utils::GetAnonyString(cidStr).c_str());
154 bool ifGetSession = sessionPool_.CheckIfGetSession(fd);
155 sessionPool_.ReleaseSession(fd);
156 if (ifGetSession) {
157 GetSession(cidStr);
158 } else {
159 sessionPool_.SinkOffline(cidStr);
160 }
161 }
162
GetSession(const string & cid)163 void NetworkAgentTemplate::GetSession(const string &cid)
164 {
165 std::this_thread::sleep_for(std::chrono::seconds(NOTIFY_GET_SESSION_WAITING_TIME));
166 DeviceInfo deviceInfo;
167 deviceInfo.SetCid(cid);
168 try {
169 if (OpenSession(deviceInfo, LINK_TYPE_P2P) == FileManagement::E_OK) {
170 return;
171 }
172 LOGE("reget session failed");
173 sessionPool_.SinkOffline(cid);
174 ConnectCount::GetInstance()->NotifyRemoteReverseObj(cid, ON_STATUS_OFFLINE);
175 ConnectCount::GetInstance()->RemoveConnect(cid);
176 auto deviceManager = DeviceManagerAgent::GetInstance();
177 auto deviceId = deviceManager->GetDeviceIdByNetworkId(cid);
178 if (!deviceId.empty()) {
179 deviceManager->UMountDfsDocs(cid, deviceId, true);
180 }
181 } catch (const DfsuException &e) {
182 LOGE("reget session failed, code: %{public}d", e.code());
183 }
184 }
185 } // namespace DistributedFile
186 } // namespace Storage
187 } // namespace OHOS
188