1 /*
2 * Copyright (c) 2021 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_context.h"
17
18 #include <sys/socket.h>
19 #include <sys/types.h>
20 #include <unistd.h>
21 #include <vector>
22 #include <fcntl.h>
23
24 #include "logging.h"
25 #include "securec.h"
26 #include "service_base.h"
27 #include "service_entry.h"
28
29 namespace {
30 const int PROTO_SIZE_MAX = 1024 * 1024;
31 const int MEMORY_BLOCK_UNIT = 4096;
32 } // namespace
33
SocketContext()34 SocketContext::SocketContext()
35 {
36 socketHandle_ = -1;
37 clientState_ = CLIENT_STAT_WORKING;
38 lastProcMS_ = 0;
39 serviceBase_ = nullptr;
40 }
41
~SocketContext()42 SocketContext::~SocketContext()
43 {
44 if (socketHandle_ >= 0) {
45 HILOG_ERROR(LOG_CORE, "SocketContext socketHandle_ = %d", socketHandle_);
46
47 int ret = shutdown(socketHandle_, SHUT_RDWR);
48 if (ret < 0) {
49 const int bufSize = 1024;
50 char buf[bufSize] = { 0 };
51 strerror_r(errno, buf, bufSize);
52 HILOG_ERROR(LOG_CORE, "shutdown socket err = %d %s", errno, buf);
53 }
54 ret = close(socketHandle_);
55 if (ret < 0) {
56 const int bufSize = 1024;
57 char buf[bufSize] = { 0 };
58 strerror_r(errno, buf, bufSize);
59 HILOG_ERROR(LOG_CORE, "close socket err = %d %s", errno, buf);
60 }
61 socketHandle_ = -1;
62 }
63 if (recvThread_.joinable()) {
64 recvThread_.join();
65 }
66 HILOG_ERROR(LOG_CORE, "recvThread join success");
67 }
68
RawProtocolProc(uint32_t pnum,const int8_t * buf,const uint32_t size)69 int SocketContext::RawProtocolProc(uint32_t pnum, const int8_t* buf, const uint32_t size)
70 {
71 return -1;
72 }
73
ReceiveData(int sock,uint8_t * databuf,uint32_t size)74 bool SocketContext::ReceiveData(int sock, uint8_t* databuf, uint32_t size)
75 {
76 uint32_t p = 0;
77 if (sock < 0) {
78 return false;
79 }
80 if (size == 0) {
81 return false;
82 }
83 while (p < size) {
84 int ret = recv(sock, &databuf[p], size - p, 0);
85 if (ret <= 0) {
86 if (ret == -1 && errno == EAGAIN) {
87 continue;
88 }
89 return false;
90 }
91 p += ret;
92 }
93 return true;
94 }
95
UnixSocketRecv(void * pp)96 void* SocketContext::UnixSocketRecv(void* pp)
97 {
98 pthread_setname_np(pthread_self(), "UnixSocketRecv");
99
100 uint32_t bufferSize = MEMORY_BLOCK_UNIT;
101
102 SocketContext* pssr = (SocketContext*)pp;
103 std::vector<unsigned char> buf(bufferSize);
104
105 struct ProtocolHead* pph = (struct ProtocolHead*)buf.data();
106 uint32_t head_size = sizeof(struct ProtocolHead);
107
108 CHECK_TRUE(pssr->socketHandle_ != -1, nullptr, "UnixSocketRecv pssr->socketHandle_ ==-1");
109 while (pssr->socketHandle_ >= 0) {
110 if (!ReceiveData(pssr->socketHandle_, buf.data(), head_size)) {
111 HILOG_DEBUG(LOG_CORE, "====== IPC LOST CONNECT ======");
112 break;
113 }
114 if (pph->protoSize > bufferSize) {
115 if (pph->protoSize > PROTO_SIZE_MAX) {
116 HILOG_ERROR(LOG_CORE, "buffer size out of range %d/%d", pph->protoSize, PROTO_SIZE_MAX);
117 break;
118 }
119 bufferSize = (pph->protoSize / MEMORY_BLOCK_UNIT + 1) * MEMORY_BLOCK_UNIT;
120 buf.resize(bufferSize);
121 pph = (struct ProtocolHead*)buf.data();
122 }
123
124 if (!ReceiveData(pssr->socketHandle_, buf.data() + head_size, pph->protoSize - head_size)) {
125 HILOG_DEBUG(LOG_CORE, "====== IPC LOST CONNECT ======");
126 break;
127 }
128 switch (pph->protoType & PROTOCOL_TYPE_FILTER) {
129 case PROTOCOL_TYPE_RAW:
130 pssr->RawProtocolProc(pph->protoType & (~PROTOCOL_TYPE_FILTER), pph->datas, pph->protoSize - head_size);
131 break;
132 case PROTOCOL_TYPE_PROTOBUF:
133 if (pssr->serviceBase_ != nullptr) {
134 pssr->serviceBase_->ProtocolProc(*pssr, pph->protoType & (~PROTOCOL_TYPE_FILTER), pph->datas,
135 pph->protoSize - head_size);
136 }
137 break;
138 default:
139 HILOG_ERROR(LOG_CORE, "unknown protocol %d", pph->protoType);
140 break;
141 }
142 }
143 pssr->clientState_ = CLIENT_STAT_THREAD_EXITED;
144 HILOG_DEBUG(LOG_CORE, "UnixSocketRecv thread exit");
145 return nullptr;
146 }
147
CreateRecvThread()148 bool SocketContext::CreateRecvThread()
149 {
150 recvThread_ = std::thread(&SocketContext::UnixSocketRecv, this);
151 CHECK_TRUE(recvThread_.get_id() != std::thread::id(), false, "CreateRecvThread FAIL");
152 return true;
153 }
154
SendRaw(uint32_t pnum,const int8_t * data,uint32_t size,int sockfd)155 bool SocketContext::SendRaw(uint32_t pnum, const int8_t* data, uint32_t size, int sockfd)
156 {
157 CHECK_NOTNULL(data, false, "SendRaw data null");
158 if (sockfd == -1) {
159 sockfd = socketHandle_;
160 }
161 struct ProtocolHead phead;
162 phead.protoType = PROTOCOL_TYPE_RAW | pnum;
163 phead.protoSize = size + sizeof(struct ProtocolHead);
164 CHECK_TRUE(send(sockfd, reinterpret_cast<int8_t*>(&phead), sizeof(struct ProtocolHead), 0) != -1, false,
165 "SendRaw Send Head ERR :%d", errno);
166
167 CHECK_TRUE(send(sockfd, data, size, 0) != -1, false, "SendRaw Send Data ERR : %d", errno);
168 return true;
169 }
170
171 #ifndef NO_PROTOBUF
SendProtobuf(uint32_t pnum,google::protobuf::Message & pmsg)172 bool SocketContext::SendProtobuf(uint32_t pnum, google::protobuf::Message& pmsg)
173 {
174 int size = pmsg.ByteSizeLong();
175 CHECK_TRUE(size > 0, false, "%s:size less than or equal to 0", __func__);
176 int8_t* data = reinterpret_cast<int8_t*>(malloc(size));
177 if (data == nullptr) {
178 return false;
179 }
180 pmsg.SerializeToArray(data, size);
181 struct ProtocolHead phead;
182 phead.protoType = PROTOCOL_TYPE_PROTOBUF | pnum;
183 phead.protoSize = size + sizeof(struct ProtocolHead);
184 send(socketHandle_, reinterpret_cast<int8_t*>(&phead), sizeof(struct ProtocolHead), 0);
185 send(socketHandle_, data, size, 0);
186
187 free(data);
188 return true;
189 }
190 #endif
191
SendHookConfig(uint64_t config)192 bool SocketContext::SendHookConfig(uint64_t config)
193 {
194 struct ProtocolHead phead;
195 phead.protoType = PROTOCOL_TYPE_PROTOBUF;
196 phead.protoSize = sizeof(config) + sizeof(struct ProtocolHead);
197 send(socketHandle_, reinterpret_cast<int8_t*>(&phead), sizeof(struct ProtocolHead), 0);
198 send(socketHandle_, &config , sizeof(config), 0);
199
200 return true;
201 }
202
SendFileDescriptor(int fd)203 bool SocketContext::SendFileDescriptor(int fd)
204 {
205 struct msghdr msg = {0};
206 struct cmsghdr* cmsg = nullptr;
207 char buf[CMSG_SPACE(1 * sizeof(int))], data;
208 if (memset_s(buf, sizeof(buf), 0, sizeof(buf)) != EOK) {
209 HILOG_ERROR(LOG_CORE, "memset_s error!");
210 }
211 struct iovec io = {.iov_base = &data, .iov_len = 1};
212 msg.msg_iov = &io;
213 msg.msg_iovlen = 1;
214 msg.msg_control = buf;
215 msg.msg_controllen = sizeof(buf);
216 cmsg = CMSG_FIRSTHDR(&msg);
217 cmsg->cmsg_level = SOL_SOCKET;
218 cmsg->cmsg_type = SCM_RIGHTS;
219 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * 1);
220 if (memcpy_s(CMSG_DATA(cmsg), 1 * sizeof(int), &fd, 1 * sizeof(int)) != EOK) {
221 HILOG_ERROR(LOG_CORE, "memcpy_s error");
222 }
223
224 CHECK_TRUE(sendmsg(socketHandle_, &msg, 0) != -1, false, "SendFileDescriptor FAIL");
225 return true;
226 }
227
ReceiveFileDiscriptor()228 int SocketContext::ReceiveFileDiscriptor()
229 {
230 struct msghdr msg = {0};
231 struct cmsghdr* cmsg = nullptr;
232 char buf[CMSG_SPACE(1 * sizeof(int))], data;
233 struct iovec io = {.iov_base = &data, .iov_len = 1};
234 msg.msg_iov = &io;
235 msg.msg_iovlen = 1;
236 msg.msg_control = buf;
237 msg.msg_controllen = sizeof(buf);
238
239 CHECK_TRUE(recvmsg(socketHandle_, &msg, 0) != -1, -1, "ReceiveFileDiscriptor FAIL");
240 cmsg = CMSG_FIRSTHDR(&msg);
241
242 return cmsg ? *(int*)CMSG_DATA(cmsg) : -1;
243 }
244