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