• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &param, 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 &param)
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