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 &param)
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