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/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 int socketFd = session->GetHandle();
76 auto masterkey = session->GetKey();
77 auto cid = session->GetCid();
78 LOGI("sink session to kernel success, cid:%{public}s, socketFd:%{public}d",
79 Utils::GetAnonyString(cid).c_str(), socketFd);
80
81 uint8_t status = (backStage == "Server" ? SOCKET_STAT_ACCEPT : SOCKET_STAT_OPEN);
82
83 UpdateSocketParam cmd = {
84 .cmd = CMD_UPDATE_SOCKET,
85 .newfd = socketFd,
86 .devsl = 0,
87 .status = status,
88 };
89 if (memcpy_s(cmd.masterKey, KEY_MAX_LEN, masterkey.data(), KEY_MAX_LEN) != EOK) {
90 return;
91 }
92
93 if (memcpy_s(cmd.cid, CID_MAX_LEN, cid.c_str(), cid.size())) {
94 return;
95 }
96 SetCmd(cmd);
97
98 DevslDispatcher::DevslGetRegister(cid, shared_from_this());
99 }
100
SinkDevslTokernel(const std::string & cid,uint32_t devsl)101 void KernelTalker::SinkDevslTokernel(const std::string &cid, uint32_t devsl)
102 {
103 LOGI("sink dsl to kernel success, cid:%{public}s, devsl:%{public}d", Utils::GetAnonyString(cid).c_str(), devsl);
104 UpdateDevslParam cmd = {
105 .cmd = CMD_UPDATE_DEVSL,
106 .devsl = devsl,
107 };
108
109 if (memcpy_s(cmd.cid, CID_MAX_LEN, cid.c_str(), CID_MAX_LEN)) {
110 return;
111 }
112 SetCmd(cmd);
113 }
114
SinkOfflineCmdToKernel(string cid)115 void KernelTalker::SinkOfflineCmdToKernel(string cid)
116 {
117 OfflineParam cmd = {
118 .cmd = CMD_OFF_LINE,
119 };
120
121 if (cid.length() < CID_MAX_LEN) {
122 LOGE("cid lengh err, cid:%{public}s, length:%{public}zu", Utils::GetAnonyString(cid).c_str(), cid.length());
123 return;
124 }
125
126 if (memcpy_s(cmd.remoteCid, CID_MAX_LEN, cid.c_str(), CID_MAX_LEN) != EOK) {
127 return;
128 }
129 SetCmd(cmd);
130 }
131
CreatePollThread()132 void KernelTalker::CreatePollThread()
133 {
134 isRunning_ = true;
135 if (pollThread_ != nullptr) {
136 LOGE("pollTread is not null");
137 return;
138 }
139 pollThread_ = make_unique<thread>(&KernelTalker::PollRun, this);
140 LOGI("Create pollThread OK");
141 }
142
WaitForPollThreadExited()143 void KernelTalker::WaitForPollThreadExited()
144 {
145 isRunning_ = false;
146 if (pollThread_ == nullptr) {
147 LOGE("pollTread is null");
148 return;
149 }
150
151 if (pollThread_->joinable()) {
152 LOGI("pollThread->joinable is true");
153 pollThread_->join();
154 }
155 pollThread_ = nullptr;
156 LOGI("pollTread exit ok");
157 }
158
PollRun()159 void KernelTalker::PollRun()
160 {
161 struct pollfd fileFd;
162 int cmdFd = -1;
163
164 LOGI("entry");
165 auto spt = mountPoint_.lock();
166 if (spt == nullptr) {
167 LOGE("mountPoint is not exist! bad weak_ptr");
168 return;
169 }
170 string ctrlPath = spt->GetMountArgument().GetCtrlPath();
171 LOGI("Open node file ctrl path %{public}s", GetAnonyString(ctrlPath).c_str());
172 char resolvedPath[PATH_MAX] = {'\0'};
173 char *realPath = realpath(ctrlPath.c_str(), resolvedPath);
174 if (realPath == nullptr) {
175 return;
176 }
177 cmdFd = open(realPath, O_RDWR);
178 if (cmdFd < 0) {
179 LOGE("Open node file error %{public}d, ctrl path %{public}s", errno, GetAnonyString(ctrlPath).c_str());
180 return;
181 }
182
183 LOGI("Open node file success");
184
185 while (isRunning_) {
186 fileFd.fd = cmdFd;
187 fileFd.events = POLLPRI;
188 fileFd.revents = 0;
189 int ret = poll(&fileFd, 1, POLL_TIMEOUT_MS);
190 switch (ret) {
191 case NONE_EVENT:
192 LOGI("none event, poll exit");
193 break;
194 case TIME_OUT_EVENT:
195 break;
196 case READ_EVENT:
197 HandleAllNotify(cmdFd);
198 break;
199 default:
200 LOGI("poll exit");
201 }
202 }
203 close(cmdFd);
204 LOGI("exit");
205 return;
206 }
207
HandleAllNotify(int fd)208 void KernelTalker::HandleAllNotify(int fd)
209 {
210 NotifyParam param;
211
212 while (isRunning_) {
213 lseek(fd, 0, SEEK_SET);
214 param.notify = NOTIFY_NONE;
215 int readSize = read(fd, ¶m, sizeof(NotifyParam));
216 if ((readSize < (int)sizeof(NotifyParam)) || (param.notify == NOTIFY_NONE)) {
217 return;
218 }
219 NotifyHandler(param);
220 }
221 }
222
NotifyHandler(NotifyParam & param)223 void KernelTalker::NotifyHandler(NotifyParam ¶m)
224 {
225 int cmd = param.notify;
226 string cidStr(param.remoteCid, CID_MAX_LEN);
227 switch (cmd) {
228 case NOTIFY_GET_SESSION:
229 GetSessionCallback_(param);
230 break;
231 case NOTIFY_OFFLINE:
232 CloseSessionCallback_(cidStr);
233 break;
234 default:
235 LOGI("cmd %{public}d not support now", cmd);
236 break;
237 }
238 }
239 } // namespace DistributedFile
240 } // namespace Storage
241 } // namespace OHOS
242