1 /*
2 * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3 */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <errno.h>
9 #include "ulog/ulog.h"
10 #include "aos/kernel.h"
11 #include "aos_socket.h"
12 #include <netdb.h>
13 #include "aos_udp.h"
14 #include "aos_system.h"
15
16 #define TRANSPORT_ADDR_LEN 16
17
18 #ifndef IP_PKTINFO
19 #define IP_PKTINFO IP_MULTICAST_IF
20 #endif
21
22 #ifndef IPV6_PKTINFO
23 #define IPV6_PKTINFO IPV6_V6ONL
24 #endif
25
26 #define NETWORK_ADDR_LEN (16)
27
28 #define LOG_TAG "HAL_TL"
29
30 #define platform_info(format, ...) LOGI(LOG_TAG, format, ##__VA_ARGS__)
31 #define platform_err(format, ...) LOGE(LOG_TAG, format, ##__VA_ARGS__)
32
aos_udp_socket_create()33 int aos_udp_socket_create()
34 {
35 int rc = -1;
36 long socket_id = -1;
37
38 socket_id = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
39 if (socket_id < 0) {
40 aos_printf("create socket error");
41 return rc;
42 }
43
44 return socket_id;
45 }
46
aos_udp_socket_bind(int p_socket,unsigned short port)47 int aos_udp_socket_bind(int p_socket, unsigned short port)
48 {
49 struct sockaddr_in addr;
50 int opt_val = 1;
51
52 memset(&addr, 0, sizeof(struct sockaddr_in));
53
54 if (0 != setsockopt(p_socket, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof(opt_val))) {
55 aos_printf("setsockopt(SO_REUSEADDR) falied\n");
56 close(p_socket);
57 return -1;
58 }
59
60 addr.sin_addr.s_addr = htonl(INADDR_ANY);
61 addr.sin_family = AF_INET;
62 addr.sin_port = htons(port);
63
64 if (-1 == bind(p_socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in))) {
65 aos_printf("bind(%d) falied\n", (int)p_socket);
66 close(p_socket);
67 return -1;
68 }
69 aos_printf("success to establish udp, fd = %d", (int)p_socket);
70
71 return p_socket;
72 }
73
74 /**
75 * @brief Create a UDP socket.
76 *
77 * @param [in] port: @n Specify the UDP port of UDP socket
78 *
79 * @retval < 0 : Fail.
80 * @retval >= 0 : Success, the value is handle of this UDP socket.
81 * @see None.
82 */
aos_udp_create(char * host,unsigned short port)83 int aos_udp_create(char *host, unsigned short port)
84 {
85 int rc = -1;
86 long socket_id = -1;
87 char port_ptr[6] = {0};
88 struct addrinfo hints;
89 char addr[NETWORK_ADDR_LEN] = {0};
90 struct addrinfo *res, *ainfo;
91 struct sockaddr_in *sa = NULL;
92
93 if (NULL == host) {
94 return (-1);
95 }
96
97 sprintf(port_ptr, "%u", port);
98 memset((char *)&hints, 0x00, sizeof(hints));
99 hints.ai_socktype = SOCK_DGRAM;
100 hints.ai_family = AF_INET;
101 hints.ai_protocol = IPPROTO_UDP;
102
103 rc = getaddrinfo(host, port_ptr, &hints, &res);
104 if (0 != rc) {
105 platform_err("getaddrinfo error: %d", rc);
106 return (-1);
107 }
108
109 for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) {
110 if (AF_INET == ainfo->ai_family) {
111 sa = (struct sockaddr_in *)ainfo->ai_addr;
112 inet_ntop(AF_INET, &sa->sin_addr, addr, NETWORK_ADDR_LEN);
113
114 socket_id = socket(ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol);
115 if (socket_id < 0) {
116 platform_err("create socket error");
117 continue;
118 }
119 if (0 == connect(socket_id, ainfo->ai_addr, ainfo->ai_addrlen)) {
120 break;
121 }
122
123 close(socket_id);
124 }
125 }
126 freeaddrinfo(res);
127
128 return socket_id;
129 }
130
aos_udp_create_without_connect(const char * host,unsigned short port)131 int aos_udp_create_without_connect(const char *host, unsigned short port)
132 {
133 int flag = 1;
134 int ret = -1;
135 int socket_id = -1;
136 struct sockaddr_in local_addr; /*local addr*/
137
138 if ((socket_id = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
139 platform_err("socket create failed\r\n");
140 return (intptr_t)-1;
141 }
142
143 ret = setsockopt(socket_id, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
144 if (ret < 0) {
145 close(socket_id);
146 platform_err("setsockopt SO_REUSEADDR failed");
147 return (intptr_t)-1;
148 }
149
150 flag = 1;
151 #ifdef IP_RECVPKTINFO
152 if ((ret = setsockopt(socket_id, IPPROTO_IP, IP_RECVPKTINFO, &flag,
153 sizeof(flag))) < 0)
154 #else /* IP_RECVPKTINFO */
155 if ((ret = setsockopt(socket_id, IPPROTO_IP, IP_PKTINFO, &flag,
156 sizeof(flag))) < 0)
157 #endif /* IP_RECVPKTINFO */
158 if (ret < 0) {
159 close(socket_id);
160 platform_err("setsockopt IP_PKTINFO failed\r\n");
161 return (intptr_t)-1;
162 }
163
164
165 memset(&local_addr, 0x00, sizeof(local_addr));
166 local_addr.sin_family = AF_INET;
167 if (NULL != host) {
168 inet_aton(host, &local_addr.sin_addr);
169 } else {
170 local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
171 }
172 local_addr.sin_port = htons(port);
173 ret = bind(socket_id, (struct sockaddr *)&local_addr, sizeof(local_addr));
174
175 // faos_printf(stderr,"\r\n[%s LINE #%d] Create socket port %d fd %d ret
176 // %d\r\n",
177 // __FILE__, __LINE__, port, socket_id, ret);
178 return socket_id;
179 }
180
aos_udp_close_without_connect(int sockfd)181 int aos_udp_close_without_connect(int sockfd)
182 {
183 return close((int)sockfd);
184 }
185
aos_udp_recvfrom(int sockfd,aos_networkAddr * p_remote,unsigned char * p_data,unsigned int datalen,unsigned int timeout_ms)186 int aos_udp_recvfrom(int sockfd, aos_networkAddr *p_remote,
187 unsigned char *p_data, unsigned int datalen,
188 unsigned int timeout_ms)
189 {
190 int socket_id = -1;
191 struct sockaddr from;
192 int count = -1, ret = -1;
193 socklen_t addrlen = 0;
194 struct timeval tv;
195 fd_set read_fds;
196
197 if (NULL == p_remote || NULL == p_data) {
198 return -1;
199 }
200
201 socket_id = (int)sockfd;
202
203 FD_ZERO(&read_fds);
204 FD_SET(socket_id, &read_fds);
205
206 tv.tv_sec = timeout_ms / 1000;
207 tv.tv_usec = (timeout_ms % 1000) * 1000;
208
209 ret = select(socket_id + 1, &read_fds, NULL, NULL,
210 timeout_ms == 0 ? NULL : &tv);
211
212 /* Zero fds ready means we timed out */
213 if (ret == 0) {
214 return 0; /* receive timeout */
215 }
216
217 if (ret < 0) {
218 if (errno == EINTR) {
219 return -3; /* want read */
220 }
221
222 return -4; /* receive failed */
223 }
224
225 addrlen = sizeof(struct sockaddr);
226 count = recvfrom(socket_id, p_data, (size_t)datalen, 0, &from, &addrlen);
227 if (-1 == count) {
228 return -1;
229 }
230 if (from.sa_family == AF_INET) {
231 struct sockaddr_in *sin = (struct sockaddr_in *)&from;
232 inet_ntop(AF_INET, &sin->sin_addr, (char *)p_remote->addr,
233 NETWORK_ADDR_LEN);
234 p_remote->port = ntohs(sin->sin_port);
235 }
236 return count;
237 }
238
aos_udp_sendto(int sockfd,const aos_networkAddr * p_remote,const unsigned char * p_data,unsigned int datalen,unsigned int timeout_ms)239 int aos_udp_sendto(int sockfd, const aos_networkAddr *p_remote,
240 const unsigned char *p_data, unsigned int datalen,
241 unsigned int timeout_ms)
242 {
243 int rc = -1;
244 int socket_id = -1;
245 struct sockaddr_in remote_addr;
246
247 if (NULL == p_remote || NULL == p_data) {
248 return -1;
249 }
250
251 socket_id = (int)sockfd;
252 remote_addr.sin_family = AF_INET;
253 if (1 !=
254 (rc = inet_pton(remote_addr.sin_family, (const char *)p_remote->addr,
255 &remote_addr.sin_addr.s_addr))) {
256 return -1;
257 }
258 remote_addr.sin_port = htons(p_remote->port);
259 rc = sendto(socket_id, p_data, (size_t)datalen, 0,
260 (const struct sockaddr *)&remote_addr, sizeof(remote_addr));
261 if (-1 == rc) {
262 return -1;
263 }
264
265 return (rc) > 0 ? rc : -1;
266 }
267
aos_udp_joinmulticast(int sockfd,char * p_group)268 int aos_udp_joinmulticast(int sockfd, char *p_group)
269 {
270 int err = -1;
271 int socket_id = -1;
272
273 if (NULL == p_group) {
274 return -1;
275 }
276
277 /*set loopback*/
278 int loop = 1;
279 socket_id = (int)sockfd;
280 err =
281 setsockopt(socket_id, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));
282 if (err < 0) {
283 aos_printf("setsockopt():IP_MULTICAST_LOOP failed\r\n");
284 return err;
285 }
286
287 struct ip_mreq mreq;
288 mreq.imr_multiaddr.s_addr = inet_addr(p_group);
289 mreq.imr_interface.s_addr = htonl(INADDR_ANY); /*default networt interface*/
290
291 /*join to the mutilcast group*/
292 err =
293 setsockopt(socket_id, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
294 if (err < 0) {
295 aos_printf("setsockopt():IP_ADD_MEMBERSHIP failed\r\n");
296 return err;
297 }
298
299 return 0;
300 }
301
aos_udp_write(int p_socket,const unsigned char * p_data,unsigned int datalen)302 int aos_udp_write(int p_socket, const unsigned char *p_data,
303 unsigned int datalen)
304 {
305 int rc = -1;
306 long socket_id = -1;
307
308 socket_id = (long)p_socket;
309 rc = send(socket_id, (char *)p_data, (int)datalen, 0);
310 if (-1 == rc) {
311 return -1;
312 }
313
314 return rc;
315 }
316
317
aos_udp_read_timeout(int p_socket,unsigned char * p_data,unsigned int datalen,unsigned int timeout)318 int aos_udp_read_timeout(int p_socket, unsigned char *p_data,
319 unsigned int datalen, unsigned int timeout)
320 {
321 int ret;
322 struct timeval tv;
323 fd_set read_fds;
324 long socket_id = -1;
325
326 if (0 == p_socket || NULL == p_data) {
327 return -1;
328 }
329 socket_id = (long)p_socket;
330
331 if (socket_id < 0) {
332 return -1;
333 }
334
335 FD_ZERO(&read_fds);
336 FD_SET(socket_id, &read_fds);
337
338 tv.tv_sec = timeout / 1000;
339 tv.tv_usec = (timeout % 1000) * 1000;
340
341 ret =
342 select(socket_id + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv);
343
344 /* Zero fds ready means we timed out */
345 if (ret == 0) {
346 return -2; /* receive timeout */
347 }
348
349 if (ret < 0) {
350 if (errno == EINTR) {
351 return -3; /* want read */
352 }
353
354 return -4; /* receive failed */
355 }
356
357 /* This call will not block */
358 return read((long)p_socket, p_data, datalen);
359
360 }
361