106f6ba60Sopenharmony_ci/* 206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved. 306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License. 506f6ba60Sopenharmony_ci * You may obtain a copy of the License at 606f6ba60Sopenharmony_ci * 706f6ba60Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 806f6ba60Sopenharmony_ci * 906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and 1306f6ba60Sopenharmony_ci * limitations under the License. 1406f6ba60Sopenharmony_ci */ 1506f6ba60Sopenharmony_ci#include "ipc_unix_socket.h" 1606f6ba60Sopenharmony_ci 1706f6ba60Sopenharmony_ci#include <poll.h> 1806f6ba60Sopenharmony_ci#include <sys/socket.h> 1906f6ba60Sopenharmony_ci#include <sys/un.h> 2006f6ba60Sopenharmony_ci#include <unistd.h> 2106f6ba60Sopenharmony_ci 2206f6ba60Sopenharmony_ci#include "hhlog.h" 2306f6ba60Sopenharmony_ci 2406f6ba60Sopenharmony_cinamespace OHOS { 2506f6ba60Sopenharmony_cinamespace Developtools { 2606f6ba60Sopenharmony_cinamespace Hiebpf { 2706f6ba60Sopenharmony_ciIpcUnixSocketServer::IpcUnixSocketServer() {} 2806f6ba60Sopenharmony_ci 2906f6ba60Sopenharmony_ciIpcUnixSocketServer::~IpcUnixSocketServer() 3006f6ba60Sopenharmony_ci{ 3106f6ba60Sopenharmony_ci Stop(); 3206f6ba60Sopenharmony_ci} 3306f6ba60Sopenharmony_ci 3406f6ba60Sopenharmony_cibool IpcUnixSocketServer::Start(const std::string &pathname) 3506f6ba60Sopenharmony_ci{ 3606f6ba60Sopenharmony_ci CHECK_TRUE(serverFd_ == -1, false, "Unix Socket Server is running"); 3706f6ba60Sopenharmony_ci 3806f6ba60Sopenharmony_ci serverFd_ = socket(AF_UNIX, SOCK_STREAM, 0); 3906f6ba60Sopenharmony_ci CHECK_TRUE(serverFd_ != -1, false, "create Unix Socket Server failed, %d: %s", errno, strerror(errno)); 4006f6ba60Sopenharmony_ci 4106f6ba60Sopenharmony_ci unlink(pathname.c_str()); 4206f6ba60Sopenharmony_ci struct sockaddr_un addr = {0}; 4306f6ba60Sopenharmony_ci addr.sun_family = AF_UNIX; 4406f6ba60Sopenharmony_ci std::copy(pathname.c_str(), pathname.c_str() + pathname.size() + 1, addr.sun_path); 4506f6ba60Sopenharmony_ci if (bind(serverFd_, (struct sockaddr*)&addr, sizeof(sockaddr_un)) != 0) { 4606f6ba60Sopenharmony_ci HHLOGE(true, "bind failed, Unix Socket(%s), %d: %s", pathname.c_str(), errno, strerror(errno)); 4706f6ba60Sopenharmony_ci close(serverFd_); 4806f6ba60Sopenharmony_ci return false; 4906f6ba60Sopenharmony_ci } 5006f6ba60Sopenharmony_ci if (listen(serverFd_, UNIX_SOCKET_LISTEN_COUNT) != 0) { 5106f6ba60Sopenharmony_ci HHLOGE(true, "listen failed, Unix Socket(%s), %d: %s", pathname.c_str(), errno, strerror(errno)); 5206f6ba60Sopenharmony_ci close(serverFd_); 5306f6ba60Sopenharmony_ci unlink(pathname.c_str()); 5406f6ba60Sopenharmony_ci return false; 5506f6ba60Sopenharmony_ci } 5606f6ba60Sopenharmony_ci pathName_ = pathname; 5706f6ba60Sopenharmony_ci 5806f6ba60Sopenharmony_ci isRunning_ = true; 5906f6ba60Sopenharmony_ci handleThread_ = std::thread([this] { this->HandleThreadLoop(); }); 6006f6ba60Sopenharmony_ci return true; 6106f6ba60Sopenharmony_ci} 6206f6ba60Sopenharmony_ci 6306f6ba60Sopenharmony_cibool IpcUnixSocketServer::Stop() 6406f6ba60Sopenharmony_ci{ 6506f6ba60Sopenharmony_ci isRunning_ = false; 6606f6ba60Sopenharmony_ci if (serverFd_ != -1) { 6706f6ba60Sopenharmony_ci close(serverFd_); 6806f6ba60Sopenharmony_ci serverFd_ = -1; 6906f6ba60Sopenharmony_ci } 7006f6ba60Sopenharmony_ci if (clientFd_ != -1) { 7106f6ba60Sopenharmony_ci close(clientFd_); 7206f6ba60Sopenharmony_ci clientFd_ = -1; 7306f6ba60Sopenharmony_ci } 7406f6ba60Sopenharmony_ci if (handleThread_.joinable()) { 7506f6ba60Sopenharmony_ci handleThread_.join(); 7606f6ba60Sopenharmony_ci } 7706f6ba60Sopenharmony_ci unlink(pathName_.c_str()); 7806f6ba60Sopenharmony_ci return true; 7906f6ba60Sopenharmony_ci} 8006f6ba60Sopenharmony_ci 8106f6ba60Sopenharmony_cibool IpcUnixSocketServer::SendMessage(const void *buf, size_t size) 8206f6ba60Sopenharmony_ci{ 8306f6ba60Sopenharmony_ci CHECK_TRUE(clientFd_ != -1, false, "no available Unix Socket"); 8406f6ba60Sopenharmony_ci 8506f6ba60Sopenharmony_ci CHECK_TRUE(send(clientFd_, buf, size, 0) != -1, false, 8606f6ba60Sopenharmony_ci "send failed, Unix Socket(%d) %zu bytes, %d: %s", clientFd_, size, errno, strerror(errno)); 8706f6ba60Sopenharmony_ci return true; 8806f6ba60Sopenharmony_ci} 8906f6ba60Sopenharmony_ci 9006f6ba60Sopenharmony_civoid IpcUnixSocketServer::HandleThreadLoop() 9106f6ba60Sopenharmony_ci{ 9206f6ba60Sopenharmony_ci while (isRunning_) { 9306f6ba60Sopenharmony_ci struct pollfd pollFd {serverFd_, POLLIN, 0}; 9406f6ba60Sopenharmony_ci const int timeout = 1000; 9506f6ba60Sopenharmony_ci int polled = TEMP_FAILURE_RETRY(poll(&pollFd, 1, timeout)); 9606f6ba60Sopenharmony_ci if (polled == 0) { // timeout 9706f6ba60Sopenharmony_ci continue; 9806f6ba60Sopenharmony_ci } else if (polled < 0 || !(pollFd.revents & POLLIN)) { 9906f6ba60Sopenharmony_ci HHLOGE(true, "poll failed, Unix Socket(%d), %d: %s", serverFd_, errno, strerror(errno)); 10006f6ba60Sopenharmony_ci close(serverFd_); 10106f6ba60Sopenharmony_ci serverFd_ = -1; 10206f6ba60Sopenharmony_ci break; 10306f6ba60Sopenharmony_ci } 10406f6ba60Sopenharmony_ci 10506f6ba60Sopenharmony_ci clientFd_ = accept(serverFd_, nullptr, nullptr); 10606f6ba60Sopenharmony_ci if (clientFd_ == -1) { 10706f6ba60Sopenharmony_ci HHLOGE(true, "accept failed, Unix Socket(%d), %d: %s", serverFd_, errno, strerror(errno)); 10806f6ba60Sopenharmony_ci continue; 10906f6ba60Sopenharmony_ci } 11006f6ba60Sopenharmony_ci 11106f6ba60Sopenharmony_ci while (isRunning_ && clientFd_ != -1) { 11206f6ba60Sopenharmony_ci uint8_t buf[UNIX_SOCKET_BUFFER_SIZE] = {0}; 11306f6ba60Sopenharmony_ci int recvSize = recv(clientFd_, buf, UNIX_SOCKET_BUFFER_SIZE, 0); 11406f6ba60Sopenharmony_ci if (recvSize > 0) { 11506f6ba60Sopenharmony_ci if (handleMessageFn_) { 11606f6ba60Sopenharmony_ci handleMessageFn_(buf, recvSize); 11706f6ba60Sopenharmony_ci } 11806f6ba60Sopenharmony_ci continue; 11906f6ba60Sopenharmony_ci } else if (recvSize == 0) { 12006f6ba60Sopenharmony_ci HHLOGE(true, "recv failed, peer has closed"); 12106f6ba60Sopenharmony_ci } else { 12206f6ba60Sopenharmony_ci HHLOGE(true, "recv failed, Unix Socket(%d), %d: %s", clientFd_, errno, strerror(errno)); 12306f6ba60Sopenharmony_ci } 12406f6ba60Sopenharmony_ci close(clientFd_); 12506f6ba60Sopenharmony_ci clientFd_ = -1; 12606f6ba60Sopenharmony_ci } 12706f6ba60Sopenharmony_ci } 12806f6ba60Sopenharmony_ci} 12906f6ba60Sopenharmony_ci 13006f6ba60Sopenharmony_ciIpcUnixSocketClient::IpcUnixSocketClient() {} 13106f6ba60Sopenharmony_ci 13206f6ba60Sopenharmony_ciIpcUnixSocketClient::~IpcUnixSocketClient() 13306f6ba60Sopenharmony_ci{ 13406f6ba60Sopenharmony_ci Disconnect(); 13506f6ba60Sopenharmony_ci} 13606f6ba60Sopenharmony_ci 13706f6ba60Sopenharmony_cibool IpcUnixSocketClient::Connect(const std::string &pathname) 13806f6ba60Sopenharmony_ci{ 13906f6ba60Sopenharmony_ci CHECK_TRUE(sockFd_ == -1, false, "Unix Socket has connected"); 14006f6ba60Sopenharmony_ci 14106f6ba60Sopenharmony_ci sockFd_ = socket(AF_UNIX, SOCK_STREAM, 0); 14206f6ba60Sopenharmony_ci CHECK_TRUE(sockFd_ != -1, false, "create Unix Socket Server failed, %d: %s", errno, strerror(errno)); 14306f6ba60Sopenharmony_ci 14406f6ba60Sopenharmony_ci struct sockaddr_un addr = {0}; 14506f6ba60Sopenharmony_ci addr.sun_family = AF_UNIX; 14606f6ba60Sopenharmony_ci std::copy(pathname.c_str(), pathname.c_str() + pathname.size() + 1, addr.sun_path); 14706f6ba60Sopenharmony_ci if (connect(sockFd_, (struct sockaddr*)&addr, sizeof(sockaddr_un)) == -1) { 14806f6ba60Sopenharmony_ci HHLOGE(true, "connect failed, %d: %s", errno, strerror(errno)); 14906f6ba60Sopenharmony_ci sockFd_ = -1; 15006f6ba60Sopenharmony_ci return false; 15106f6ba60Sopenharmony_ci } 15206f6ba60Sopenharmony_ci 15306f6ba60Sopenharmony_ci return true; 15406f6ba60Sopenharmony_ci} 15506f6ba60Sopenharmony_ci 15606f6ba60Sopenharmony_civoid IpcUnixSocketClient::Disconnect() 15706f6ba60Sopenharmony_ci{ 15806f6ba60Sopenharmony_ci if (sockFd_ != -1) { 15906f6ba60Sopenharmony_ci close(sockFd_); 16006f6ba60Sopenharmony_ci sockFd_ = -1; 16106f6ba60Sopenharmony_ci } 16206f6ba60Sopenharmony_ci} 16306f6ba60Sopenharmony_ci 16406f6ba60Sopenharmony_cibool IpcUnixSocketClient::SendMessage(const void *buf, size_t size) 16506f6ba60Sopenharmony_ci{ 16606f6ba60Sopenharmony_ci CHECK_TRUE(sockFd_ != -1, false, "Unix Socket disconnected"); 16706f6ba60Sopenharmony_ci 16806f6ba60Sopenharmony_ci if (send(sockFd_, buf, size, 0) != -1) { 16906f6ba60Sopenharmony_ci return true; 17006f6ba60Sopenharmony_ci } 17106f6ba60Sopenharmony_ci HHLOGE(true, "send failed, Unix Socket(%d), %d: %s", sockFd_, errno, strerror(errno)); 17206f6ba60Sopenharmony_ci return false; 17306f6ba60Sopenharmony_ci} 17406f6ba60Sopenharmony_ci 17506f6ba60Sopenharmony_cibool IpcUnixSocketClient::RecvMessage(void *buf, size_t &size, uint32_t timeout) 17606f6ba60Sopenharmony_ci{ 17706f6ba60Sopenharmony_ci CHECK_TRUE(sockFd_ != -1, false, "Unix Socket disconnected"); 17806f6ba60Sopenharmony_ci 17906f6ba60Sopenharmony_ci struct pollfd pollFd {sockFd_, POLLIN | POLLERR | POLLHUP, 0}; 18006f6ba60Sopenharmony_ci int polled = poll(&pollFd, 1, timeout); 18106f6ba60Sopenharmony_ci if (polled == 0) { // timeout 18206f6ba60Sopenharmony_ci size = 0; 18306f6ba60Sopenharmony_ci return true; 18406f6ba60Sopenharmony_ci } else if (polled < 0 || !(pollFd.revents & POLLIN)) { 18506f6ba60Sopenharmony_ci HHLOGE(true, "poll failed, Unix Socket(%d), %d: %s", sockFd_, errno, strerror(errno)); 18606f6ba60Sopenharmony_ci return false; 18706f6ba60Sopenharmony_ci } 18806f6ba60Sopenharmony_ci 18906f6ba60Sopenharmony_ci int recvSize = recv(sockFd_, buf, size, 0); 19006f6ba60Sopenharmony_ci if (recvSize > 0) { 19106f6ba60Sopenharmony_ci size = static_cast<size_t>(recvSize); 19206f6ba60Sopenharmony_ci return true; 19306f6ba60Sopenharmony_ci } else if (recvSize == 0) { 19406f6ba60Sopenharmony_ci HHLOGE(true, "recv failed, peer has closed"); 19506f6ba60Sopenharmony_ci } else { 19606f6ba60Sopenharmony_ci HHLOGE(true, "recv failed, Unix Socket(%d), %d: %s", sockFd_, errno, strerror(errno)); 19706f6ba60Sopenharmony_ci } 19806f6ba60Sopenharmony_ci 19906f6ba60Sopenharmony_ci return false; 20006f6ba60Sopenharmony_ci} 20106f6ba60Sopenharmony_ci} // namespace Hiebpf 20206f6ba60Sopenharmony_ci} // namespace Developtools 20306f6ba60Sopenharmony_ci} // namespace OHOS 204