1 /*
2  * Copyright (c) 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 "socket_client.h"
17 
18 #include "event_handler.h"
19 
20 #include "devicestatus_define.h"
21 #include "intention_identity.h"
22 #include "socket_params.h"
23 #include "time_cost_chk.h"
24 
25 #undef LOG_TAG
26 #define LOG_TAG "SocketClient"
27 
28 namespace OHOS {
29 namespace Msdp {
30 namespace DeviceStatus {
31 namespace {
32 const std::string THREAD_NAME { "os_ClientEventHandler" };
33 }
34 
SocketClient(std::shared_ptr<ITunnelClient> tunnel)35 SocketClient::SocketClient(std::shared_ptr<ITunnelClient> tunnel)
36     : tunnel_(tunnel)
37 {
38     auto runner = AppExecFwk::EventRunner::Create(THREAD_NAME);
39     eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
40 }
41 
RegisterEvent(MessageId id,std::function<int32_t (const StreamClient &,NetPacket &)> callback)42 bool SocketClient::RegisterEvent(MessageId id, std::function<int32_t(const StreamClient&, NetPacket&)> callback)
43 {
44     std::lock_guard guard(lock_);
45     auto [_, inserted] = callbacks_.emplace(id, callback);
46     return inserted;
47 }
48 
Start()49 void SocketClient::Start()
50 {
51     CALL_DEBUG_ENTER;
52     Reconnect();
53 }
54 
Stop()55 void SocketClient::Stop()
56 {}
57 
Connect()58 bool SocketClient::Connect()
59 {
60     CALL_DEBUG_ENTER;
61     if (socket_ != nullptr) {
62         return true;
63     }
64     auto socket = SocketConnection::Connect(
65         [this] { return this->Socket(); },
66         [this](NetPacket &pkt) { this->OnPacket(pkt); },
67         [this] { this->OnDisconnected(); });
68     CHKPF(socket);
69     CHKPF(eventHandler_);
70     auto errCode = eventHandler_->AddFileDescriptorListener(socket->GetFd(),
71         AppExecFwk::FILE_DESCRIPTOR_INPUT_EVENT, socket, "DeviceStatusTask");
72     if (errCode != ERR_OK) {
73         FI_HILOGE("AddFileDescriptorListener(%{public}d) failed (%{public}u)", socket->GetFd(), errCode);
74         return false;
75     }
76     socket_ = socket;
77     FI_HILOGD("SocketClient started successfully");
78     if (funConnected_ != nullptr) {
79         FI_HILOGI("Execute funConnected");
80         funConnected_();
81     }
82     return true;
83 }
84 
Socket()85 int32_t SocketClient::Socket()
86 {
87     CALL_DEBUG_ENTER;
88     std::shared_ptr<ITunnelClient> tunnel = tunnel_.lock();
89     CHKPR(tunnel, RET_ERR);
90     AllocSocketPairParam param { GetProgramName(), CONNECT_MODULE_TYPE_FI_CLIENT };
91     AllocSocketPairReply reply;
92 
93     int32_t ret = tunnel->Control(Intention::SOCKET, SocketAction::SOCKET_ACTION_CONNECT, param, reply);
94     if (ret != RET_OK) {
95         FI_HILOGE("ITunnelClient::Control fail");
96         return -1;
97     }
98     FI_HILOGD("Connected to intention service (%{public}d)", reply.socketFd);
99     return reply.socketFd;
100 }
101 
OnPacket(NetPacket & pkt)102 void SocketClient::OnPacket(NetPacket &pkt)
103 {
104     CALL_DEBUG_ENTER;
105     std::lock_guard guard(lock_);
106     OnMsgHandler(*this, pkt);
107 }
108 
OnDisconnected()109 void SocketClient::OnDisconnected()
110 {
111     CALL_DEBUG_ENTER;
112     std::lock_guard guard(lock_);
113     if (socket_ != nullptr) {
114         eventHandler_->RemoveFileDescriptorListener(socket_->GetFd());
115         eventHandler_->RemoveAllEvents();
116         socket_.reset();
117     }
118     if (funDisconnected_ != nullptr) {
119         FI_HILOGI("Execute funDisconnected");
120         funDisconnected_();
121     }
122     if (!eventHandler_->PostTask([this] { this->Reconnect(); }, CLIENT_RECONNECT_COOLING_TIME)) {
123         FI_HILOGE("Failed to post reconnection task");
124     }
125 }
126 
Reconnect()127 void SocketClient::Reconnect()
128 {
129     std::lock_guard guard(lock_);
130     if (Connect()) {
131         return;
132     }
133     if (!eventHandler_->PostTask([this] { this->Reconnect(); }, CLIENT_RECONNECT_COOLING_TIME)) {
134         FI_HILOGE("Failed to post reconnection task");
135     }
136 }
137 
OnMsgHandler(const StreamClient & client,NetPacket & pkt)138 void SocketClient::OnMsgHandler(const StreamClient &client, NetPacket &pkt)
139 {
140     CALL_DEBUG_ENTER;
141     MessageId id = pkt.GetMsgId();
142     TimeCostChk chk("SocketClient::OnMsgHandler", "overtime 300(us)", MAX_OVER_TIME, id);
143     auto iter = callbacks_.find(id);
144     if (iter == callbacks_.end()) {
145         FI_HILOGE("Unknown msg id:%{public}d", id);
146         return;
147     }
148     int32_t ret = iter->second(client, pkt);
149     if (ret < 0) {
150         FI_HILOGE("Msg handling failed, id:%{public}d, ret:%{public}d", id, ret);
151     }
152 }
153 
RegisterConnectedFunction(ConnectCallback funConnected)154 void SocketClient::RegisterConnectedFunction(ConnectCallback funConnected)
155 {
156     funConnected_ = funConnected;
157 }
158 
RegisterDisconnectedFunction(ConnectCallback funDisconnected)159 void SocketClient::RegisterDisconnectedFunction(ConnectCallback funDisconnected)
160 {
161     funDisconnected_ = funDisconnected;
162 }
163 } // namespace DeviceStatus
164 } // namespace Msdp
165 } // namespace OHOS