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