1 /*
2 * Copyright (c) 2021-2025 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/kernel_talker.h"
17 #include "device/device_manager_agent.h"
18 #include "network/devsl_dispatcher.h"
19 #include "securec.h"
20 #include "utils_log.h"
21
22 namespace OHOS {
23 namespace Storage {
24 namespace DistributedFile {
25 using namespace std;
26
27 constexpr int KEY_MAX_LEN = 32;
28 constexpr int POLL_TIMEOUT_MS = 200;
29 constexpr int NONE_EVENT = -1;
30 constexpr int READ_EVENT = 1;
31 constexpr int TIME_OUT_EVENT = 0;
32
33 struct UpdateSocketParam {
34 int32_t cmd;
35 int32_t newfd;
36 uint32_t devsl;
37 uint8_t status;
38 uint8_t masterKey[KEY_MAX_LEN];
39 uint8_t cid[CID_MAX_LEN];
40 } __attribute__((packed));
41
42 struct UpdateDevslParam {
43 int32_t cmd;
44 uint32_t devsl;
45 uint8_t cid[CID_MAX_LEN];
46 } __attribute__((packed));
47
48 struct OfflineParam {
49 int32_t cmd;
50 uint8_t remoteCid[CID_MAX_LEN];
51 } __attribute__((packed));
52
53 enum CmdCode {
54 CMD_UPDATE_SOCKET = 0,
55 CMD_UPDATE_DEVSL,
56 CMD_OFF_LINE,
57 CMD_OFF_LINE_ALL,
58 CMD_CNT,
59 };
60
61 enum SocketStat {
62 SOCKET_STAT_ACCEPT = 0,
63 SOCKET_STAT_OPEN,
64 };
65
66 enum Notify {
67 NOTIFY_GET_SESSION = 0,
68 NOTIFY_OFFLINE,
69 NOTIFY_NONE,
70 NOTIFY_CNT,
71 };
72
SinkSessionTokernel(shared_ptr<BaseSession> session,const std::string backStage)73 void KernelTalker::SinkSessionTokernel(shared_ptr<BaseSession> session, const std::string backStage)
74 {
75 if (session == nullptr) {
76 LOGE("session is nullptr.");
77 return;
78 }
79 int socketFd = session->GetHandle();
80 auto masterkey = session->GetKey();
81 auto cid = session->GetCid();
82 LOGI("sink session to kernel success, cid:%{public}s, socketFd:%{public}d",
83 Utils::GetAnonyString(cid).c_str(), socketFd);
84
85 uint8_t status = (backStage == "Server" ? SOCKET_STAT_ACCEPT : SOCKET_STAT_OPEN);
86
87 UpdateSocketParam cmd = {
88 .cmd = CMD_UPDATE_SOCKET,
89 .newfd = socketFd,
90 .devsl = 0,
91 .status = status,
92 };
93 if (memcpy_s(cmd.masterKey, KEY_MAX_LEN, masterkey.data(), KEY_MAX_LEN) != EOK) {
94 return;
95 }
96
97 if (memcpy_s(cmd.cid, CID_MAX_LEN, cid.c_str(), cid.size())) {
98 return;
99 }
100 SetCmd(cmd);
101 int32_t remoteDevsl = DevslDispatcher::GetDeviceDevsl(cid);
102 SinkDevslTokernel(cid, remoteDevsl);
103 }
104
SinkDevslTokernel(const std::string & cid,uint32_t devsl)105 void KernelTalker::SinkDevslTokernel(const std::string &cid, uint32_t devsl)
106 {
107 LOGI("sink dsl to kernel success, cid:%{public}s, devsl:%{public}d", Utils::GetAnonyString(cid).c_str(), devsl);
108 UpdateDevslParam cmd = {
109 .cmd = CMD_UPDATE_DEVSL,
110 .devsl = devsl,
111 };
112
113 if (memcpy_s(cmd.cid, CID_MAX_LEN, cid.c_str(), CID_MAX_LEN)) {
114 return;
115 }
116 SetCmd(cmd);
117 }
118
SinkOfflineCmdToKernel(string cid)119 void KernelTalker::SinkOfflineCmdToKernel(string cid)
120 {
121 OfflineParam cmd = {
122 .cmd = CMD_OFF_LINE,
123 };
124
125 if (cid.length() < CID_MAX_LEN) {
126 LOGE("cid lengh err, cid:%{public}s, length:%{public}zu", Utils::GetAnonyString(cid).c_str(), cid.length());
127 return;
128 }
129
130 if (memcpy_s(cmd.remoteCid, CID_MAX_LEN, cid.c_str(), CID_MAX_LEN) != EOK) {
131 return;
132 }
133 SetCmd(cmd);
134 }
135
CreatePollThread()136 void KernelTalker::CreatePollThread()
137 {
138 isRunning_ = true;
139 if (pollThread_ != nullptr) {
140 LOGE("pollTread is not null");
141 return;
142 }
143 pollThread_ = make_unique<thread>(&KernelTalker::PollRun, this);
144 LOGI("Create pollThread OK");
145 }
146
WaitForPollThreadExited()147 void KernelTalker::WaitForPollThreadExited()
148 {
149 isRunning_ = false;
150 if (pollThread_ == nullptr) {
151 LOGE("pollTread is null");
152 return;
153 }
154
155 if (pollThread_->joinable()) {
156 LOGI("pollThread->joinable is true");
157 pollThread_->join();
158 }
159 pollThread_ = nullptr;
160 LOGI("pollTread exit ok");
161 }
162
PollRun()163 void KernelTalker::PollRun()
164 {
165 struct pollfd fileFd;
166 int cmdFd = -1;
167
168 LOGI("entry");
169 auto spt = mountPoint_.lock();
170 if (spt == nullptr) {
171 LOGE("mountPoint is not exist! bad weak_ptr");
172 return;
173 }
174 string ctrlPath = spt->GetMountArgument().GetCtrlPath();
175 LOGI("Open node file ctrl path");
176 char resolvedPath[PATH_MAX] = {'\0'};
177 char *realPath = realpath(ctrlPath.c_str(), resolvedPath);
178 if (realPath == nullptr) {
179 LOGE("realpath fail");
180 return;
181 }
182 cmdFd = open(realPath, O_RDWR);
183 if (cmdFd < 0) {
184 LOGE("Open node file error %{public}d", errno);
185 return;
186 }
187
188 LOGI("Open node file success");
189
190 while (isRunning_) {
191 fileFd.fd = cmdFd;
192 fileFd.events = POLLPRI;
193 fileFd.revents = 0;
194 int ret = poll(&fileFd, 1, POLL_TIMEOUT_MS);
195 switch (ret) {
196 case NONE_EVENT:
197 LOGI("none event, poll exit");
198 break;
199 case TIME_OUT_EVENT:
200 break;
201 case READ_EVENT:
202 HandleAllNotify(cmdFd);
203 break;
204 default:
205 LOGI("poll exit");
206 }
207 }
208 close(cmdFd);
209 LOGI("exit");
210 return;
211 }
212
HandleAllNotify(int fd)213 void KernelTalker::HandleAllNotify(int fd)
214 {
215 NotifyParam param;
216
217 while (isRunning_) {
218 lseek(fd, 0, SEEK_SET);
219 param.notify = NOTIFY_NONE;
220 int readSize = read(fd, ¶m, sizeof(NotifyParam));
221 if ((readSize < (int)sizeof(NotifyParam)) || (param.notify == NOTIFY_NONE)) {
222 return;
223 }
224 NotifyHandler(param);
225 }
226 }
227
NotifyHandler(NotifyParam & param)228 void KernelTalker::NotifyHandler(NotifyParam ¶m)
229 {
230 int cmd = param.notify;
231 string cidStr(param.remoteCid, CID_MAX_LEN);
232 switch (cmd) {
233 case NOTIFY_GET_SESSION:
234 GetSessionCallback_(param);
235 break;
236 case NOTIFY_OFFLINE:
237 LOGI("NOTIFY_OFFLINE, cid:%{public}.5s", cidStr.c_str());
238 CloseSessionCallback_(cidStr);
239 break;
240 default:
241 LOGI("cmd %{public}d not support now", cmd);
242 break;
243 }
244 }
245 } // namespace DistributedFile
246 } // namespace Storage
247 } // namespace OHOS
248