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