1 /*
2 * Copyright (c) 2021-2023 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 "client.h"
17
18 #include <cinttypes>
19 #include <condition_variable>
20
21 #include "devicestatus_client.h"
22 #include "fd_listener.h"
23 #include "fi_log.h"
24 #include "proto.h"
25 #include "time_cost_chk.h"
26 #include "include/util.h"
27
28 #undef LOG_TAG
29 #define LOG_TAG "Client"
30
31 namespace OHOS {
32 namespace Msdp {
33 namespace DeviceStatus {
34 namespace {
35 const std::string THREAD_NAME { "os_ClientEventHandler" };
36 } // namespace
37
38 using namespace AppExecFwk;
~Client()39 Client::~Client()
40 {
41 CALL_DEBUG_ENTER;
42 Stop();
43 }
44
SetEventHandler(EventHandlerPtr eventHandler)45 void Client::SetEventHandler(EventHandlerPtr eventHandler)
46 {
47 CHKPV(eventHandler);
48 eventHandler_ = eventHandler;
49 }
50
MarkIsEventHandlerChanged(EventHandlerPtr eventHandler)51 void Client::MarkIsEventHandlerChanged(EventHandlerPtr eventHandler)
52 {
53 CHKPV(eventHandler);
54 CHKPV(eventHandler_);
55 auto currentRunner = eventHandler_->GetEventRunner();
56 CHKPV(currentRunner);
57 auto newEventRunner = eventHandler->GetEventRunner();
58 CHKPV(newEventRunner);
59 isEventHandlerChanged_ = false;
60 if (currentRunner->GetRunnerThreadName() != newEventRunner->GetRunnerThreadName()) {
61 isEventHandlerChanged_ = true;
62 FI_HILOGD("Event handler changed");
63 }
64 FI_HILOGD("Current handler name:%{public}s, New handler name:%{public}s",
65 currentRunner->GetRunnerThreadName().c_str(), newEventRunner->GetRunnerThreadName().c_str());
66 }
67
SendMessage(const NetPacket & pkt) const68 bool Client::SendMessage(const NetPacket &pkt) const
69 {
70 return SendMsg(pkt);
71 }
72
GetCurrentConnectedStatus() const73 bool Client::GetCurrentConnectedStatus() const
74 {
75 return GetConnectedStatus();
76 }
77
GetSharedPtr()78 IClientPtr Client::GetSharedPtr()
79 {
80 return shared_from_this();
81 }
82
Start()83 bool Client::Start()
84 {
85 CALL_DEBUG_ENTER;
86 auto callback = [this](const StreamClient &client, NetPacket &pkt) {
87 this->OnMsgHandler(client, pkt);
88 };
89 if (!StartClient(callback)) {
90 FI_HILOGE("Client startup failed");
91 Stop();
92 return false;
93 }
94 if (!StartEventRunner()) {
95 FI_HILOGE("Start runner failed");
96 Stop();
97 return false;
98 }
99 FI_HILOGD("Client started successfully");
100 return true;
101 }
102
StartEventRunner()103 bool Client::StartEventRunner()
104 {
105 CALL_DEBUG_ENTER;
106 CHK_PID_AND_TID();
107 auto runner = AppExecFwk::EventRunner::Create(THREAD_NAME);
108 CHKPF(runner);
109 eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
110
111 FI_HILOGI("Create event handler, thread name:%{public}s", runner->GetRunnerThreadName().c_str());
112
113 if (hasConnected_ && fd_ >= 0) {
114 if (isListening_) {
115 FI_HILOGI("File fd is in listening");
116 return true;
117 }
118 if (!AddFdListener(fd_)) {
119 FI_HILOGE("Add fd listener failed");
120 return false;
121 }
122 } else {
123 if (!eventHandler_->PostTask([this] { this->OnReconnect(); }, CLIENT_RECONNECT_COOLING_TIME)) {
124 FI_HILOGE("Send reconnect event failed");
125 return false;
126 }
127 }
128 return true;
129 }
130
AddFdListener(int32_t fd)131 bool Client::AddFdListener(int32_t fd)
132 {
133 CALL_DEBUG_ENTER;
134 if (fd < 0) {
135 FI_HILOGE("Invalid fd:%{public}d", fd);
136 return false;
137 }
138 CHKPF(eventHandler_);
139 auto fdListener = std::make_shared<FdListener>(GetSharedPtr());
140 auto errCode = eventHandler_->AddFileDescriptorListener(fd, FILE_DESCRIPTOR_INPUT_EVENT, fdListener,
141 "DeviceStatusTask");
142 if (errCode != ERR_OK) {
143 FI_HILOGE("Add fd listener failed, fd:%{public}d, code:%{public}u, str:%{public}s", fd, errCode,
144 GetErrorStr(errCode).c_str());
145 return false;
146 }
147 isRunning_ = true;
148 FI_HILOGI("serverFd:%{public}d was listening, mask:%{public}u," PRIu64, fd, FILE_DESCRIPTOR_INPUT_EVENT);
149 return true;
150 }
151
DelFdListener(int32_t fd)152 bool Client::DelFdListener(int32_t fd)
153 {
154 CALL_DEBUG_ENTER;
155 CHKPF(eventHandler_);
156 if (fd >= 0) {
157 eventHandler_->RemoveFileDescriptorListener(fd);
158 FI_HILOGI("Remove file descriptor listener success");
159 } else {
160 FI_HILOGE("Invalid fd:%{public}d", fd);
161 }
162 auto runner = eventHandler_->GetEventRunner();
163 CHKPF(runner);
164 if (runner->GetRunnerThreadName() == THREAD_NAME) {
165 eventHandler_->RemoveAllEvents();
166 FI_HILOGI("Remove all events success");
167 }
168 isRunning_ = false;
169 return true;
170 }
171
OnPacket(NetPacket & pkt)172 void Client::OnPacket(NetPacket &pkt)
173 {
174 recvFun_(*this, pkt);
175 }
176
OnRecvMsg(const char * buf,size_t size)177 void Client::OnRecvMsg(const char *buf, size_t size)
178 {
179 CHKPV(buf);
180 if (size == 0 || size > MAX_PACKET_BUF_SIZE) {
181 FI_HILOGE("Invalid input param size, size:%{public}zu", size);
182 return;
183 }
184 if (!circBuf_.Write(buf, size)) {
185 FI_HILOGW("Write data failed, size:%{public}zu", size);
186 }
187 OnReadPackets(circBuf_, [this](NetPacket &pkt) { this->OnPacket(pkt); });
188 }
189
Reconnect()190 int32_t Client::Reconnect()
191 {
192 return StartConnect();
193 }
194
OnReconnect()195 void Client::OnReconnect()
196 {
197 if (Reconnect() == RET_OK) {
198 FI_HILOGI("Reconnect ok");
199 return;
200 }
201 CHKPV(eventHandler_);
202 if (!eventHandler_->PostTask([this] { this->OnReconnect(); }, CLIENT_RECONNECT_COOLING_TIME)) {
203 FI_HILOGE("Post reconnect event failed");
204 }
205 }
206
OnDisconnect()207 void Client::OnDisconnect()
208 {
209 OnDisconnected();
210 }
211
RegisterConnectedFunction(ConnectCallback function)212 void Client::RegisterConnectedFunction(ConnectCallback function)
213 {
214 funConnected_ = function;
215 }
216
RegisterDisconnectedFunction(ConnectCallback fun)217 void Client::RegisterDisconnectedFunction(ConnectCallback fun)
218 {
219 funDisconnected_ = fun;
220 }
221
OnDisconnected()222 void Client::OnDisconnected()
223 {
224 CALL_DEBUG_ENTER;
225 FI_HILOGI("Disconnected from server, fd:%{public}d", fd_);
226 hasConnected_ = false;
227 isListening_ = false;
228 if (funDisconnected_ != nullptr) {
229 FI_HILOGI("Execute funDisconnected");
230 funDisconnected_();
231 }
232 if (!DelFdListener(fd_)) {
233 FI_HILOGW("Delete fd listener failed");
234 }
235 StreamClient::Stop();
236 if (hasClient_ && eventHandler_ != nullptr) {
237 if (!eventHandler_->PostTask([this] { this->OnReconnect(); }, CLIENT_RECONNECT_COOLING_TIME)) {
238 FI_HILOGE("Send reconnect event task failed");
239 }
240 }
241 }
242
OnConnected()243 void Client::OnConnected()
244 {
245 CALL_DEBUG_ENTER;
246 FI_HILOGI("Connection to server succeeded, fd:%{public}d", GetFd());
247 hasConnected_ = true;
248 if (funConnected_ != nullptr) {
249 FI_HILOGI("Execute funConnected");
250 funConnected_();
251 }
252 if (hasClient_ && !isRunning_ && fd_ >= 0 && eventHandler_ != nullptr) {
253 if (!AddFdListener(fd_)) {
254 FI_HILOGE("Add fd listener failed");
255 return;
256 }
257 isListening_ = true;
258 }
259 }
260
Socket()261 int32_t Client::Socket()
262 {
263 CALL_DEBUG_ENTER;
264 return -1;
265 }
266
Stop()267 void Client::Stop()
268 {
269 CALL_DEBUG_ENTER;
270 StreamClient::Stop();
271 isRunning_ = false;
272 if (eventHandler_ != nullptr) {
273 auto runner = eventHandler_->GetEventRunner();
274 CHKPV(runner);
275 if (runner->GetRunnerThreadName() == THREAD_NAME) {
276 runner->Stop();
277 eventHandler_->RemoveAllEvents();
278 eventHandler_->RemoveAllFileDescriptorListeners();
279 FI_HILOGI("Remove all file descriptor listeners success");
280 }
281 }
282 }
283
OnMsgHandler(const StreamClient & client,NetPacket & pkt)284 void Client::OnMsgHandler(const StreamClient &client, NetPacket &pkt)
285 {
286 CALL_DEBUG_ENTER;
287 auto id = pkt.GetMsgId();
288 TimeCostChk chk("Client::OnMsgHandler", "overtime 300(us)", MAX_OVER_TIME, id);
289 auto callback = GetMsgCallback(id);
290 if (callback == nullptr) {
291 FI_HILOGE("Unknown msg id:%{public}d", id);
292 return;
293 }
294 int32_t ret = (*callback)(client, pkt);
295 if (ret < 0) {
296 FI_HILOGE("Msg handling failed, id:%{public}d, ret:%{public}d", id, ret);
297 return;
298 }
299 }
300
GetErrorStr(ErrCode code) const301 const std::string& Client::GetErrorStr(ErrCode code) const
302 {
303 const static std::string defErrString = "Unknown event handler error!";
304 const static std::map<ErrCode, std::string> mapStrings = {
305 { ERR_OK, "ERR_OK" },
306 { EVENT_HANDLER_ERR_INVALID_PARAM, "Invalid parameters" },
307 { EVENT_HANDLER_ERR_NO_EVENT_RUNNER, "Have not set event runner yet" },
308 { EVENT_HANDLER_ERR_FD_NOT_SUPPORT, "Not support to listen file descriptors" },
309 { EVENT_HANDLER_ERR_FD_ALREADY, "File descriptor is already in listening" },
310 { EVENT_HANDLER_ERR_FD_FAILED, "Failed to listen file descriptor" },
311 { EVENT_HANDLER_ERR_RUNNER_NO_PERMIT, "No permit to start or stop deposited event runner" },
312 { EVENT_HANDLER_ERR_RUNNER_ALREADY, "Event runner is already running" }
313 };
314 auto it = mapStrings.find(code);
315 if (it != mapStrings.end()) {
316 return it->second;
317 }
318 return defErrString;
319 }
320 } // namespace DeviceStatus
321 } // namespace Msdp
322 } // namespace OHOS
323