1d9f0492fSopenharmony_ci/* 2d9f0492fSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 3d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License. 5d9f0492fSopenharmony_ci * You may obtain a copy of the License at 6d9f0492fSopenharmony_ci * 7d9f0492fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8d9f0492fSopenharmony_ci * 9d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and 13d9f0492fSopenharmony_ci * limitations under the License. 14d9f0492fSopenharmony_ci */ 15d9f0492fSopenharmony_ci 16d9f0492fSopenharmony_ci#include "le_socket.h" 17d9f0492fSopenharmony_ci 18d9f0492fSopenharmony_ci#include <arpa/inet.h> 19d9f0492fSopenharmony_ci#include <errno.h> 20d9f0492fSopenharmony_ci#include <fcntl.h> 21d9f0492fSopenharmony_ci#include <netinet/in.h> 22d9f0492fSopenharmony_ci#include <stddef.h> 23d9f0492fSopenharmony_ci#include <string.h> 24d9f0492fSopenharmony_ci#include <sys/socket.h> 25d9f0492fSopenharmony_ci#include <sys/time.h> 26d9f0492fSopenharmony_ci#include <sys/stat.h> 27d9f0492fSopenharmony_ci#include <sys/un.h> 28d9f0492fSopenharmony_ci#include <unistd.h> 29d9f0492fSopenharmony_ci 30d9f0492fSopenharmony_ci#include "le_utils.h" 31d9f0492fSopenharmony_ci 32d9f0492fSopenharmony_cistatic int SetSocketTimeout(int fd) 33d9f0492fSopenharmony_ci{ 34d9f0492fSopenharmony_ci struct timeval timeout; 35d9f0492fSopenharmony_ci timeout.tv_sec = SOCKET_TIMEOUT; 36d9f0492fSopenharmony_ci timeout.tv_usec = 0; 37d9f0492fSopenharmony_ci int ret = setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); 38d9f0492fSopenharmony_ci LE_CHECK(ret == 0, return ret, "Failed to set socket option"); 39d9f0492fSopenharmony_ci 40d9f0492fSopenharmony_ci ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); 41d9f0492fSopenharmony_ci LE_CHECK(ret == 0, return ret, "Failed to set socket option"); 42d9f0492fSopenharmony_ci return ret; 43d9f0492fSopenharmony_ci} 44d9f0492fSopenharmony_ci 45d9f0492fSopenharmony_cistatic int CreatePipeServerSocket_(const char *server, int maxClient, int public) 46d9f0492fSopenharmony_ci{ 47d9f0492fSopenharmony_ci int listenfd = socket(PF_UNIX, SOCK_STREAM, 0); 48d9f0492fSopenharmony_ci LE_CHECK(listenfd > 0, return listenfd, "Failed to create socket errno %d", errno); 49d9f0492fSopenharmony_ci 50d9f0492fSopenharmony_ci int ret = SetSocketTimeout(listenfd); 51d9f0492fSopenharmony_ci LE_CHECK(ret == 0, return ret, "Failed to set socket timeout"); 52d9f0492fSopenharmony_ci 53d9f0492fSopenharmony_ci unlink(server); 54d9f0492fSopenharmony_ci struct sockaddr_un serverAddr; 55d9f0492fSopenharmony_ci ret = memset_s(&serverAddr, sizeof(serverAddr), 0, sizeof(serverAddr)); 56d9f0492fSopenharmony_ci LE_CHECK(ret == 0, close(listenfd); 57d9f0492fSopenharmony_ci return ret, "Failed to memory set. error: %d", errno); 58d9f0492fSopenharmony_ci serverAddr.sun_family = AF_UNIX; 59d9f0492fSopenharmony_ci ret = strcpy_s(serverAddr.sun_path, sizeof(serverAddr.sun_path), server); 60d9f0492fSopenharmony_ci LE_CHECK(ret == 0, close(listenfd); 61d9f0492fSopenharmony_ci return ret, "Failed to copy. error: %d", errno); 62d9f0492fSopenharmony_ci uint32_t size = offsetof(struct sockaddr_un, sun_path) + strlen(server); 63d9f0492fSopenharmony_ci ret = bind(listenfd, (struct sockaddr *)&serverAddr, size); 64d9f0492fSopenharmony_ci LE_CHECK(ret >= 0, close(listenfd); 65d9f0492fSopenharmony_ci return ret, "Failed to bind socket. error: %d", errno); 66d9f0492fSopenharmony_ci 67d9f0492fSopenharmony_ci SetNoBlock(listenfd); 68d9f0492fSopenharmony_ci ret = listen(listenfd, maxClient); 69d9f0492fSopenharmony_ci LE_CHECK(ret >= 0, close(listenfd); 70d9f0492fSopenharmony_ci return ret, "Failed to listen socket error: %d", errno); 71d9f0492fSopenharmony_ci mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; 72d9f0492fSopenharmony_ci if (public) { 73d9f0492fSopenharmony_ci mode |= S_IROTH | S_IWOTH; 74d9f0492fSopenharmony_ci } 75d9f0492fSopenharmony_ci ret = chmod(server, mode); 76d9f0492fSopenharmony_ci LE_CHECK(ret == 0, return -1, "Failed to chmod %s, err %d. ", server, errno); 77d9f0492fSopenharmony_ci LE_LOGV("CreatePipeSocket listen fd: %d server:%s ", listenfd, serverAddr.sun_path); 78d9f0492fSopenharmony_ci return listenfd; 79d9f0492fSopenharmony_ci} 80d9f0492fSopenharmony_ci 81d9f0492fSopenharmony_cistatic int CreatePipeSocket_(const char *server) 82d9f0492fSopenharmony_ci{ 83d9f0492fSopenharmony_ci int fd = socket(PF_UNIX, SOCK_STREAM, 0); 84d9f0492fSopenharmony_ci LE_CHECK(fd > 0, return fd, "Failed to create socket"); 85d9f0492fSopenharmony_ci SetNoBlock(fd); 86d9f0492fSopenharmony_ci 87d9f0492fSopenharmony_ci int on = 1; 88d9f0492fSopenharmony_ci int ret = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); 89d9f0492fSopenharmony_ci LE_CHECK(ret == 0, return ret, "Failed to set socket option"); 90d9f0492fSopenharmony_ci 91d9f0492fSopenharmony_ci ret = SetSocketTimeout(fd); 92d9f0492fSopenharmony_ci LE_CHECK(ret == 0, return ret, "Failed to set socket timeout"); 93d9f0492fSopenharmony_ci 94d9f0492fSopenharmony_ci struct sockaddr_un serverAddr; 95d9f0492fSopenharmony_ci ret = memset_s(&serverAddr, sizeof(serverAddr), 0, sizeof(serverAddr)); 96d9f0492fSopenharmony_ci LE_CHECK(ret == 0, close(fd); 97d9f0492fSopenharmony_ci return ret, "Failed to memset_s serverAddr"); 98d9f0492fSopenharmony_ci serverAddr.sun_family = AF_UNIX; 99d9f0492fSopenharmony_ci ret = strcpy_s(serverAddr.sun_path, sizeof(serverAddr.sun_path), server); 100d9f0492fSopenharmony_ci LE_CHECK(ret == 0, close(fd); 101d9f0492fSopenharmony_ci return ret, "Failed to strcpy_s sun_path"); 102d9f0492fSopenharmony_ci uint32_t size = offsetof(struct sockaddr_un, sun_path) + strlen(serverAddr.sun_path); 103d9f0492fSopenharmony_ci ret = connect(fd, (struct sockaddr *)&serverAddr, size); 104d9f0492fSopenharmony_ci LE_CHECK(ret >= 0, close(fd); 105d9f0492fSopenharmony_ci return ret, "Failed to connect socket"); 106d9f0492fSopenharmony_ci LE_LOGV("CreatePipeSocket connect fd: %d server: %s ", fd, serverAddr.sun_path); 107d9f0492fSopenharmony_ci return fd; 108d9f0492fSopenharmony_ci} 109d9f0492fSopenharmony_ci 110d9f0492fSopenharmony_cistatic LE_STATUS GetSockaddrFromServer_(const char *server, struct sockaddr_in *addr) 111d9f0492fSopenharmony_ci{ 112d9f0492fSopenharmony_ci int ret = memset_s(addr, sizeof(struct sockaddr_in), 0, sizeof(struct sockaddr_in)); 113d9f0492fSopenharmony_ci LE_CHECK(ret == 0, return ret, "Failed to memory set. error: %s", strerror(errno)); 114d9f0492fSopenharmony_ci addr->sin_family = AF_INET; 115d9f0492fSopenharmony_ci const char *portStr = strstr(server, ":"); 116d9f0492fSopenharmony_ci LE_CHECK(portStr != NULL, return LE_FAILURE, "Failed to get addr %s", server); 117d9f0492fSopenharmony_ci uint16_t port = atoi(portStr + 1); 118d9f0492fSopenharmony_ci addr->sin_port = htons(port); 119d9f0492fSopenharmony_ci ret = inet_pton(AF_INET, server, &addr->sin_addr); 120d9f0492fSopenharmony_ci LE_CHECK(ret >= 0, return LE_FAILURE, "Failed to inet_pton addr %s", server); 121d9f0492fSopenharmony_ci LE_LOGV("CreateTcpSocket server: %s port: %d", server, port); 122d9f0492fSopenharmony_ci return LE_SUCCESS; 123d9f0492fSopenharmony_ci} 124d9f0492fSopenharmony_ci 125d9f0492fSopenharmony_cistatic int CreateTcpServerSocket_(const char *server, int maxClient) 126d9f0492fSopenharmony_ci{ 127d9f0492fSopenharmony_ci int listenfd = socket(AF_INET, SOCK_STREAM, 0); 128d9f0492fSopenharmony_ci LE_CHECK(listenfd > 0, return listenfd, "Failed to create socket"); 129d9f0492fSopenharmony_ci 130d9f0492fSopenharmony_ci int ret = SetSocketTimeout(listenfd); 131d9f0492fSopenharmony_ci LE_CHECK(ret == 0, return ret, "Failed to set socket timeout"); 132d9f0492fSopenharmony_ci 133d9f0492fSopenharmony_ci struct sockaddr_in serverAddr; 134d9f0492fSopenharmony_ci GetSockaddrFromServer_(server, &serverAddr); 135d9f0492fSopenharmony_ci ret = bind(listenfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)); 136d9f0492fSopenharmony_ci LE_CHECK(ret >= 0, close(listenfd); 137d9f0492fSopenharmony_ci return ret, "Failed to bind socket"); 138d9f0492fSopenharmony_ci SetNoBlock(listenfd); 139d9f0492fSopenharmony_ci 140d9f0492fSopenharmony_ci ret = listen(listenfd, maxClient); 141d9f0492fSopenharmony_ci LE_CHECK(ret >= 0, close(listenfd); 142d9f0492fSopenharmony_ci return ret, "Failed to listen socket"); 143d9f0492fSopenharmony_ci return listenfd; 144d9f0492fSopenharmony_ci} 145d9f0492fSopenharmony_ci 146d9f0492fSopenharmony_cistatic int CreateTcpSocket_(const char *server) 147d9f0492fSopenharmony_ci{ 148d9f0492fSopenharmony_ci int fd = socket(AF_INET, SOCK_STREAM, 0); 149d9f0492fSopenharmony_ci LE_CHECK(fd > 0, return fd, "Failed to create socket"); 150d9f0492fSopenharmony_ci SetNoBlock(fd); 151d9f0492fSopenharmony_ci 152d9f0492fSopenharmony_ci int on = 1; 153d9f0492fSopenharmony_ci int ret = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); 154d9f0492fSopenharmony_ci LE_CHECK(ret == 0, return ret, "Failed to set socket option"); 155d9f0492fSopenharmony_ci 156d9f0492fSopenharmony_ci ret = SetSocketTimeout(fd); 157d9f0492fSopenharmony_ci LE_CHECK(ret == 0, return ret, "Failed to set socket timeout"); 158d9f0492fSopenharmony_ci 159d9f0492fSopenharmony_ci struct sockaddr_in serverAddr; 160d9f0492fSopenharmony_ci GetSockaddrFromServer_(server, &serverAddr); 161d9f0492fSopenharmony_ci ret = connect(fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)); 162d9f0492fSopenharmony_ci LE_CHECK(ret >= 0, close(fd); 163d9f0492fSopenharmony_ci return ret, "Failed to connect socket errno:%d", errno); 164d9f0492fSopenharmony_ci return fd; 165d9f0492fSopenharmony_ci} 166d9f0492fSopenharmony_ci 167d9f0492fSopenharmony_cistatic int AcceptPipeSocket_(int serverFd) 168d9f0492fSopenharmony_ci{ 169d9f0492fSopenharmony_ci struct sockaddr_un clientAddr; 170d9f0492fSopenharmony_ci socklen_t addrlen = sizeof(clientAddr); 171d9f0492fSopenharmony_ci bzero(&clientAddr, addrlen); 172d9f0492fSopenharmony_ci int fd = accept(serverFd, (struct sockaddr *)&clientAddr, &addrlen); 173d9f0492fSopenharmony_ci LE_CHECK(fd >= 0, return fd, "Failed to accept socket"); 174d9f0492fSopenharmony_ci LE_LOGV("AcceptPipeSocket client fd %d %s ", fd, clientAddr.sun_path); 175d9f0492fSopenharmony_ci return fd; 176d9f0492fSopenharmony_ci} 177d9f0492fSopenharmony_ci 178d9f0492fSopenharmony_cistatic int AcceptTcpSocket_(int serverFd) 179d9f0492fSopenharmony_ci{ 180d9f0492fSopenharmony_ci struct sockaddr_in clientAddr; 181d9f0492fSopenharmony_ci socklen_t addrlen = sizeof(clientAddr); 182d9f0492fSopenharmony_ci bzero(&clientAddr, addrlen); 183d9f0492fSopenharmony_ci int fd = accept(serverFd, (struct sockaddr *)&clientAddr, &addrlen); 184d9f0492fSopenharmony_ci LE_CHECK(fd >= 0, return fd, "Failed to accept socket"); 185d9f0492fSopenharmony_ci LE_LOGV("AcceptTcpSocket_ client: %s ", inet_ntoa(clientAddr.sin_addr)); 186d9f0492fSopenharmony_ci return fd; 187d9f0492fSopenharmony_ci} 188d9f0492fSopenharmony_ciINIT_LOCAL_API 189d9f0492fSopenharmony_ciint CreateSocket(int flags, const char *server) 190d9f0492fSopenharmony_ci{ 191d9f0492fSopenharmony_ci int fd = -1; 192d9f0492fSopenharmony_ci int type = flags & 0x0000ff00; 193d9f0492fSopenharmony_ci LE_LOGV("CreateSocket flags %x type %x server %s", flags, type, server); 194d9f0492fSopenharmony_ci if (type == TASK_TCP) { 195d9f0492fSopenharmony_ci if (LE_TEST_FLAGS(flags, TASK_SERVER)) { 196d9f0492fSopenharmony_ci fd = CreateTcpServerSocket_(server, LOOP_MAX_CLIENT); 197d9f0492fSopenharmony_ci } else if (LE_TEST_FLAGS(flags, TASK_CONNECT)) { 198d9f0492fSopenharmony_ci fd = CreateTcpSocket_(server); 199d9f0492fSopenharmony_ci } 200d9f0492fSopenharmony_ci } else if (type == TASK_PIPE) { 201d9f0492fSopenharmony_ci if (LE_TEST_FLAGS(flags, TASK_SERVER)) { 202d9f0492fSopenharmony_ci fd = CreatePipeServerSocket_(server, LOOP_MAX_CLIENT, 203d9f0492fSopenharmony_ci (int)LE_TEST_FLAGS(flags, TASK_PUBLIC)); 204d9f0492fSopenharmony_ci } else if (LE_TEST_FLAGS(flags, TASK_CONNECT)) { 205d9f0492fSopenharmony_ci fd = CreatePipeSocket_(server); 206d9f0492fSopenharmony_ci } 207d9f0492fSopenharmony_ci } 208d9f0492fSopenharmony_ci if (fd <= 0) { 209d9f0492fSopenharmony_ci LE_LOGE("Invalid flags 0x%08x for server %s", flags, server); 210d9f0492fSopenharmony_ci return -1; 211d9f0492fSopenharmony_ci } 212d9f0492fSopenharmony_ci return fd; 213d9f0492fSopenharmony_ci} 214d9f0492fSopenharmony_ciINIT_LOCAL_API 215d9f0492fSopenharmony_ciint AcceptSocket(int fd, int flags) 216d9f0492fSopenharmony_ci{ 217d9f0492fSopenharmony_ci int clientFd = -1; 218d9f0492fSopenharmony_ci int type = flags & 0x0000ff00; 219d9f0492fSopenharmony_ci if (type == TASK_TCP) { 220d9f0492fSopenharmony_ci clientFd = AcceptTcpSocket_(fd); 221d9f0492fSopenharmony_ci } else if (type == TASK_PIPE) { 222d9f0492fSopenharmony_ci clientFd = AcceptPipeSocket_(fd); 223d9f0492fSopenharmony_ci } else { 224d9f0492fSopenharmony_ci LE_LOGE("AcceptSocket invalid flags %#8x ", flags); 225d9f0492fSopenharmony_ci return -1; 226d9f0492fSopenharmony_ci } 227d9f0492fSopenharmony_ci SetNoBlock(clientFd); 228d9f0492fSopenharmony_ci return clientFd; 229d9f0492fSopenharmony_ci} 230d9f0492fSopenharmony_ci 231d9f0492fSopenharmony_ciINIT_LOCAL_API 232d9f0492fSopenharmony_ciint listenSocket(int fd, int flags, const char *server) 233d9f0492fSopenharmony_ci{ 234d9f0492fSopenharmony_ci unsigned int type = (unsigned int)flags & 0x0000ff00; 235d9f0492fSopenharmony_ci LE_LOGV("listenSocket flags %x type %x server %s", flags, type, server); 236d9f0492fSopenharmony_ci SetNoBlock(fd); 237d9f0492fSopenharmony_ci if (!LE_TEST_FLAGS((unsigned int)flags, TASK_SERVER)) { 238d9f0492fSopenharmony_ci return 0; 239d9f0492fSopenharmony_ci } 240d9f0492fSopenharmony_ci if (type == TASK_TCP) { 241d9f0492fSopenharmony_ci int ret = listen(fd, LOOP_MAX_CLIENT); 242d9f0492fSopenharmony_ci LE_CHECK(ret >= 0, close(fd); 243d9f0492fSopenharmony_ci return ret, "Failed to listen socket"); 244d9f0492fSopenharmony_ci } else if (type == TASK_PIPE) { 245d9f0492fSopenharmony_ci int ret = listen(fd, LOOP_MAX_CLIENT); 246d9f0492fSopenharmony_ci LE_CHECK(ret >= 0, close(fd); 247d9f0492fSopenharmony_ci return ret, "Failed to listen socket error: %d", errno); 248d9f0492fSopenharmony_ci ret = chmod(server, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); 249d9f0492fSopenharmony_ci LE_CHECK(ret == 0, return -1, "Failed to chmod %s, err %d. ", server, errno); 250d9f0492fSopenharmony_ci } 251d9f0492fSopenharmony_ci return 0; 252d9f0492fSopenharmony_ci} 253