1 /*
2 * Copyright (c) 2021-2022 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 "uds_socket.h"
17
18 #include <cinttypes>
19
20 #include "error_multimodal.h"
21 #include "mmi_log.h"
22
23 namespace OHOS {
24 namespace MMI {
25 namespace {
26 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, MMI_LOG_DOMAIN, "UDSSocket" };
27 } // namespace
28
UDSSocket()29 UDSSocket::UDSSocket() {}
30
~UDSSocket()31 UDSSocket::~UDSSocket()
32 {
33 Close();
34 EpollClose();
35 }
36
EpollCreat(int32_t size)37 int32_t UDSSocket::EpollCreat(int32_t size)
38 {
39 epollFd_ = epoll_create(size);
40 if (epollFd_ < 0) {
41 MMI_HILOGE("epoll_create return %{public}d", epollFd_);
42 } else {
43 MMI_HILOGI("epoll_create, epollFd_:%{public}d", epollFd_);
44 }
45 return epollFd_;
46 }
47
EpollCtl(int32_t fd,int32_t op,struct epoll_event & event,int32_t epollFd)48 int32_t UDSSocket::EpollCtl(int32_t fd, int32_t op, struct epoll_event &event, int32_t epollFd)
49 {
50 if (fd < 0) {
51 MMI_HILOGE("Invalid fd");
52 return RET_ERR;
53 }
54 if (epollFd < 0) {
55 epollFd = epollFd_;
56 }
57 if (epollFd < 0) {
58 MMI_HILOGE("Invalid param epollFd");
59 return RET_ERR;
60 }
61 int32_t ret;
62 if (op == EPOLL_CTL_DEL) {
63 ret = epoll_ctl(epollFd, op, fd, NULL);
64 } else {
65 ret = epoll_ctl(epollFd, op, fd, &event);
66 }
67 if (ret < 0) {
68 MMI_HILOGE("epoll_ctl return %{public}d,epollFd_:%{public}d,"
69 "op:%{public}d,fd:%{public}d,errno:%{public}d",
70 ret, epollFd, op, fd, errno);
71 }
72 return ret;
73 }
74
EpollWait(struct epoll_event & events,int32_t maxevents,int32_t timeout,int32_t epollFd)75 int32_t UDSSocket::EpollWait(struct epoll_event &events, int32_t maxevents, int32_t timeout, int32_t epollFd)
76 {
77 if (epollFd < 0) {
78 epollFd = epollFd_;
79 }
80 if (epollFd < 0) {
81 MMI_HILOGE("Invalid param epollFd");
82 return RET_ERR;
83 }
84 auto ret = epoll_wait(epollFd, &events, maxevents, timeout);
85 if (ret < 0) {
86 MMI_HILOGE("epoll_wait ret:%{public}d,errno:%{public}d", ret, errno);
87 }
88 return ret;
89 }
90
SetNonBlockMode(int32_t fd,bool isNonBlock)91 int32_t UDSSocket::SetNonBlockMode(int32_t fd, bool isNonBlock)
92 {
93 if (fd < 0) {
94 MMI_HILOGE("Invalid fd");
95 return RET_ERR;
96 }
97 int32_t flags = fcntl(fd, F_GETFL);
98 if (flags < 0) {
99 MMI_HILOGE("fcntl F_GETFL fail. fd:%{public}d,flags:%{public}d,errno:%{public}d,errCode:%{public}d",
100 fd, flags, errno, FCNTL_FAIL);
101 return flags;
102 }
103 MMI_HILOGI("F_GETFL fd:%{public}d,flags:%{public}d", fd, flags);
104 uint32_t mask = static_cast<uint32_t>(flags);
105 mask |= O_NONBLOCK;
106 if (!isNonBlock) {
107 mask &= ~O_NONBLOCK;
108 }
109 flags = fcntl(fd, F_SETFL, static_cast<int32_t>(mask));
110 if (flags < 0) {
111 MMI_HILOGE("fcntl F_SETFL fail. fd:%{public}d,flags:%{public}d,errno:%{public}d,errCode:%{public}d",
112 fd, flags, errno, FCNTL_FAIL);
113 return flags;
114 }
115 MMI_HILOGI("F_SETFL fd:%{public}d,flags:%{public}d", fd, flags);
116 return flags;
117 }
118
OnReadPackets(CircleStreamBuffer & circBuf,UDSSocket::PacketCallBackFun callbackFun)119 void UDSSocket::OnReadPackets(CircleStreamBuffer &circBuf, UDSSocket::PacketCallBackFun callbackFun)
120 {
121 constexpr int32_t headSize = static_cast<int32_t>(sizeof(PackHead));
122 for (int32_t i = 0; i < ONCE_PROCESS_NETPACKET_LIMIT; i++) {
123 const int32_t unreadSize = circBuf.UnreadSize();
124 if (unreadSize < headSize) {
125 break;
126 }
127 int32_t dataSize = unreadSize - headSize;
128 char *buf = const_cast<char *>(circBuf.ReadBuf());
129 CHKPB(buf);
130 PackHead *head = reinterpret_cast<PackHead *>(buf);
131 CHKPB(head);
132 if (head->size < 0 || head->size > MAX_PACKET_BUF_SIZE) {
133 MMI_HILOGF("Packet header parsing error, and this error cannot be recovered. The buffer will be reset."
134 " head->size:%{public}d, unreadSize:%{public}d", head->size, unreadSize);
135 circBuf.Reset();
136 break;
137 }
138 if (head->size > dataSize) {
139 break;
140 }
141 NetPacket pkt(head->idMsg);
142 if ((head->size > 0) && (!pkt.Write(&buf[headSize], head->size))) {
143 MMI_HILOGW("Error writing data in the NetPacket. It will be retried next time. messageid:%{public}d,"
144 "size:%{public}d", head->idMsg, head->size);
145 break;
146 }
147 if (!circBuf.SeekReadPos(pkt.GetPacketLength())) {
148 MMI_HILOGW("Set read position error, and this error cannot be recovered, and the buffer will be reset."
149 " packetSize:%{public}d unreadSize:%{public}d", pkt.GetPacketLength(), unreadSize);
150 circBuf.Reset();
151 break;
152 }
153 callbackFun(pkt);
154 if (circBuf.IsEmpty()) {
155 circBuf.Reset();
156 break;
157 }
158 }
159 }
160
EpollClose()161 void UDSSocket::EpollClose()
162 {
163 if (epollFd_ >= 0) {
164 close(epollFd_);
165 epollFd_ = -1;
166 }
167 }
168
Close()169 void UDSSocket::Close()
170 {
171 if (fd_ >= 0) {
172 auto rf = close(fd_);
173 if (rf > 0) {
174 MMI_HILOGE("Socket close failed rf:%{public}d", rf);
175 }
176 }
177 fd_ = -1;
178 }
179 } // namespace MMI
180 } // namespace OHOS