• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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