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