1 /*
2  * Copyright (c) 2006-2024 RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2018-06-06     chenyong     first version
9  * 2022-06-02     xianxistu    add implement about "AT server"
10  */
11 
12 #include <at.h>
13 #ifdef AT_USING_SOCKET_SERVER
14 #include <stdio.h>
15 #endif
16 #include <stdlib.h>
17 #include <string.h>
18 #include <ctype.h>
19 #include <sys/time.h>
20 #include <sys/errno.h>
21 
22 #include <at_socket.h>
23 #include <at_device.h>
24 
25 #ifdef SAL_USING_POSIX
26 #include <poll.h>
27 #endif
28 
29 #include <arpa/inet.h>
30 #include <netdev.h>
31 
32 #define LOG_TAG              "at.skt"
33 #include <at_log.h>
34 
35 #ifdef AT_USING_SOCKET
36 
37 #define HTONS_PORT(x) ((((x) & 0x00ffUL) << 8) | (((x) & 0xff00UL) >> 8))
38 #define NIPQUAD(addr) \
39         ((unsigned char *)&addr)[0], \
40         ((unsigned char *)&addr)[1], \
41         ((unsigned char *)&addr)[2], \
42         ((unsigned char *)&addr)[3]
43 
44 /* The maximum number of sockets structure */
45 #ifndef AT_SOCKETS_NUM
46 #define AT_SOCKETS_NUM       AT_DEVICE_SOCKETS_NUM
47 #endif
48 
49 typedef enum {
50     AT_EVENT_SEND,
51     AT_EVENT_RECV,
52     AT_EVENT_ERROR,
53 } at_event_t;
54 
55 #ifdef AT_USING_SOCKET_SERVER
56 static void at_connect_notice_cb(struct at_socket *sock, at_socket_evt_t event, const char *buff, size_t bfsz);
57 #endif
58 
59 static rt_mutex_t at_slock = RT_NULL;
60 
61 /* the global of sockets list */
62 static rt_slist_t _socket_list = RT_SLIST_OBJECT_INIT(_socket_list);
63 
at_get_socket(int socket)64 struct at_socket *at_get_socket(int socket)
65 {
66     rt_base_t level;
67     rt_slist_t *node = RT_NULL;
68     struct at_socket *at_sock = RT_NULL;
69 
70     level = rt_hw_interrupt_disable();
71 
72     rt_slist_for_each(node, &_socket_list)
73     {
74         at_sock = rt_slist_entry(node, struct at_socket, list);
75         if (at_sock && socket == at_sock->socket)
76         {
77             if (at_sock->magic == AT_SOCKET_MAGIC)
78             {
79                 rt_hw_interrupt_enable(level);
80                 return at_sock;
81             }
82         }
83     }
84 
85     rt_hw_interrupt_enable(level);
86 
87     return RT_NULL;
88 }
89 
90 #ifdef AT_USING_SOCKET_SERVER
at_get_base_socket(int base_socket)91 struct at_socket *at_get_base_socket(int base_socket)
92 {
93     rt_base_t level;
94     rt_slist_t *node = RT_NULL;
95     struct at_socket *at_sock = RT_NULL;
96 
97     level = rt_hw_interrupt_disable();
98 
99     rt_slist_for_each(node, &_socket_list)
100     {
101         at_sock = rt_slist_entry(node, struct at_socket, list);
102         if (at_sock && base_socket == (int)at_sock->user_data && at_sock->state != AT_SOCKET_LISTEN)
103         {
104             if (at_sock->magic == AT_SOCKET_MAGIC)
105             {
106                 rt_hw_interrupt_enable(level);
107                 return at_sock;
108             }
109         }
110     }
111 
112     rt_hw_interrupt_enable(level);
113 
114     return RT_NULL;
115 }
116 #endif
117 
118 /* get a block to the AT socket receive list*/
at_recvpkt_put(rt_slist_t * rlist,const char * ptr,size_t length)119 static rt_err_t at_recvpkt_put(rt_slist_t *rlist, const char *ptr, size_t length)
120 {
121     at_recv_pkt_t pkt = RT_NULL;
122 
123     pkt = (at_recv_pkt_t) rt_calloc(1, sizeof(struct at_recv_pkt));
124     if (pkt == RT_NULL)
125     {
126         LOG_E("No memory for receive packet table!");
127         return -RT_ENOMEM;
128     }
129 
130     pkt->bfsz_totle = length;
131     pkt->bfsz_index = 0;
132     pkt->buff = (char *) ptr;
133 
134     rt_slist_append(rlist, &pkt->list);
135 
136     return RT_EOK;
137 }
138 
139 /* delete and free all receive buffer list */
at_recvpkt_all_delete(rt_slist_t * rlist)140 static int at_recvpkt_all_delete(rt_slist_t *rlist)
141 {
142     at_recv_pkt_t pkt = RT_NULL;
143     rt_slist_t *node = RT_NULL;
144 
145     if (rt_slist_isempty(rlist))
146     {
147         return 0;
148     }
149 
150     for(node = rt_slist_first(rlist); node;)
151     {
152         pkt = rt_slist_entry(node, struct at_recv_pkt, list);
153         node = rt_slist_next(node);
154         if (pkt && pkt->buff)
155         {
156             rt_free(pkt->buff);
157         }
158         if (pkt)
159         {
160             rt_free(pkt);
161             pkt = RT_NULL;
162         }
163     }
164 
165     return 0;
166 }
167 
168 /* delete and free specified list block */
at_recvpkt_node_delete(rt_slist_t * rlist,rt_slist_t * node)169 static int at_recvpkt_node_delete(rt_slist_t *rlist, rt_slist_t *node)
170 {
171     at_recv_pkt_t pkt = RT_NULL;
172 
173     if (rt_slist_isempty(rlist))
174     {
175         return 0;
176     }
177 
178     rt_slist_remove(rlist, node);
179 
180     pkt = rt_slist_entry(node, struct at_recv_pkt, list);
181     if (pkt && pkt->buff)
182     {
183         rt_free(pkt->buff);
184     }
185     if (pkt)
186     {
187         rt_free(pkt);
188         pkt = RT_NULL;
189     }
190 
191     return 0;
192 }
193 
194 /* get a block from AT socket receive buffer list */
at_recvpkt_get(rt_slist_t * rlist,char * mem,size_t len)195 static size_t at_recvpkt_get(rt_slist_t *rlist, char *mem, size_t len)
196 {
197     rt_slist_t *node = RT_NULL;
198     rt_slist_t *free_node = RT_NULL;
199     at_recv_pkt_t pkt = RT_NULL;
200     size_t content_pos = 0, page_pos = 0;
201 
202     if (rt_slist_isempty(rlist))
203     {
204         return 0;
205     }
206 
207     for (node = rt_slist_first(rlist); node;)
208     {
209         pkt = rt_slist_entry(node, struct at_recv_pkt, list);
210 
211         free_node = node;
212         node = rt_slist_next(node);
213 
214         if (!pkt) continue;
215 
216         page_pos = pkt->bfsz_totle - pkt->bfsz_index;
217 
218         if (page_pos >= len - content_pos)
219         {
220             rt_memcpy((char *) mem + content_pos, pkt->buff + pkt->bfsz_index, len - content_pos);
221             pkt->bfsz_index += len - content_pos;
222             if (pkt->bfsz_index == pkt->bfsz_totle)
223             {
224                 at_recvpkt_node_delete(rlist, free_node);
225             }
226             content_pos = len;
227             break;
228         }
229         else
230         {
231             rt_memcpy((char *) mem + content_pos, pkt->buff + pkt->bfsz_index, page_pos);
232             content_pos += page_pos;
233             pkt->bfsz_index += page_pos;
234             at_recvpkt_node_delete(rlist, free_node);
235         }
236     }
237 
238     return content_pos;
239 }
240 
at_do_event_changes(struct at_socket * sock,at_event_t event,rt_bool_t is_plus)241 static void at_do_event_changes(struct at_socket *sock, at_event_t event, rt_bool_t is_plus)
242 {
243     switch (event)
244     {
245     case AT_EVENT_SEND:
246     {
247         if (is_plus)
248         {
249             sock->sendevent = 1;
250 
251 #ifdef SAL_USING_POSIX
252             rt_wqueue_wakeup(&sock->wait_head, (void*) POLLOUT);
253 #endif
254         }
255         else if (sock->sendevent)
256         {
257             sock->sendevent = 0;
258         }
259         break;
260     }
261     case AT_EVENT_RECV:
262     {
263         if (is_plus)
264         {
265             sock->rcvevent++;
266 
267 #ifdef SAL_USING_POSIX
268             rt_wqueue_wakeup(&sock->wait_head, (void*) POLLIN);
269 #endif
270         }
271         else if (sock->rcvevent)
272         {
273             sock->rcvevent --;
274         }
275         break;
276     }
277     case AT_EVENT_ERROR:
278     {
279         if (is_plus)
280         {
281             sock->errevent++;
282 
283 #ifdef SAL_USING_POSIX
284             rt_wqueue_wakeup(&sock->wait_head, (void*) POLLERR);
285 #endif
286         }
287         else if (sock->errevent)
288         {
289             sock->errevent --;
290         }
291         break;
292     }
293     default:
294         LOG_E("Not supported event (%d)", event);
295     }
296 }
297 
at_do_event_clean(struct at_socket * sock,at_event_t event)298 static void at_do_event_clean(struct at_socket *sock, at_event_t event)
299 {
300     switch (event)
301     {
302     case AT_EVENT_SEND:
303     {
304         sock->sendevent = 0;
305         break;
306     }
307     case AT_EVENT_RECV:
308     {
309         sock->rcvevent = 0;
310         break;
311     }
312     case AT_EVENT_ERROR:
313     {
314         sock->errevent = 0;
315         break;
316     }
317     default:
318         LOG_E("Not supported event (%d)", event);
319     }
320 }
321 
free_socket(struct at_socket * sock)322 static int free_socket(struct at_socket *sock)
323 {
324     if (at_slock == RT_NULL)
325     {
326         /* create AT socket lock */
327         at_slock = rt_mutex_create("at_slock", RT_IPC_FLAG_PRIO);
328         if (at_slock == RT_NULL)
329         {
330             LOG_E("No memory for socket allocation lock!");
331             return RT_NULL;
332         }
333     }
334 
335     rt_mutex_take(at_slock, RT_WAITING_FOREVER);
336     if (sock->recv_notice)
337     {
338         rt_sem_delete(sock->recv_notice);
339     }
340 
341     if (sock->recv_lock)
342     {
343         rt_mutex_delete(sock->recv_lock);
344     }
345 
346     if (!rt_slist_isempty(&sock->recvpkt_list))
347     {
348         at_recvpkt_all_delete(&sock->recvpkt_list);
349     }
350 
351     /* delect socket from socket list */
352     {
353         rt_base_t level;
354         rt_slist_t *node = RT_NULL;
355         struct at_socket *at_sock = RT_NULL;
356 
357         level = rt_hw_interrupt_disable();
358 
359         rt_slist_for_each(node, &_socket_list)
360         {
361             at_sock = rt_slist_entry(node, struct at_socket, list);
362             if (at_sock && sock->socket == at_sock->socket)
363             {
364                 if (at_sock->magic == AT_SOCKET_MAGIC)
365                 {
366                     rt_slist_remove(&_socket_list, &at_sock->list);
367                     break;
368                 }
369             }
370         }
371 
372         rt_hw_interrupt_enable(level);
373     }
374 
375     rt_memset(sock, RT_NULL, sizeof(struct at_socket));
376     rt_mutex_release(at_slock);
377     return 0;
378 }
379 
alloc_socket_by_device(struct at_device * device,enum at_socket_type type)380 static struct at_socket *alloc_socket_by_device(struct at_device *device, enum at_socket_type type)
381 {
382     rt_base_t level;
383     struct at_socket *sock = RT_NULL;
384     char name[RT_NAME_MAX] = {0};
385     int idx = 0;
386 
387     if (at_slock == RT_NULL)
388     {
389         /* create AT socket lock */
390         at_slock = rt_mutex_create("at_slock", RT_IPC_FLAG_PRIO);
391         if (at_slock == RT_NULL)
392         {
393             LOG_E("No memory for socket allocation lock!");
394             return RT_NULL;
395         }
396     }
397 
398     rt_mutex_take(at_slock, RT_WAITING_FOREVER);
399 
400     /* find an empty at socket entry */
401     if (device->class->socket_ops->at_socket != RT_NULL)
402     {
403         idx = device->class->socket_ops->at_socket(device, type);
404     }
405     else
406     {
407         for (idx = 0; idx < device->class->socket_num && device->sockets[idx].magic == AT_SOCKET_MAGIC; idx++);
408     }
409 
410     /* can't find an empty protocol family entry */
411     if (idx < 0 || idx >= device->class->socket_num)
412     {
413         LOG_E("can't find an empty protocol family entry.");
414         goto __err;
415     }
416 
417     sock = &(device->sockets[idx]);
418     /* the socket descriptor is the number of sockte lists */
419     sock->socket = idx;
420     /* the socket operations is the specify operations of the device */
421     sock->ops = device->class->socket_ops;
422     /* the user-data is the at device socket descriptor */
423     sock->user_data = (void *) idx;
424     sock->device = (void *) device;
425     sock->magic = AT_SOCKET_MAGIC;
426     sock->state = AT_SOCKET_NONE;
427     sock->rcvevent = RT_NULL;
428     sock->sendevent = RT_NULL;
429     sock->errevent = RT_NULL;
430 
431     rt_slist_init(&(sock->list));
432     level = rt_hw_interrupt_disable();
433     rt_slist_insert(&_socket_list, &(sock->list));
434     rt_hw_interrupt_enable(level);
435 
436     rt_slist_init(&sock->recvpkt_list);
437 #ifdef SAL_USING_POSIX
438     rt_wqueue_init(&sock->wait_head);
439 #endif
440 
441     rt_snprintf(name, RT_NAME_MAX, "%s%d", "at_skt", idx);
442     /* create AT socket receive semaphore */
443     if ((sock->recv_notice = rt_sem_create(name, 0, RT_IPC_FLAG_FIFO)) == RT_NULL)
444     {
445         LOG_E("No memory socket receive notic semaphore create.");
446         goto __err;
447     }
448     /* set AT socket receive semaphore 'max_value' to 1 */
449     rt_sem_control(sock->recv_notice, RT_IPC_CMD_SET_VLIMIT, (void *)1);
450 
451     rt_snprintf(name, RT_NAME_MAX, "%s%d", "at_skt", idx);
452     /* create AT socket receive ring buffer lock */
453     if((sock->recv_lock = rt_mutex_create(name, RT_IPC_FLAG_PRIO)) == RT_NULL)
454     {
455         LOG_E("No memory for socket receive mutex create.");
456         goto __err;
457     }
458 
459     rt_mutex_release(at_slock);
460     return sock;
461 
462 __err:
463     rt_mutex_release(at_slock);
464     if(sock != RT_NULL)
465     {
466         free_socket(sock);
467     }
468     return RT_NULL;
469 }
470 
alloc_socket(enum at_socket_type type)471 static struct at_socket *alloc_socket(enum at_socket_type type)
472 {
473     extern struct netdev *netdev_default;
474     struct netdev *netdev = RT_NULL;
475     struct at_device *device = RT_NULL;
476 
477     if (netdev_default && netdev_is_up(netdev_default) &&
478             netdev_family_get(netdev_default) == AF_AT)
479     {
480         netdev = netdev_default;
481     }
482     else
483     {
484         /* get network interface device by protocol family AF_AT */
485         netdev = netdev_get_by_family(AF_AT);
486         if (netdev == RT_NULL)
487         {
488             return RT_NULL;
489         }
490     }
491 
492     device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
493     if (device == RT_NULL)
494     {
495         return RT_NULL;
496     }
497 
498     return alloc_socket_by_device(device, type);
499 }
500 
501 static void at_recv_notice_cb(struct at_socket *sock, at_socket_evt_t event, const char *buff, size_t bfsz);
502 static void at_closed_notice_cb(struct at_socket *sock, at_socket_evt_t event, const char *buff, size_t bfsz);
503 
at_socket(int domain,int type,int protocol)504 int at_socket(int domain, int type, int protocol)
505 {
506     struct at_socket *sock = RT_NULL;
507     enum at_socket_type socket_type;
508 
509     /* check socket family protocol */
510     if(domain != AF_INET && domain != AF_AT)
511     {
512         rt_set_errno(EAFNOSUPPORT);
513         return -1;
514     }
515 
516     /*TODO check protocol*/
517 
518     switch(type)
519     {
520     case SOCK_STREAM:
521         socket_type = AT_SOCKET_TCP;
522         break;
523 
524     case SOCK_DGRAM:
525         socket_type = AT_SOCKET_UDP;
526         break;
527 
528     default :
529         LOG_E("Don't support socket type (%d)!", type);
530         rt_set_errno(EPROTOTYPE);
531         return -1;
532     }
533 
534     /* allocate and initialize a new AT socket */
535     sock = alloc_socket(socket_type);
536     if (sock == RT_NULL)
537     {
538         LOG_E("Failed to allocate socket");
539         rt_set_errno(EIO);
540         return -1;
541     }
542     sock->type = socket_type;
543     sock->state = AT_SOCKET_OPEN;
544 
545     /* set AT socket receive data callback function */
546     sock->ops->at_set_event_cb(AT_SOCKET_EVT_RECV, at_recv_notice_cb);
547     sock->ops->at_set_event_cb(AT_SOCKET_EVT_CLOSED, at_closed_notice_cb);
548 #ifdef AT_USING_SOCKET_SERVER
549     sock->ops->at_set_event_cb(AT_SOCKET_EVT_CONNECTED, at_connect_notice_cb);
550 #endif
551 
552     return sock->socket;
553 }
554 
at_closesocket(int socket)555 int at_closesocket(int socket)
556 {
557     struct at_socket *sock = RT_NULL;
558     enum at_socket_state last_state;
559 
560     /* deal with TCP server actively disconnect */
561     rt_thread_delay(rt_tick_from_millisecond(100));
562 
563     sock = at_get_socket(socket);
564     if (sock == RT_NULL)
565     {
566         rt_set_errno(ENXIO);
567         return -1;
568     }
569 
570     last_state = sock->state;
571 
572     /* the rt_at_socket_close is need some time, so change state in advance */
573     sock->state = AT_SOCKET_CLOSED;
574 
575     if (last_state != AT_SOCKET_CLOSED)
576     {
577         if (sock->ops->at_closesocket(sock) != 0)
578         {
579             free_socket(sock);
580             rt_set_errno(EIO);
581             return -1;
582         }
583     }
584 
585     free_socket(sock);
586     return 0;
587 }
588 
at_shutdown(int socket,int how)589 int at_shutdown(int socket, int how)
590 {
591     struct at_socket *sock = RT_NULL;
592     enum at_socket_state last_state;
593 
594     sock = at_get_socket(socket);
595     if (sock == RT_NULL)
596     {
597         rt_set_errno(ENXIO);
598         return -1;
599     }
600 
601     last_state = sock->state;
602 
603     /* the rt_at_socket_close is need some time, so change state in advance */
604     sock->state = AT_SOCKET_CLOSED;
605 
606     if (last_state != AT_SOCKET_CLOSED)
607     {
608         if (sock->ops->at_closesocket(sock) != 0)
609         {
610             free_socket(sock);
611             rt_set_errno(EIO);
612             return -1;
613         }
614     }
615 
616     free_socket(sock);
617     return 0;
618 }
619 
620 /* get IP address and port by socketaddr structure information */
socketaddr_to_ipaddr_port(const struct sockaddr * sockaddr,ip_addr_t * addr,uint16_t * port)621 static int socketaddr_to_ipaddr_port(const struct sockaddr *sockaddr, ip_addr_t *addr, uint16_t *port)
622 {
623     const struct sockaddr_in* sin = (const struct sockaddr_in*) (const void *) sockaddr;
624 
625 #if NETDEV_IPV4 && NETDEV_IPV6
626     addr->u_addr.ip4.addr = sin->sin_addr.s_addr;
627     addr->type = IPADDR_TYPE_V4;
628 #elif NETDEV_IPV4
629     addr->addr = sin->sin_addr.s_addr;
630 #elif NETDEV_IPV6
631 #error "not support IPV6."
632 #endif /* NETDEV_IPV4 && NETDEV_IPV6 */
633 
634     *port = (uint16_t) HTONS_PORT(sin->sin_port);
635 
636     return 0;
637 }
638 
639 #ifdef AT_USING_SOCKET_SERVER
640 /* set socketaddr structure information by IP address and port */
ipaddr_port_to_socketaddr(struct sockaddr * sockaddr,ip_addr_t * addr,uint16_t * port)641 static int ipaddr_port_to_socketaddr(struct sockaddr *sockaddr, ip_addr_t *addr, uint16_t *port)
642 {
643     struct sockaddr_in* sin = (struct sockaddr_in*) (void *) sockaddr;
644 
645 #if NETDEV_IPV4 && NETDEV_IPV6
646     sin->sin_addr.s_addr = addr->u_addr.ip4.addr;
647 #elif NETDEV_IPV4
648     sin->sin_addr.s_addr = addr->addr;
649 #elif NETDEV_IPV6
650 #error "not support IPV6."
651 #endif /* NETDEV_IPV4 && NETDEV_IPV6 */
652 
653     sin->sin_port = (uint16_t) HTONS_PORT(*port);
654 
655     return 0;
656 }
657 #endif
658 
at_bind(int socket,const struct sockaddr * name,socklen_t namelen)659 int at_bind(int socket, const struct sockaddr *name, socklen_t namelen)
660 {
661     struct at_socket *sock = RT_NULL;
662     struct at_device *device = RT_NULL;
663     ip_addr_t input_ipaddr, local_ipaddr;
664     uint16_t port = 0;
665 
666     if (name == NULL || namelen == 0)
667     {
668         rt_set_errno(EINVAL);
669         return -1;
670     }
671 
672     sock = at_get_socket(socket);
673     if (sock == RT_NULL)
674     {
675         rt_set_errno(ENXIO);
676         return -1;
677     }
678 
679     /* get current device ip address */
680     device = (struct at_device *) sock->device;
681     ip_addr_copy(local_ipaddr, device->netdev->ip_addr);
682 
683     /* prase ip address and port from sockaddr structure */
684     socketaddr_to_ipaddr_port(name, &input_ipaddr, &port);
685 
686     /* input ip address is different from device ip address */
687     if (ip_addr_cmp(&input_ipaddr, &local_ipaddr) != 0)
688     {
689         struct at_socket *new_sock = RT_NULL;
690         struct at_device *new_device = RT_NULL;
691         enum at_socket_type type = sock->type;
692 
693         /* close old socket */
694         if (at_closesocket(socket) < 0)
695         {
696             free_socket(sock);
697             rt_set_errno(EIO);
698             return -1;
699         }
700 
701         extern struct at_device *at_device_get_by_ipaddr(ip_addr_t *ip_addr);
702         new_device = at_device_get_by_ipaddr(&input_ipaddr);
703         if (new_device == RT_NULL)
704         {
705             rt_set_errno(EHOSTUNREACH);
706             return -1;
707         }
708 
709         /* allocate new socket */
710         new_sock = alloc_socket_by_device(new_device, type);
711         if (new_sock == RT_NULL)
712         {
713             rt_set_errno(EIO);
714             return -1;
715         }
716         new_sock->type = type;
717         new_sock->state = AT_SOCKET_OPEN;
718     }
719 
720 #ifdef AT_USING_SOCKET_SERVER
721     /* store 'port' into at_socket */
722     sock->listen.port = port;
723 #endif
724 
725     return 0;
726 }
727 
728 /* ipaddr structure change to IP address */
ipaddr_to_ipstr(const struct sockaddr * sockaddr,char * ipstr)729 static int ipaddr_to_ipstr(const struct sockaddr *sockaddr, char *ipstr)
730 {
731     struct sockaddr_in *sin = (struct sockaddr_in *) sockaddr;
732 
733     /* change network ip_addr to ip string  */
734     rt_snprintf(ipstr, 16, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr));
735 
736     return 0;
737 }
738 
739 #ifdef AT_USING_SOCKET_SERVER
at_connect_notice_cb(struct at_socket * sock,at_socket_evt_t event,const char * buff,size_t bfsz)740 static void at_connect_notice_cb(struct at_socket *sock, at_socket_evt_t event, const char *buff, size_t bfsz)
741 {
742     RT_ASSERT(buff);
743     RT_ASSERT(sock == RT_NULL);
744     RT_ASSERT(event == AT_SOCKET_EVT_CONNECTED);
745 
746     int new_socket;
747     struct at_socket *new_sock = RT_NULL;
748     rt_base_t level;
749     rt_slist_t *node = RT_NULL;
750     struct at_socket *at_sock = RT_NULL;
751     char *socket_info = RT_NULL;
752     int base_socket = 0;
753 
754     /* avoid use bottom driver to alloc "socket" */
755     new_socket = at_socket(AF_AT, SOCK_STREAM, 0);
756     if (new_socket == -1)
757     {
758         return;
759     }
760     new_sock = at_get_socket(new_socket);
761     new_sock->state = AT_SOCKET_CONNECT;
762     rt_sscanf(buff, "SOCKET:%d", &base_socket);
763     LOG_D("ACCEPT BASE SOCKET: %d", base_socket);
764     new_sock->user_data = (void *)base_socket;
765 
766     /* find out the listen socket */
767     level = rt_hw_interrupt_disable();
768     rt_slist_for_each(node, &_socket_list)
769     {
770         at_sock = rt_slist_entry(node, struct at_socket, list);
771         if (at_sock && at_sock->magic == AT_SOCKET_MAGIC && at_sock->listen.is_listen == RT_TRUE)
772         {
773             break;
774         }
775         at_sock = RT_NULL;
776     }
777     rt_hw_interrupt_enable(level);
778 
779     if (at_sock == RT_NULL)
780     {
781         at_closesocket(new_socket);
782         return;
783     }
784 
785     /* put incoming "socket" to the listen socket receiver packet list */
786     socket_info = rt_malloc(AT_SOCKET_INFO_LEN);
787     rt_memset(socket_info, 0, AT_SOCKET_INFO_LEN);
788     rt_sprintf(socket_info, "SOCKET:%d", new_sock->socket);
789 
790     /* wakeup the "accept" function */
791     rt_mutex_take(at_sock->recv_lock, RT_WAITING_FOREVER);
792     if (at_recvpkt_put(&(at_sock->recvpkt_list), socket_info, AT_SOCKET_INFO_LEN) != RT_EOK)
793     {
794         at_closesocket(new_socket);
795         rt_free(socket_info);
796         rt_mutex_release(at_sock->recv_lock);
797         return;
798     }
799     rt_mutex_release(at_sock->recv_lock);
800     rt_sem_release(at_sock->recv_notice);
801 
802     at_do_event_changes(at_sock, AT_EVENT_RECV, RT_TRUE);
803 }
804 #endif
805 
at_recv_notice_cb(struct at_socket * sock,at_socket_evt_t event,const char * buff,size_t bfsz)806 static void at_recv_notice_cb(struct at_socket *sock, at_socket_evt_t event, const char *buff, size_t bfsz)
807 {
808     RT_ASSERT(buff);
809     RT_ASSERT(event == AT_SOCKET_EVT_RECV);
810 
811     /* check the socket object status */
812     if (sock->magic != AT_SOCKET_MAGIC || sock->state == AT_SOCKET_CLOSED)
813     {
814         rt_free((void *)buff);
815         return;
816     }
817 
818     /* put receive buffer to receiver packet list */
819     rt_mutex_take(sock->recv_lock, RT_WAITING_FOREVER);
820     if (at_recvpkt_put(&(sock->recvpkt_list), buff, bfsz) != RT_EOK)
821     {
822         rt_free((void *)buff);
823         rt_mutex_release(sock->recv_lock);
824         return;
825     }
826     rt_mutex_release(sock->recv_lock);
827 
828     rt_sem_release(sock->recv_notice);
829 
830     at_do_event_changes(sock, AT_EVENT_RECV, RT_TRUE);
831 }
832 
at_closed_notice_cb(struct at_socket * sock,at_socket_evt_t event,const char * buff,size_t bfsz)833 static void at_closed_notice_cb(struct at_socket *sock, at_socket_evt_t event, const char *buff, size_t bfsz)
834 {
835     RT_ASSERT(event == AT_SOCKET_EVT_CLOSED);
836 
837     /* check the socket object status */
838     if (sock->magic != AT_SOCKET_MAGIC)
839     {
840         return;
841     }
842 
843     at_do_event_changes(sock, AT_EVENT_RECV, RT_TRUE);
844     at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
845 
846     sock->state = AT_SOCKET_CLOSED;
847     rt_sem_release(sock->recv_notice);
848 }
849 
850 #ifdef AT_USING_SOCKET_SERVER
at_listen(int socket,int backlog)851 int at_listen(int socket, int backlog)
852 {
853     struct at_socket *sock = RT_NULL;
854     int result = 0;
855 
856     sock = at_get_socket(socket);
857     if (sock == RT_NULL)
858     {
859         rt_set_errno(ENXIO);
860         return -1;
861     }
862 
863     if (sock->state != AT_SOCKET_OPEN)
864     {
865         LOG_E("Socket(%d) connect state is %d.", sock->socket, sock->state);
866         rt_set_errno(ENETUNREACH);
867         result = -1;
868         goto __exit;
869     }
870 
871     if (sock->ops->at_listen(sock, backlog) < 0)
872     {
873         rt_set_errno(EIO);
874         result = -1;
875         goto __exit;
876     }
877 
878     sock->listen.is_listen = RT_TRUE;
879     sock->state = AT_SOCKET_LISTEN;
880 
881 __exit:
882     if (result < 0)
883     {
884         at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
885     }
886 
887     return result;
888 }
889 #endif
890 
at_connect(int socket,const struct sockaddr * name,socklen_t namelen)891 int at_connect(int socket, const struct sockaddr *name, socklen_t namelen)
892 {
893     struct at_socket *sock = RT_NULL;
894     ip_addr_t remote_addr;
895     uint16_t remote_port = 0;
896     char ipstr[16] = { 0 };
897     int result = 0;
898 
899     if (name == RT_NULL || namelen == 0)
900     {
901         rt_set_errno(EINVAL);
902         return -1;
903     }
904 
905     sock = at_get_socket(socket);
906     if (sock == RT_NULL)
907     {
908         rt_set_errno(ENXIO);
909         return -1;
910     }
911 
912     if (sock->state != AT_SOCKET_OPEN)
913     {
914         LOG_E("Socket(%d) connect state is %d.", sock->socket, sock->state);
915         rt_set_errno(EPERM);
916         result = -1;
917         goto __exit;
918     }
919 
920     /* get IP address and port by socketaddr structure */
921     socketaddr_to_ipaddr_port(name, &remote_addr, &remote_port);
922     ipaddr_to_ipstr(name, ipstr);
923 
924     if (sock->ops->at_connect(sock, ipstr, remote_port, sock->type, RT_TRUE) < 0)
925     {
926         rt_set_errno(EIO);
927         result = -1;
928         goto __exit;
929     }
930 
931     sock->state = AT_SOCKET_CONNECT;
932 
933 __exit:
934     if (result < 0)
935     {
936         at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
937     }
938     else
939     {
940         at_do_event_changes(sock, AT_EVENT_SEND, RT_TRUE);
941     }
942 
943     return result;
944 }
945 
946 #ifdef AT_USING_SOCKET_SERVER
at_accept(int socket,struct sockaddr * name,socklen_t * namelen)947 int at_accept(int socket, struct sockaddr *name, socklen_t *namelen)
948 {
949     struct at_socket *sock = RT_NULL;
950     struct at_socket *new_sock = RT_NULL;
951     char receive_buff[AT_SOCKET_INFO_LEN];
952     ip_addr_t remote_addr;
953     uint16_t remote_port = 0;
954     int new_socket = -1;
955     int result = 0;
956 
957     sock = at_get_socket(socket);
958     if (sock == RT_NULL)
959     {
960         rt_set_errno(ENXIO);
961         return -1;
962     }
963 
964     if (sock->state != AT_SOCKET_LISTEN)
965     {
966         LOG_E("Socket(%d) connect state is %d.", sock->socket, sock->state);
967         rt_set_errno(EIO);
968         result = -1;
969         goto __exit;
970     }
971 
972     /* wait the receive semaphore, waiting for info */
973     if (rt_sem_take(sock->recv_notice, RT_WAITING_FOREVER) != RT_EOK)
974     {
975         rt_set_errno(EAGAIN);
976         result = -1;
977         goto __exit;
978     }
979     else
980     {
981         /* get receive buffer to receiver ring buffer */
982         rt_mutex_take(sock->recv_lock, RT_WAITING_FOREVER);
983         at_recvpkt_get(&(sock->recvpkt_list), (char *) &receive_buff, AT_SOCKET_INFO_LEN);
984         rt_mutex_release(sock->recv_lock);
985         at_do_event_changes(sock, AT_EVENT_RECV, RT_FALSE);
986     }
987 
988     rt_sscanf(&receive_buff[0], "SOCKET:%d", &new_socket);
989     new_sock = at_get_socket(new_socket);
990     ip4_addr_set_any(&remote_addr);
991     ipaddr_port_to_socketaddr(name, &remote_addr, &remote_port);
992     LOG_D("Accept: [socket :%d, base_socket:%d]", new_socket, (int)new_sock->user_data);
993 
994 __exit:
995     if (result < 0)
996     {
997         at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
998     }
999 
1000     return new_sock->socket;
1001 }
1002 #endif
1003 
at_recvfrom(int socket,void * mem,size_t len,int flags,struct sockaddr * from,socklen_t * fromlen)1004 int at_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1005 {
1006     struct at_socket *sock = RT_NULL;
1007     int timeout, result = 0;
1008     size_t recv_len = 0;
1009 
1010     if (mem == RT_NULL || len == 0)
1011     {
1012         /* if the requested number of bytes to receive from a stream socket was 0. */
1013         rt_set_errno(EFAULT);
1014         return -1;
1015     }
1016 
1017     sock = at_get_socket(socket);
1018     if (sock == RT_NULL)
1019     {
1020         rt_set_errno(ENXIO);
1021         return -1;
1022     }
1023 
1024     /* if the socket type is UDP, need to connect socket first */
1025     if (sock->type == AT_SOCKET_UDP)
1026     {
1027         if (from == RT_NULL || fromlen == 0)
1028         {
1029             rt_set_errno(EFAULT);
1030             return -1;
1031         }
1032 
1033         if(sock->state == AT_SOCKET_CONNECT && rt_memcmp(&sock->last_udp_adr, from, sizeof(struct sockaddr)) != 0)
1034         {
1035             if (sock->ops->at_closesocket(sock) != 0)
1036             {
1037                 free_socket(sock);
1038                 rt_set_errno(EIO);
1039                 goto __exit;
1040             }
1041             sock->state = AT_SOCKET_OPEN;
1042         }
1043 
1044         if (sock->state == AT_SOCKET_OPEN)
1045         {
1046             ip_addr_t remote_addr;
1047             uint16_t remote_port = 0;
1048             char ipstr[16] = { 0 };
1049 
1050             socketaddr_to_ipaddr_port(from, &remote_addr, &remote_port);
1051             ipaddr_to_ipstr(from, ipstr);
1052 
1053             if (sock->ops->at_connect(sock, ipstr, remote_port, sock->type, RT_TRUE) < 0)
1054             {
1055                 at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
1056                 rt_set_errno(EIO);
1057                 /* socket shutdown */
1058                 goto __exit;
1059             }
1060 
1061             rt_memcpy(&sock->last_udp_adr, from, sizeof(struct sockaddr));
1062             sock->state = AT_SOCKET_CONNECT;
1063         }
1064     }
1065 
1066     while (1)
1067     {
1068         /* receive packet list last transmission of remaining data */
1069         rt_mutex_take(sock->recv_lock, RT_WAITING_FOREVER);
1070         recv_len = at_recvpkt_get(&(sock->recvpkt_list), (char *)mem, len);
1071         rt_mutex_release(sock->recv_lock);
1072         if (recv_len > 0)
1073         {
1074             if (rt_slist_isempty(&sock->recvpkt_list))
1075             {
1076                 at_do_event_clean(sock, AT_EVENT_RECV);
1077             }
1078             result = recv_len;
1079             goto __exit;
1080         }
1081 
1082         if (sock->state == AT_SOCKET_CLOSED)
1083         {
1084             /* socket passively closed, receive function return 0 */
1085             result = 0;
1086             goto __exit;
1087         }
1088 
1089         if (flags & MSG_DONTWAIT)
1090         {
1091             rt_set_errno(EAGAIN);
1092             result = -1;
1093             goto __exit;
1094         }
1095 
1096         /* set AT socket receive timeout */
1097         if (sock->recv_timeout == 0)
1098         {
1099             timeout = RT_WAITING_FOREVER;
1100         }
1101         else
1102         {
1103             timeout = rt_tick_from_millisecond(sock->recv_timeout);
1104         }
1105         if (rt_sem_take(sock->recv_notice, timeout) != RT_EOK)
1106         {
1107             LOG_D("AT socket (%d) receive timeout (%d)!", socket, timeout);
1108             rt_set_errno(EAGAIN);
1109             result = -1;
1110             goto __exit;
1111         }
1112     }
1113 
1114 __exit:
1115     if (result <= 0)
1116     {
1117         at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
1118     }
1119 
1120     return result;
1121 }
1122 
at_recv(int s,void * mem,size_t len,int flags)1123 int at_recv(int s, void *mem, size_t len, int flags)
1124 {
1125     return at_recvfrom(s, mem, len, flags, RT_NULL, RT_NULL);
1126 }
1127 
at_sendto(int socket,const void * data,size_t size,int flags,const struct sockaddr * to,socklen_t tolen)1128 int at_sendto(int socket, const void *data, size_t size, int flags, const struct sockaddr *to, socklen_t tolen)
1129 {
1130     struct at_socket *sock = RT_NULL;
1131     int len = 0, result = 0;
1132 
1133     if (data == RT_NULL || size == 0)
1134     {
1135         LOG_E("AT sendto input data or size error!");
1136         rt_set_errno(EFAULT);
1137         return -1;
1138     }
1139 
1140     sock = at_get_socket(socket);
1141     if (sock == RT_NULL)
1142     {
1143         rt_set_errno(ENXIO);
1144         return -1;
1145     }
1146 
1147     switch (sock->type)
1148     {
1149     case AT_SOCKET_TCP:
1150         if (sock->state == AT_SOCKET_CLOSED)
1151         {
1152             /* socket passively closed, transmit function return 0 */
1153             result = 0;
1154             goto __exit;
1155         }
1156         else if (sock->state != AT_SOCKET_CONNECT)
1157         {
1158             LOG_E("send data error, current socket (%d) state (%d) is error.", socket, sock->state);
1159             rt_set_errno(ENETUNREACH);
1160             result = -1;
1161             goto __exit;
1162         }
1163 
1164         if ((len = sock->ops->at_send(sock, (const char *) data, size, sock->type)) < 0)
1165         {
1166             rt_set_errno(EIO);
1167             result = -1;
1168             goto __exit;
1169         }
1170         break;
1171 
1172     case AT_SOCKET_UDP:
1173         if (to == RT_NULL || tolen == 0)
1174         {
1175             rt_set_errno(EFAULT);
1176             result = -1;
1177             goto __exit;
1178         }
1179 
1180         /* Inconsistent with the last UDP sending address, reconnect to a new address */
1181         if(sock->state == AT_SOCKET_CONNECT && rt_memcmp(&sock->last_udp_adr, to, sizeof(struct sockaddr)) != 0)
1182         {
1183             if (sock->ops->at_closesocket(sock) != 0)
1184             {
1185                 free_socket(sock);
1186                 rt_set_errno(EIO);
1187                 goto __exit;
1188             }
1189             sock->state = AT_SOCKET_OPEN;
1190         }
1191 
1192         if (sock->state == AT_SOCKET_OPEN)
1193         {
1194             ip_addr_t remote_addr;
1195             uint16_t remote_port = 0;
1196             char ipstr[16] = { 0 };
1197 
1198             socketaddr_to_ipaddr_port(to, &remote_addr, &remote_port);
1199             ipaddr_to_ipstr(to, ipstr);
1200 
1201             if (sock->ops->at_connect(sock, ipstr, remote_port, sock->type, RT_TRUE) < 0)
1202             {
1203                 rt_set_errno(EIO);
1204                 result = -1;
1205                 goto __exit;
1206             }
1207 
1208             rt_memcpy(&sock->last_udp_adr, to, sizeof(struct sockaddr));
1209             sock->state = AT_SOCKET_CONNECT;
1210         }
1211 
1212         if ((len = sock->ops->at_send(sock, (char *) data, size, sock->type)) < 0)
1213         {
1214             rt_set_errno(EIO);
1215             result = -1;
1216             goto __exit;
1217         }
1218         break;
1219 
1220     default:
1221         LOG_E("Socket (%d) type %d is not support.", socket, sock->type);
1222         rt_set_errno(EPERM);
1223         result = -1;
1224         goto __exit;
1225     }
1226 
1227 __exit:
1228     if (result < 0)
1229     {
1230         at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
1231     }
1232     else
1233     {
1234         result = len;
1235     }
1236 
1237     return result;
1238 }
1239 
at_send(int socket,const void * data,size_t size,int flags)1240 int at_send(int socket, const void *data, size_t size, int flags)
1241 {
1242     return at_sendto(socket, data, size, flags, RT_NULL, 0);
1243 }
1244 
at_getsockopt(int socket,int level,int optname,void * optval,socklen_t * optlen)1245 int at_getsockopt(int socket, int level, int optname, void *optval, socklen_t *optlen)
1246 {
1247     struct at_socket *sock;
1248     int32_t timeout;
1249 
1250     if (optval == RT_NULL || optlen == RT_NULL)
1251     {
1252         LOG_E("AT getsocketopt input option value or option length error!");
1253         rt_set_errno(EFAULT);
1254         return -1;
1255     }
1256 
1257     sock = at_get_socket(socket);
1258     if (sock == RT_NULL)
1259     {
1260         rt_set_errno(ENXIO);
1261         return -1;
1262     }
1263 
1264     switch (level)
1265     {
1266     case SOL_SOCKET:
1267         switch (optname)
1268         {
1269         case SO_RCVTIMEO:
1270             timeout = sock->recv_timeout;
1271             ((struct timeval *)(optval))->tv_sec = (timeout) / 1000U;
1272             ((struct timeval *)(optval))->tv_usec = (timeout % 1000U) * 1000U;
1273             break;
1274 
1275         case SO_SNDTIMEO:
1276             timeout = sock->send_timeout;
1277             ((struct timeval *) optval)->tv_sec = timeout / 1000U;
1278             ((struct timeval *) optval)->tv_usec = (timeout % 1000U) * 1000U;
1279             break;
1280 
1281         default:
1282             LOG_E("AT socket (%d) not support option name : %d.", socket, optname);
1283             rt_set_errno(EPERM);
1284             return -1;
1285         }
1286         break;
1287 
1288     default:
1289         LOG_E("AT socket (%d) not support option level : %d.", socket, level);
1290         rt_set_errno(EPERM);
1291         return -1;
1292     }
1293 
1294     return 0;
1295 }
1296 
at_setsockopt(int socket,int level,int optname,const void * optval,socklen_t optlen)1297 int at_setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen)
1298 {
1299     struct at_socket *sock;
1300 
1301     if (optval == RT_NULL)
1302     {
1303         LOG_E("AT setsockopt input option value error!");
1304         rt_set_errno(EFAULT);
1305         return -1;
1306     }
1307 
1308     sock = at_get_socket(socket);
1309     if (sock == RT_NULL)
1310     {
1311         rt_set_errno(ENXIO);
1312         return -1;
1313     }
1314 
1315     switch (level)
1316     {
1317     case SOL_SOCKET:
1318         switch (optname)
1319         {
1320         case SO_RCVTIMEO:
1321             sock->recv_timeout = ((const struct timeval *) optval)->tv_sec * 1000
1322                     + ((const struct timeval *) optval)->tv_usec / 1000;
1323             break;
1324 
1325         case SO_SNDTIMEO:
1326             sock->send_timeout = ((const struct timeval *) optval)->tv_sec * 1000
1327                     + ((const struct timeval *) optval)->tv_usec / 1000;
1328             break;
1329 
1330         default:
1331             LOG_E("AT socket (%d) not support option name : %d.", socket, optname);
1332             rt_set_errno(EPERM);
1333             return -1;
1334         }
1335         break;
1336     case IPPROTO_TCP:
1337         switch (optname)
1338         {
1339         case TCP_NODELAY:
1340             break;
1341         }
1342         break;
1343     default:
1344         LOG_E("AT socket (%d) not support option level : %d.", socket, level);
1345         rt_set_errno(EPERM);
1346         return -1;
1347     }
1348 
1349     return 0;
1350 }
1351 
ipstr_atol(const char * nptr)1352 static uint32_t ipstr_atol(const char* nptr)
1353 {
1354     uint32_t total = 0;
1355     char sign = '+';
1356     /* jump space */
1357     while (isspace(*nptr))
1358     {
1359         ++nptr;
1360     }
1361     if (*nptr == '-' || *nptr == '+')
1362     {
1363         sign = *nptr++;
1364     }
1365     while (isdigit(*nptr))
1366     {
1367         total = 10 * total + ((*nptr++) - '0');
1368     }
1369     return (sign == '-') ? -total : total;
1370 }
1371 
1372 /* IP address to unsigned int type */
ipstr_to_u32(char * ipstr)1373 static uint32_t ipstr_to_u32(char *ipstr)
1374 {
1375     char ipBytes[4] = { 0 };
1376     uint32_t i;
1377 
1378     for (i = 0; i < 4; i++, ipstr++)
1379     {
1380         ipBytes[i] = (char) ipstr_atol(ipstr);
1381         if ((ipstr = strchr(ipstr, '.')) == RT_NULL)
1382         {
1383             break;
1384         }
1385     }
1386     return *(uint32_t *) ipBytes;
1387 }
1388 
1389 /**
1390  * @brief resolves a domain name via AT device and returns its IP address.
1391  * @note function uses static global mutex internally, which will cause multiple AT devices to block and wait while performing DNS resolution.
1392  * @param name Pointer to a string containing the domain name.
1393  * @param addr Pointer to a structure where the IP address information is stored.
1394  * @return int Returns 0 on success or -1/-2 on failure
1395  *          -1: domain failed
1396  *          -2: HOST_NOT_FOUND
1397  */
_gethostbyname_by_device(const char * name,ip_addr_t * addr)1398 static int _gethostbyname_by_device(const char *name, ip_addr_t *addr)
1399 {
1400     static rt_mutex_t at_dlock = RT_NULL;
1401 
1402     struct at_device *device = RT_NULL;
1403     char ipstr[16] = { 0 };
1404     size_t idx = 0;
1405 
1406     device = at_device_get_first_initialized();
1407     if (device == RT_NULL)
1408     {
1409         return -1;
1410     }
1411 
1412     if (!netdev_is_link_up(device->netdev))
1413     {
1414         return -1;
1415     }
1416 
1417     for (idx = 0; idx < strlen(name) && !isalpha(name[idx]); idx++);
1418 
1419     if (idx < strlen(name))
1420     {
1421         if (at_dlock == RT_NULL)
1422         {
1423             at_dlock = rt_mutex_create("at_dlock", RT_IPC_FLAG_PRIO);
1424             if (at_dlock == RT_NULL)
1425             {
1426                 return -1;
1427             }
1428         }
1429 
1430         rt_mutex_take(at_dlock, RT_WAITING_FOREVER);
1431         if (device->class->socket_ops->at_domain_resolve(name, ipstr) < 0)
1432         {
1433             rt_mutex_release(at_dlock);
1434             return -2;
1435         }
1436         rt_mutex_release(at_dlock);
1437     }
1438     else
1439     {
1440         strncpy(ipstr, name, strlen(name));
1441     }
1442 
1443 #if NETDEV_IPV4 && NETDEV_IPV6
1444     addr.type = IPADDR_TYPE_V4;
1445     if (inet_aton(ipstr, addr) == 0)
1446     {
1447         return -1;
1448     }
1449 #elif NETDEV_IPV4
1450     if (inet_aton(ipstr, addr) == 0)
1451     {
1452         return -1;
1453     }
1454 #elif NETDEV_IPV6
1455 #error "not support IPV6."
1456 #endif /* NETDEV_IPV4 && NETDEV_IPV6 */
1457 
1458     return 0;
1459 }
1460 
at_gethostbyname(const char * name)1461 struct hostent *at_gethostbyname(const char *name)
1462 {
1463     ip_addr_t addr = {0};
1464     /* buffer variables for at_gethostbyname() */
1465     static struct hostent s_hostent;
1466     static char *s_aliases;
1467     static ip_addr_t s_hostent_addr;
1468     static ip_addr_t *s_phostent_addr[2];
1469     static char s_hostname[DNS_MAX_NAME_LENGTH + 1];
1470 
1471     if (name == RT_NULL)
1472     {
1473         LOG_E("AT gethostbyname input name error!");
1474         return RT_NULL;
1475     }
1476 
1477     if (strlen(name) > DNS_MAX_NAME_LENGTH)
1478     {
1479         return RT_NULL;
1480     }
1481 
1482     if (_gethostbyname_by_device(name, &addr) != 0)
1483     {
1484         return RT_NULL;
1485     }
1486 
1487     /* fill hostent structure */
1488     s_hostent_addr = addr;
1489     s_phostent_addr[0] = &s_hostent_addr;
1490     s_phostent_addr[1] = RT_NULL;
1491     strncpy(s_hostname, name, strlen(name));
1492     s_hostname[strlen(name)] = 0;
1493     s_aliases = RT_NULL;
1494 
1495     s_hostent.h_name = s_hostname;
1496     s_hostent.h_aliases = &s_aliases;
1497     s_hostent.h_addrtype = AF_AT;
1498     s_hostent.h_length = sizeof(ip_addr_t);
1499     s_hostent.h_addr_list = (char**) &s_phostent_addr;
1500 
1501     return &s_hostent;
1502 }
1503 
at_gethostbyname_r(const char * name,struct hostent * ret,char * buf,size_t buflen,struct hostent ** result,int * h_errnop)1504 int at_gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop)
1505 {
1506     struct gethostbyname_r_helper
1507     {
1508         ip_addr_t *addr_list[2];
1509         ip_addr_t addr;
1510         char *aliases;
1511     };
1512 
1513     char *hostname = RT_NULL;
1514     int lh_errno = 0;
1515     int domain_err = 0;
1516     size_t namelen = 0;
1517     struct gethostbyname_r_helper *h = RT_NULL;
1518 
1519     if (h_errnop == RT_NULL)
1520     {
1521         h_errnop = &lh_errno;
1522     }
1523 
1524     if ((name == RT_NULL) || (ret == RT_NULL) || (buf == RT_NULL))
1525     {
1526         *h_errnop = EINVAL;
1527         return -1;
1528     }
1529 
1530     if (result == RT_NULL)
1531     {
1532         *h_errnop = EINVAL;
1533         return -1;
1534     }
1535 
1536     *result = RT_NULL;
1537 
1538     namelen = strlen(name);
1539     if (buflen < (sizeof(struct gethostbyname_r_helper) + (namelen + 1)))
1540     {
1541         *h_errnop = ERANGE;
1542         return -1;
1543     }
1544 
1545     h = (struct gethostbyname_r_helper *)buf;
1546     hostname = ((char *)h) + sizeof(struct gethostbyname_r_helper);
1547 
1548     domain_err = _gethostbyname_by_device(name, &h->addr);
1549     if (domain_err != 0)
1550     {
1551         if (domain_err == -2)
1552         {
1553             *h_errnop = HOST_NOT_FOUND;
1554         }
1555 
1556         *h_errnop = NO_DATA;
1557         return -1;
1558     }
1559 
1560     rt_memcpy(hostname, name, namelen);
1561     hostname[namelen] = 0;
1562 
1563     h->addr_list[0] = &h->addr;
1564     h->addr_list[1] = NULL;
1565     h->aliases = NULL;
1566 
1567     ret->h_name = hostname;
1568     ret->h_aliases = &h->aliases;
1569     ret->h_addrtype = AF_INET;
1570     ret->h_length = sizeof(ip_addr_t);
1571     ret->h_addr_list = (char **)&h->addr_list;
1572 
1573     *result = ret;
1574     return 0;
1575 }
1576 
at_getaddrinfo(const char * nodename,const char * servname,const struct addrinfo * hints,struct addrinfo ** res)1577 int at_getaddrinfo(const char *nodename, const char *servname,
1578                     const struct addrinfo *hints, struct addrinfo **res)
1579 {
1580     int port_nr = 0;
1581     ip_addr_t addr = {0};
1582     struct addrinfo *ai;
1583     struct sockaddr_storage *sa;
1584     size_t total_size = 0;
1585     size_t namelen = 0;
1586     int ai_family = 0;
1587 
1588     if (res == RT_NULL)
1589     {
1590         return EAI_FAIL;
1591     }
1592     *res = RT_NULL;
1593 
1594     if ((nodename == RT_NULL) && (servname == RT_NULL))
1595     {
1596         return EAI_NONAME;
1597     }
1598 
1599     if (hints != RT_NULL)
1600     {
1601         ai_family = hints->ai_family;
1602         if (hints->ai_family != AF_AT && hints->ai_family != AF_INET && hints->ai_family != AF_UNSPEC)
1603         {
1604             return EAI_FAMILY;
1605         }
1606     }
1607     else
1608     {
1609         ai_family = AF_UNSPEC;
1610     }
1611 
1612     if (servname != RT_NULL)
1613     {
1614         /* service name specified: convert to port number */
1615         port_nr = atoi(servname);
1616         if ((port_nr <= 0) || (port_nr > 0xffff))
1617         {
1618             return EAI_SERVICE;
1619         }
1620     }
1621 
1622     if (nodename != RT_NULL)
1623     {
1624         /* service location specified, try to resolve */
1625         if ((hints != RT_NULL) && (hints->ai_flags & AI_NUMERICHOST))
1626         {
1627             if (ai_family == AF_AT || ai_family == AF_INET)
1628             {
1629                 return EAI_NONAME;
1630             }
1631 
1632             /* no DNS lookup, just parse for an address string */
1633             if (!inet_aton(nodename, &addr))
1634             {
1635                 return EAI_NONAME;
1636             }
1637 
1638         }
1639         else
1640         {
1641             int domain_err = 0;
1642             domain_err = _gethostbyname_by_device(nodename, &addr);
1643             if (domain_err != 0)
1644             {
1645                 if (domain_err == -2)
1646                 {
1647                     return HOST_NOT_FOUND;
1648                 }
1649 
1650                 return NO_DATA;
1651             }
1652         }
1653     }
1654     else
1655     {
1656         /* service location specified, use loopback address */
1657         inet_aton("127.0.0.1", &addr);
1658     }
1659 
1660     total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_storage);
1661     if (nodename != RT_NULL)
1662     {
1663         namelen = strlen(nodename);
1664         if (namelen == 0 || namelen > DNS_MAX_NAME_LENGTH)
1665         {
1666             /* invalid name length */
1667             return EAI_FAIL;
1668         }
1669 
1670         total_size += namelen + 1;
1671     }
1672     /* If this fails, please report to lwip-devel! :-) */
1673     if (total_size > sizeof(struct addrinfo) + sizeof(struct sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1)
1674     {
1675         return EAI_FAIL;
1676     }
1677 
1678     ai = (struct addrinfo *) rt_malloc(total_size);
1679     if (ai == RT_NULL)
1680     {
1681         return EAI_MEMORY;
1682     }
1683     rt_memset(ai, RT_NULL, total_size);
1684     /* cast through void* to get rid of alignment warnings */
1685     sa = (struct sockaddr_storage *) (void *) ((uint8_t *) ai + sizeof(struct addrinfo));
1686     struct sockaddr_in *sa4 = (struct sockaddr_in *) sa;
1687     /* set up sockaddr */
1688 #if NETDEV_IPV4 && NETDEV_IPV6
1689     sa4->sin_addr.s_addr = addr.u_addr.ip4.addr;
1690     sa4->type = IPADDR_TYPE_V4;
1691 #elif NETDEV_IPV4
1692     sa4->sin_addr.s_addr = addr.addr;
1693 #elif NETDEV_IPV6
1694 #error "not support IPV6."
1695 #endif /* NETDEV_IPV4 && NETDEV_IPV6 */
1696     sa4->sin_family = AF_INET;
1697     sa4->sin_len = sizeof(struct sockaddr_in);
1698     sa4->sin_port = htons((uint16_t)port_nr);
1699     ai->ai_family = AF_INET;
1700 
1701     /* set up addrinfo */
1702     if (hints != RT_NULL)
1703     {
1704         /* copy socktype & protocol from hints if specified */
1705         ai->ai_socktype = hints->ai_socktype;
1706         ai->ai_protocol = hints->ai_protocol;
1707     }
1708     if (nodename != RT_NULL)
1709     {
1710         /* copy nodename to canonname if specified */
1711         ai->ai_canonname = ((char *) ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_storage));
1712         rt_memcpy(ai->ai_canonname, nodename, namelen);
1713         ai->ai_canonname[namelen] = 0;
1714     }
1715     ai->ai_addrlen = sizeof(struct sockaddr_storage);
1716     ai->ai_addr = (struct sockaddr *) sa;
1717 
1718     *res = ai;
1719 
1720     return 0;
1721 }
1722 
at_freeaddrinfo(struct addrinfo * ai)1723 void at_freeaddrinfo(struct addrinfo *ai)
1724 {
1725     struct addrinfo *next;
1726 
1727     while (ai != NULL)
1728     {
1729         next = ai->ai_next;
1730         rt_free(ai);
1731         ai = next;
1732     }
1733 }
1734 
1735 #endif /* AT_USING_SOCKET */
1736