xref: /nrf52832-nimble/rt-thread/components/net/at/at_socket/at_socket.c (revision 104654410c56c573564690304ae786df310c91fc)
1 /*
2  * Copyright (c) 2006-2018, 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  */
10 
11 #include <at.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <ctype.h>
15 #include <sys/time.h>
16 
17 #include <at_socket.h>
18 
19 #ifdef SAL_USING_POSIX
20 #include <dfs_poll.h>
21 #endif
22 
23 #define LOG_TAG              "at.skt"
24 #include <at_log.h>
25 
26 #ifdef AT_USING_SOCKET
27 
28 #define HTONS_PORT(x) ((((x) & 0x00ffUL) << 8) | (((x) & 0xff00UL) >> 8))
29 #define NIPQUAD(addr) \
30         ((unsigned char *)&addr)[0], \
31         ((unsigned char *)&addr)[1], \
32         ((unsigned char *)&addr)[2], \
33         ((unsigned char *)&addr)[3]
34 
35 #if !defined(AT_DEVICE_SOCKETS_NUM) || defined(AT_DEVICE_NOT_SELECTED)
36 #error The AT socket device is not selected, please select it through the env menuconfig.
37 #endif
38 
39 /* The maximum number of sockets structure */
40 #ifndef AT_SOCKETS_NUM
41 #define AT_SOCKETS_NUM       AT_DEVICE_SOCKETS_NUM
42 #endif
43 
44 typedef enum {
45     AT_EVENT_SEND,
46     AT_EVENT_RECV,
47     AT_EVENT_ERROR,
48 } at_event_t;
49 
50 /* the global array of available sockets */
51 static struct at_socket sockets[AT_SOCKETS_NUM] = { 0 };
52 /* AT device socket options */
53 static struct at_device_ops *at_dev_ops = RT_NULL;
54 
at_get_socket(int socket)55 struct at_socket *at_get_socket(int socket)
56 {
57     if (socket < 0 || socket >= AT_SOCKETS_NUM)
58     {
59         return RT_NULL;
60     }
61 
62     /* check socket structure valid or not */
63     if (sockets[socket].magic != AT_SOCKET_MAGIC)
64     {
65         return RT_NULL;
66     }
67 
68     return &sockets[socket];
69 }
70 
71 /* get a block to the AT socket receive list*/
at_recvpkt_put(rt_slist_t * rlist,const char * ptr,size_t length)72 static size_t at_recvpkt_put(rt_slist_t *rlist, const char *ptr, size_t length)
73 {
74     at_recv_pkt_t pkt;
75 
76     pkt = (at_recv_pkt_t) rt_calloc(1, sizeof(struct at_recv_pkt));
77     if (pkt == RT_NULL)
78     {
79         LOG_E("No memory for receive packet table!");
80         return 0;
81     }
82 
83     pkt->bfsz_totle = length;
84     pkt->bfsz_index = 0;
85     pkt->buff = (char *) ptr;
86 
87     rt_slist_append(rlist, &pkt->list);
88 
89     return length;
90 }
91 
92 /* delete and free all receive buffer list */
at_recvpkt_all_delete(rt_slist_t * rlist)93 static int at_recvpkt_all_delete(rt_slist_t *rlist)
94 {
95     at_recv_pkt_t pkt;
96     rt_slist_t *node;
97 
98     if(rt_slist_isempty(rlist))
99         return 0;
100 
101     for(node = rt_slist_first(rlist); node; node = rt_slist_next(node))
102     {
103         pkt = rt_slist_entry(node, struct at_recv_pkt, list);
104         if (pkt->buff)
105         {
106             rt_free(pkt->buff);
107         }
108         if(pkt)
109         {
110             rt_free(pkt);
111             pkt = RT_NULL;
112         }
113     }
114 
115     return 0;
116 }
117 
118 /* delete and free specified list block */
at_recvpkt_node_delete(rt_slist_t * rlist,rt_slist_t * node)119 static int at_recvpkt_node_delete(rt_slist_t *rlist, rt_slist_t *node)
120 {
121     at_recv_pkt_t pkt;
122 
123     if(rt_slist_isempty(rlist))
124         return 0;
125 
126     rt_slist_remove(rlist, node);
127 
128     pkt= rt_slist_entry(node, struct at_recv_pkt, list);
129     if (pkt->buff)
130     {
131         rt_free(pkt->buff);
132     }
133     if (pkt)
134     {
135         rt_free(pkt);
136         pkt = RT_NULL;
137     }
138 
139     return 0;
140 }
141 
142 /* get a block from AT socket receive list */
at_recvpkt_get(rt_slist_t * rlist,char * mem,size_t len)143 static size_t at_recvpkt_get(rt_slist_t *rlist, char *mem, size_t len)
144 {
145     rt_slist_t *node;
146     at_recv_pkt_t pkt;
147     size_t content_pos = 0, page_pos = 0;
148 
149     if(rt_slist_isempty(rlist))
150         return 0;
151 
152     for (node = rt_slist_first(rlist); node; node = rt_slist_next(node))
153     {
154         pkt = rt_slist_entry(node, struct at_recv_pkt, list);
155 
156         page_pos = pkt->bfsz_totle - pkt->bfsz_index;
157 
158         if (page_pos >= len - content_pos)
159         {
160             memcpy((char *) mem + content_pos, pkt->buff + pkt->bfsz_index, len - content_pos);
161             pkt->bfsz_index += len - content_pos;
162             if (pkt->bfsz_index == pkt->bfsz_totle)
163             {
164                 at_recvpkt_node_delete(rlist, node);
165             }
166             content_pos = len;
167             break;
168         }
169         else
170         {
171             memcpy((char *) mem + content_pos, pkt->buff + pkt->bfsz_index, page_pos);
172             content_pos += page_pos;
173             pkt->bfsz_index += page_pos;
174             at_recvpkt_node_delete(rlist, node);
175         }
176     }
177 
178     return content_pos;
179 }
180 
at_do_event_changes(struct at_socket * sock,at_event_t event,rt_bool_t is_plus)181 static void at_do_event_changes(struct at_socket *sock, at_event_t event, rt_bool_t is_plus)
182 {
183     switch (event)
184     {
185     case AT_EVENT_SEND:
186     {
187         if (is_plus)
188         {
189             sock->sendevent = 1;
190 
191 #ifdef SAL_USING_POSIX
192             rt_wqueue_wakeup(&sock->wait_head, (void*) POLLOUT);
193 #endif
194 
195         }
196         else if (sock->sendevent)
197         {
198             sock->sendevent = 0;
199         }
200         break;
201     }
202     case AT_EVENT_RECV:
203     {
204         if (is_plus)
205         {
206             sock->rcvevent++;
207 
208 #ifdef SAL_USING_POSIX
209             rt_wqueue_wakeup(&sock->wait_head, (void*) POLLIN);
210 #endif
211 
212         }
213         else if (sock->rcvevent)
214         {
215             sock->rcvevent --;
216         }
217         break;
218     }
219     case AT_EVENT_ERROR:
220     {
221         if (is_plus)
222         {
223             sock->errevent++;
224 
225 #ifdef SAL_USING_POSIX
226             rt_wqueue_wakeup(&sock->wait_head, (void*) POLLERR);
227 #endif
228 
229         }
230         else if (sock->errevent)
231         {
232             sock->errevent --;
233         }
234         break;
235     }
236     default:
237         LOG_E("Not supported event (%d)", event);
238     }
239 }
240 
at_do_event_clean(struct at_socket * sock,at_event_t event)241 static void at_do_event_clean(struct at_socket *sock, at_event_t event)
242 {
243     switch (event)
244     {
245     case AT_EVENT_SEND:
246     {
247         sock->sendevent = 0;
248         break;
249     }
250     case AT_EVENT_RECV:
251     {
252         sock->rcvevent = 0;
253         break;
254     }
255     case AT_EVENT_ERROR:
256     {
257         sock->errevent = 0;
258         break;
259     }
260     default:
261         LOG_E("Not supported event (%d)", event);
262     }
263 }
264 
alloc_socket(void)265 static struct at_socket *alloc_socket(void)
266 {
267     static rt_mutex_t at_slock = RT_NULL;
268     char name[RT_NAME_MAX];
269     struct at_socket *sock;
270     int idx;
271 
272     if(at_slock == RT_NULL)
273     {
274         /* create AT socket lock */
275         at_slock = rt_mutex_create("at_s", RT_IPC_FLAG_FIFO);
276         if (at_slock == RT_NULL)
277         {
278             LOG_E("No memory for AT socket lock!");
279             return RT_NULL;
280         }
281     }
282 
283     rt_mutex_take(at_slock, RT_WAITING_FOREVER);
284 
285     /* find an empty at socket entry */
286     for (idx = 0; idx < AT_SOCKETS_NUM && sockets[idx].magic; idx++);
287 
288     /* can't find an empty protocol family entry */
289     if (idx == AT_SOCKETS_NUM)
290     {
291         goto __err;
292     }
293 
294     sock = &(sockets[idx]);
295     sock->magic = AT_SOCKET_MAGIC;
296     sock->socket = idx;
297     sock->state = AT_SOCKET_NONE;
298     sock->rcvevent = RT_NULL;
299     sock->sendevent = RT_NULL;
300     sock->errevent = RT_NULL;
301     rt_slist_init(&sock->recvpkt_list);
302 
303     rt_snprintf(name, RT_NAME_MAX, "%s%d", "at_sr", idx);
304     /* create AT socket receive mailbox */
305     if ((sock->recv_notice = rt_sem_create(name, 0, RT_IPC_FLAG_FIFO)) == RT_NULL)
306     {
307         goto __err;
308     }
309 
310     rt_snprintf(name, RT_NAME_MAX, "%s%d", "at_sr", idx);
311     /* create AT socket receive ring buffer lock */
312     if((sock->recv_lock = rt_mutex_create(name, RT_IPC_FLAG_FIFO)) == RT_NULL)
313     {
314         goto __err;
315     }
316 
317     rt_mutex_release(at_slock);
318     return sock;
319 
320 __err:
321     rt_mutex_release(at_slock);
322     return RT_NULL;
323 }
324 
at_socket(int domain,int type,int protocol)325 int at_socket(int domain, int type, int protocol)
326 {
327     struct at_socket *sock;
328     enum at_socket_type socket_type;
329 
330     /* check socket family protocol */
331     RT_ASSERT(domain == AF_AT||domain == AF_INET);
332 
333     //TODO check protocol
334 
335     switch(type)
336     {
337     case SOCK_STREAM:
338         socket_type = AT_SOCKET_TCP;
339         break;
340 
341     case SOCK_DGRAM:
342         socket_type = AT_SOCKET_UDP;
343         break;
344 
345     default :
346         LOG_E("Don't support socket type (%d)!", type);
347         return -1;
348     }
349 
350     /* allocate and initialize a new AT socket */
351     sock = alloc_socket();
352     if(sock == RT_NULL)
353     {
354         LOG_E("Allocate a new AT socket failed!");
355         return RT_NULL;
356     }
357     sock->type = socket_type;
358 
359 #ifdef SAL_USING_POSIX
360     rt_wqueue_init(&sock->wait_head);
361 #endif
362 
363     return sock->socket;
364 }
365 
free_socket(struct at_socket * sock)366 static int free_socket(struct at_socket *sock)
367 {
368     if (sock->recv_notice)
369     {
370         rt_sem_delete(sock->recv_notice);
371     }
372 
373     if (sock->recv_lock)
374     {
375         rt_mutex_delete(sock->recv_lock);
376     }
377 
378     if (!rt_slist_isempty(&sock->recvpkt_list))
379     {
380         at_recvpkt_all_delete(&sock->recvpkt_list);
381     }
382 
383     memset(sock, 0x00, sizeof(struct at_socket));
384 
385     return 0;
386 }
387 
at_closesocket(int socket)388 int at_closesocket(int socket)
389 {
390     struct at_socket *sock;
391     enum at_socket_state last_state;
392 
393     if (at_dev_ops == RT_NULL)
394     {
395         return -1;
396     }
397 
398     /* deal with TCP server actively disconnect */
399     rt_thread_delay(rt_tick_from_millisecond(100));
400 
401     sock = at_get_socket(socket);
402     if (sock == RT_NULL)
403     {
404         return -1;
405     }
406 
407     last_state = sock->state;
408 
409     /* the rt_at_socket_close is need some time, so change state in advance */
410     sock->state = AT_SOCKET_CLOSED;
411 
412     if (last_state == AT_SOCKET_CONNECT)
413     {
414         if (at_dev_ops->at_closesocket(socket) != 0)
415         {
416             LOG_E("AT socket (%d) closesocket failed!", socket);
417             free_socket(sock);
418             return -1;
419         }
420     }
421 
422     free_socket(sock);
423     return 0;
424 }
425 
at_shutdown(int socket,int how)426 int at_shutdown(int socket, int how)
427 {
428     struct at_socket *sock;
429 
430     if (at_dev_ops == RT_NULL)
431     {
432         return -1;
433     }
434 
435     sock = at_get_socket(socket);
436     if (sock == RT_NULL)
437     {
438         return -1;
439     }
440 
441     if (sock->state == AT_SOCKET_CONNECT)
442     {
443         if (at_dev_ops->at_closesocket(socket) != 0)
444         {
445             LOG_E("AT socket (%d) shutdown failed!", socket);
446             free_socket(sock);
447             return -1;
448         }
449     }
450 
451     free_socket(sock);
452     return 0;
453 }
454 
at_bind(int socket,const struct sockaddr * name,socklen_t namelen)455 int at_bind(int socket, const struct sockaddr *name, socklen_t namelen)
456 {
457 
458     if (at_get_socket(socket) == RT_NULL)
459     {
460         return -1;
461     }
462 
463     return 0;
464 }
465 
466 /* get IP address and port by socketaddr structure information */
socketaddr_to_ipaddr_port(const struct sockaddr * sockaddr,ip_addr_t * addr,uint16_t * port)467 static int socketaddr_to_ipaddr_port(const struct sockaddr *sockaddr, ip_addr_t *addr, uint16_t *port)
468 {
469     const struct sockaddr_in* sin = (const struct sockaddr_in*) (const void *) sockaddr;
470 
471     (*addr).u_addr.ip4.addr = sin->sin_addr.s_addr;
472 
473     *port = (uint16_t) HTONS_PORT(sin->sin_port);
474 
475     return 0;
476 }
477 
478 /* ipaddr structure change to IP address */
ipaddr_to_ipstr(const struct sockaddr * sockaddr,char * ipstr)479 static int ipaddr_to_ipstr(const struct sockaddr *sockaddr, char *ipstr)
480 {
481     struct sockaddr_in *sin = (struct sockaddr_in *) sockaddr;
482 
483     /* change network ip_addr to ip string  */
484     rt_snprintf(ipstr, 16, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr));
485 
486     return 0;
487 }
488 
at_recv_notice_cb(int socket,at_socket_evt_t event,const char * buff,size_t bfsz)489 static void at_recv_notice_cb(int socket, at_socket_evt_t event, const char *buff, size_t bfsz)
490 {
491     struct at_socket *sock;
492 
493     RT_ASSERT(buff);
494     RT_ASSERT(bfsz);
495     RT_ASSERT(event == AT_SOCKET_EVT_RECV);
496 
497     sock = at_get_socket(socket);
498     if (sock == RT_NULL)
499         return ;
500 
501     /* put receive buffer to receiver packet list */
502     rt_mutex_take(sock->recv_lock, RT_WAITING_FOREVER);
503     at_recvpkt_put(&(sock->recvpkt_list), buff, bfsz);
504     rt_mutex_release(sock->recv_lock);
505 
506     rt_sem_release(sock->recv_notice);
507 
508     at_do_event_changes(sock, AT_EVENT_RECV, RT_TRUE);
509 }
510 
at_closed_notice_cb(int socket,at_socket_evt_t event,const char * buff,size_t bfsz)511 static void at_closed_notice_cb(int socket, at_socket_evt_t event, const char *buff, size_t bfsz)
512 {
513     struct at_socket *sock;
514 
515     RT_ASSERT(event == AT_SOCKET_EVT_CLOSED);
516 
517     if ((sock = at_get_socket(socket)) == RT_NULL)
518         return ;
519 
520     at_do_event_changes(sock, AT_EVENT_RECV, RT_TRUE);
521     at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
522 
523     sock->state = AT_SOCKET_CLOSED;
524     rt_sem_release(sock->recv_notice);
525 }
526 
at_connect(int socket,const struct sockaddr * name,socklen_t namelen)527 int at_connect(int socket, const struct sockaddr *name, socklen_t namelen)
528 {
529     struct at_socket *sock;
530     ip_addr_t remote_addr;
531     uint16_t remote_port;
532     char ipstr[16] = { 0 };
533     int result = 0;
534 
535     if (at_dev_ops == RT_NULL)
536     {
537         return -1;
538     }
539 
540     sock = at_get_socket(socket);
541     if (sock == RT_NULL)
542     {
543         result = -1;
544         goto __exit;
545     }
546 
547     if (sock->state != AT_SOCKET_NONE)
548     {
549         LOG_E("Socket %d connect state is %d.", sock->socket, sock->state);
550         result = -1;
551         goto __exit;
552     }
553 
554     /* get IP address and port by socketaddr structure */
555     socketaddr_to_ipaddr_port(name, &remote_addr, &remote_port);
556     ipaddr_to_ipstr(name, ipstr);
557 
558     if (at_dev_ops->at_connect(socket, ipstr, remote_port, sock->type, RT_TRUE) < 0)
559     {
560         LOG_E("AT socket(%d) connect failed!", socket);
561         result = -1;
562         goto __exit;
563     }
564 
565     sock->state = AT_SOCKET_CONNECT;
566 
567     /* set AT socket receive data callback function */
568     at_dev_ops->at_set_event_cb(AT_SOCKET_EVT_RECV, at_recv_notice_cb);
569     at_dev_ops->at_set_event_cb(AT_SOCKET_EVT_CLOSED, at_closed_notice_cb);
570 
571 __exit:
572 
573     if (result < 0)
574     {
575         if (sock != RT_NULL)
576         {
577             at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
578         }
579     }
580 
581     if (sock)
582     {
583         at_do_event_changes(sock, AT_EVENT_SEND, RT_TRUE);
584     }
585 
586     return result;
587 }
588 
at_recvfrom(int socket,void * mem,size_t len,int flags,struct sockaddr * from,socklen_t * fromlen)589 int at_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
590 {
591     struct at_socket *sock;
592     int timeout;
593     int result = 0;
594     size_t recv_len = 0;
595 
596     if (mem == RT_NULL || len == 0)
597     {
598         LOG_E("AT recvfrom input data or length error!");
599         return -1;
600     }
601 
602     if (at_dev_ops == RT_NULL)
603     {
604         return -1;
605     }
606 
607     sock = at_get_socket(socket);
608     if (sock == RT_NULL)
609     {
610         result = -1;
611         goto __exit;
612     }
613 
614     /* if the socket type is UDP, nead to connect socket first */
615     if (from && sock->type == AT_SOCKET_UDP && sock->state == AT_SOCKET_NONE)
616     {
617         ip_addr_t remote_addr;
618         uint16_t remote_port;
619         char ipstr[16] = { 0 };
620 
621         socketaddr_to_ipaddr_port(from, &remote_addr, &remote_port);
622         ipaddr_to_ipstr(from, ipstr);
623 
624         if (at_dev_ops->at_connect(socket, ipstr, remote_port, sock->type, RT_TRUE) < 0)
625         {
626             LOG_E("AT socket UDP connect failed!");
627             result = -1;
628             goto __exit;
629         }
630         sock->state = AT_SOCKET_CONNECT;
631         /* set AT socket receive data callback function */
632         at_dev_ops->at_set_event_cb(AT_SOCKET_EVT_RECV, at_recv_notice_cb);
633         at_dev_ops->at_set_event_cb(AT_SOCKET_EVT_CLOSED, at_closed_notice_cb);
634     }
635 
636     /* receive packet list last transmission of remaining data */
637     rt_mutex_take(sock->recv_lock, RT_WAITING_FOREVER);
638     if((recv_len = at_recvpkt_get(&(sock->recvpkt_list), (char *)mem, len)) > 0)
639     {
640         rt_mutex_release(sock->recv_lock);
641         goto __exit;
642     }
643     rt_mutex_release(sock->recv_lock);
644 
645     /* socket passively closed, receive function return 0 */
646     if (sock->state == AT_SOCKET_CLOSED)
647     {
648         result = 0;
649         goto __exit;
650     }
651     else if (sock->state != AT_SOCKET_CONNECT)
652     {
653         LOG_E("received data error, current socket (%d) state (%d) is error.", socket, sock->state);
654         result = -1;
655         goto __exit;
656     }
657 
658     /* non-blocking sockets receive data */
659     if (flags & MSG_DONTWAIT)
660     {
661         goto __exit;
662     }
663 
664     /* set AT socket receive timeout */
665     if((timeout = sock->recv_timeout) == 0)
666     {
667         timeout = RT_WAITING_FOREVER;
668     }
669     else
670     {
671         timeout = rt_tick_from_millisecond(timeout);
672     }
673 
674     while (1)
675     {
676         /* wait the receive semaphore */
677         if (rt_sem_take(sock->recv_notice, timeout) < 0)
678         {
679             LOG_E("AT socket (%d) receive timeout (%d)!", socket, timeout);
680             errno = EAGAIN;
681             result = -1;
682             goto __exit;
683         }
684         else
685         {
686             if (sock->state == AT_SOCKET_CONNECT)
687             {
688                 /* get receive buffer to receiver ring buffer */
689                 rt_mutex_take(sock->recv_lock, RT_WAITING_FOREVER);
690                 recv_len = at_recvpkt_get(&(sock->recvpkt_list), (char *) mem, len);
691                 rt_mutex_release(sock->recv_lock);
692                 if (recv_len > 0)
693                 {
694                     break;
695                 }
696             }
697             else
698             {
699                 LOG_D("received data exit, current socket (%d) is closed by remote.", socket);
700                 result = 0;
701                 goto __exit;
702             }
703         }
704     }
705 
706 __exit:
707 
708     if (sock != RT_NULL)
709     {
710         if (recv_len > 0)
711         {
712             result = recv_len;
713             at_do_event_changes(sock, AT_EVENT_RECV, RT_FALSE);
714             errno = 0;
715             if (!rt_slist_isempty(&sock->recvpkt_list))
716             {
717                 at_do_event_changes(sock, AT_EVENT_RECV, RT_TRUE);
718             }
719             else
720             {
721                 at_do_event_clean(sock, AT_EVENT_RECV);
722             }
723         }
724         else
725         {
726             at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
727         }
728     }
729 
730     return result;
731 }
732 
at_recv(int s,void * mem,size_t len,int flags)733 int at_recv(int s, void *mem, size_t len, int flags)
734 {
735     return at_recvfrom(s, mem, len, flags, RT_NULL, RT_NULL);
736 }
737 
at_sendto(int socket,const void * data,size_t size,int flags,const struct sockaddr * to,socklen_t tolen)738 int at_sendto(int socket, const void *data, size_t size, int flags, const struct sockaddr *to, socklen_t tolen)
739 {
740     struct at_socket *sock;
741     int len, result = 0;
742 
743     if (at_dev_ops == RT_NULL)
744     {
745         result = -1;
746         goto __exit;
747     }
748 
749     if (data == RT_NULL || size == 0)
750     {
751         LOG_E("AT sendto input data or size error!");
752         result = -1;
753         goto __exit;
754     }
755 
756     sock = at_get_socket(socket);
757     if (sock == RT_NULL)
758     {
759         result = -1;
760         goto __exit;
761     }
762 
763     switch (sock->type)
764     {
765     case AT_SOCKET_TCP:
766         if (sock->state != AT_SOCKET_CONNECT)
767         {
768             LOG_E("send data error, current socket (%d) state (%d) is error.", socket, sock->state);
769             result = -1;
770             goto __exit;
771         }
772 
773         if ((len = at_dev_ops->at_send(sock->socket, (const char *) data, size, sock->type)) < 0)
774         {
775             result = -1;
776             goto __exit;
777         }
778         break;
779 
780     case AT_SOCKET_UDP:
781         if (to && sock->state == AT_SOCKET_NONE)
782         {
783             ip_addr_t remote_addr;
784             uint16_t remote_port;
785             char ipstr[16] = { 0 };
786 
787             socketaddr_to_ipaddr_port(to, &remote_addr, &remote_port);
788             ipaddr_to_ipstr(to, ipstr);
789 
790             if (at_dev_ops->at_connect(socket, ipstr, remote_port, sock->type, RT_TRUE) < 0)
791             {
792                 LOG_E("AT socket (%d) UDP connect failed!", socket);
793                 result = -1;
794                 goto __exit;
795             }
796             sock->state = AT_SOCKET_CONNECT;
797             /* set AT socket receive data callback function */
798             at_dev_ops->at_set_event_cb(AT_SOCKET_EVT_RECV, at_recv_notice_cb);
799             at_dev_ops->at_set_event_cb(AT_SOCKET_EVT_CLOSED, at_closed_notice_cb);
800         }
801 
802         if ((len = at_dev_ops->at_send(sock->socket, (char *) data, size, sock->type)) < 0)
803         {
804             result = -1;
805             goto __exit;
806         }
807         break;
808 
809     default:
810         LOG_E("Socket (%d) type %d is not support.", socket, sock->type);
811         result = -1;
812         goto __exit;
813     }
814 
815 __exit:
816 
817     if (result < 0)
818     {
819         if (sock != RT_NULL)
820         {
821             at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
822         }
823     }
824     else
825     {
826         result = len;
827     }
828 
829     return result;
830 }
831 
at_send(int socket,const void * data,size_t size,int flags)832 int at_send(int socket, const void *data, size_t size, int flags)
833 {
834     return at_sendto(socket, data, size, flags, RT_NULL, 0);
835 }
836 
at_getsockopt(int socket,int level,int optname,void * optval,socklen_t * optlen)837 int at_getsockopt(int socket, int level, int optname, void *optval, socklen_t *optlen)
838 {
839     struct at_socket *sock;
840     int32_t timeout;
841 
842     if (optval == RT_NULL || optlen == RT_NULL)
843     {
844         LOG_E("AT getsocketopt input option value or option length error!");
845         return -1;
846     }
847 
848     sock = at_get_socket(socket);
849     if (sock == RT_NULL)
850     {
851         return -1;
852     }
853 
854     switch (level)
855     {
856     case SOL_SOCKET:
857         switch (optname)
858         {
859         case SO_RCVTIMEO:
860             timeout = sock->recv_timeout;
861             ((struct timeval *)(optval))->tv_sec = (timeout) / 1000U;
862             ((struct timeval *)(optval))->tv_usec = (timeout % 1000U) * 1000U;
863             break;
864 
865         case SO_SNDTIMEO:
866             timeout = sock->send_timeout;
867             ((struct timeval *) optval)->tv_sec = timeout / 1000U;
868             ((struct timeval *) optval)->tv_usec = (timeout % 1000U) * 1000U;
869             break;
870 
871         default:
872             LOG_E("AT socket (%d) not support option name : %d.", socket, optname);
873             return -1;
874         }
875         break;
876 
877     default:
878         LOG_E("AT socket (%d) not support option level : %d.", socket, level);
879         return -1;
880     }
881 
882     return 0;
883 }
884 
at_setsockopt(int socket,int level,int optname,const void * optval,socklen_t optlen)885 int at_setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen)
886 {
887     struct at_socket *sock;
888 
889     if (optval == RT_NULL)
890     {
891         LOG_E("AT setsockopt input option value error!");
892         return -1;
893     }
894 
895     sock = at_get_socket(socket);
896     if (sock == RT_NULL)
897     {
898         return -1;
899     }
900 
901     switch (level)
902     {
903     case SOL_SOCKET:
904         switch (optname)
905         {
906         case SO_RCVTIMEO:
907             sock->recv_timeout = ((const struct timeval *) optval)->tv_sec * 1000
908                     + ((const struct timeval *) optval)->tv_usec / 1000;
909             break;
910 
911         case SO_SNDTIMEO:
912             sock->send_timeout = ((const struct timeval *) optval)->tv_sec * 1000
913                     + ((const struct timeval *) optval)->tv_usec / 1000;
914             break;
915 
916         default:
917             LOG_E("AT socket (%d) not support option name : %d.", socket, optname);
918             return -1;
919         }
920         break;
921     case IPPROTO_TCP:
922         switch (optname)
923         {
924         case TCP_NODELAY:
925             break;
926         }
927         break;
928     default:
929         LOG_E("AT socket (%d) not support option level : %d.", socket, level);
930         return -1;
931     }
932 
933     return 0;
934 }
935 
ipstr_atol(const char * nptr)936 static uint32_t ipstr_atol(const char* nptr)
937 {
938     uint32_t total = 0;
939     char sign = '+';
940     /* jump space */
941     while (isspace(*nptr))
942     {
943         ++nptr;
944     }
945     if (*nptr == '-' || *nptr == '+')
946     {
947         sign = *nptr++;
948     }
949     while (isdigit(*nptr))
950     {
951         total = 10 * total + ((*nptr++) - '0');
952     }
953     return (sign == '-') ? -total : total;
954 }
955 
956 /* IP address to unsigned int type */
ipstr_to_u32(char * ipstr)957 static uint32_t ipstr_to_u32(char *ipstr)
958 {
959     char ipBytes[4] = { 0 };
960     uint32_t i;
961 
962     for (i = 0; i < 4; i++, ipstr++)
963     {
964         ipBytes[i] = (char) ipstr_atol(ipstr);
965         if ((ipstr = strchr(ipstr, '.')) == RT_NULL)
966         {
967             break;
968         }
969     }
970     return *(uint32_t *) ipBytes;
971 }
972 
at_gethostbyname(const char * name)973 struct hostent *at_gethostbyname(const char *name)
974 {
975     ip_addr_t addr;
976     char ipstr[16] = { 0 };
977     /* buffer variables for at_gethostbyname() */
978     static struct hostent s_hostent;
979     static char *s_aliases;
980     static ip_addr_t s_hostent_addr;
981     static ip_addr_t *s_phostent_addr[2];
982     static char s_hostname[DNS_MAX_NAME_LENGTH + 1];
983     size_t idx = 0;
984 
985     if (name == RT_NULL)
986     {
987         LOG_E("AT gethostbyname input name error!");
988         return RT_NULL;
989     }
990 
991     if (at_dev_ops == RT_NULL)
992     {
993         return RT_NULL;
994     }
995 
996     for (idx = 0; idx < strlen(name) && !isalpha(name[idx]); idx++);
997 
998     if (idx < strlen(name))
999     {
1000         if (at_dev_ops->at_domain_resolve(name, ipstr) < 0)
1001         {
1002             LOG_E("AT domain (%s) resolve error!", name);
1003             return RT_NULL;
1004         }
1005     }
1006     else
1007     {
1008         strncpy(ipstr, name, strlen(name));
1009     }
1010 
1011     addr.u_addr.ip4.addr = ipstr_to_u32(ipstr);
1012 
1013     /* fill hostent structure */
1014     s_hostent_addr = addr;
1015     s_phostent_addr[0] = &s_hostent_addr;
1016     s_phostent_addr[1] = RT_NULL;
1017     strncpy(s_hostname, name, DNS_MAX_NAME_LENGTH);
1018     s_hostname[DNS_MAX_NAME_LENGTH] = 0;
1019     s_hostent.h_name = s_hostname;
1020     s_aliases = RT_NULL;
1021     s_hostent.h_aliases = &s_aliases;
1022     s_hostent.h_addrtype = AF_AT;
1023     s_hostent.h_length = sizeof(ip_addr_t);
1024     s_hostent.h_addr_list = (char**) &s_phostent_addr;
1025 
1026     return &s_hostent;
1027 }
1028 
at_getaddrinfo(const char * nodename,const char * servname,const struct addrinfo * hints,struct addrinfo ** res)1029 int at_getaddrinfo(const char *nodename, const char *servname,
1030                     const struct addrinfo *hints, struct addrinfo **res)
1031 {
1032     int port_nr = 0;
1033     ip_addr_t addr;
1034     struct addrinfo *ai;
1035     struct sockaddr_storage *sa;
1036     size_t total_size = 0;
1037     size_t namelen = 0;
1038     int ai_family = 0;
1039 
1040     if (res == RT_NULL)
1041     {
1042         return EAI_FAIL;
1043     }
1044     *res = RT_NULL;
1045 
1046     if (at_dev_ops == RT_NULL)
1047     {
1048         return EAI_FAIL;
1049     }
1050 
1051     if ((nodename == RT_NULL) && (servname == RT_NULL))
1052     {
1053         return EAI_NONAME;
1054     }
1055 
1056     if (hints != RT_NULL)
1057     {
1058         ai_family = hints->ai_family;
1059         if (hints->ai_family != AF_AT && hints->ai_family != AF_INET && hints->ai_family != AF_UNSPEC)
1060         {
1061             return EAI_FAMILY;
1062         }
1063     }
1064 
1065     if (servname != RT_NULL)
1066     {
1067         /* service name specified: convert to port number */
1068         port_nr = atoi(servname);
1069         if ((port_nr <= 0) || (port_nr > 0xffff))
1070         {
1071             return EAI_SERVICE;
1072         }
1073     }
1074 
1075     if (nodename != RT_NULL)
1076     {
1077         /* service location specified, try to resolve */
1078         if ((hints != RT_NULL) && (hints->ai_flags & AI_NUMERICHOST))
1079         {
1080             /* no DNS lookup, just parse for an address string */
1081             if (!inet_aton(nodename, (ip4_addr_t * )&addr))
1082             {
1083                 return EAI_NONAME;
1084             }
1085 
1086             if (ai_family == AF_AT || ai_family == AF_INET)
1087             {
1088                 return EAI_NONAME;
1089             }
1090         }
1091         else
1092         {
1093             char ip_str[16] = { 0 };
1094             size_t idx = 0;
1095 
1096             for (idx = 0; idx < strlen(nodename) && !isalpha(nodename[idx]); idx++);
1097 
1098             if(idx < strlen(nodename))
1099             {
1100                 if (at_dev_ops->at_domain_resolve((char *) nodename, ip_str) != 0)
1101                 {
1102                     return EAI_FAIL;
1103                 }
1104             }
1105             else
1106             {
1107                 strncpy(ip_str, nodename, strlen(nodename));
1108             }
1109 
1110             addr.type = IPADDR_TYPE_V4;
1111             if ((addr.u_addr.ip4.addr = ipstr_to_u32(ip_str)) == 0)
1112             {
1113                 return EAI_FAIL;
1114             }
1115         }
1116     }
1117     else
1118     {
1119         /* to do service location specified, use loopback address */
1120     }
1121 
1122     total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_storage);
1123     if (nodename != RT_NULL)
1124     {
1125         namelen = strlen(nodename);
1126         if (namelen > DNS_MAX_NAME_LENGTH)
1127         {
1128             /* invalid name length */
1129             return EAI_FAIL;
1130         }
1131         RT_ASSERT(total_size + namelen + 1 > total_size);
1132         total_size += namelen + 1;
1133     }
1134     /* If this fails, please report to lwip-devel! :-) */
1135     RT_ASSERT(total_size <= sizeof(struct addrinfo) + sizeof(struct sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1);
1136     ai = (struct addrinfo *) rt_malloc(total_size);
1137     if (ai == RT_NULL)
1138     {
1139         return EAI_MEMORY;
1140     }
1141     memset(ai, 0, total_size);
1142     /* cast through void* to get rid of alignment warnings */
1143     sa = (struct sockaddr_storage *) (void *) ((uint8_t *) ai + sizeof(struct addrinfo));
1144     struct sockaddr_in *sa4 = (struct sockaddr_in *) sa;
1145     /* set up sockaddr */
1146     sa4->sin_addr.s_addr = addr.u_addr.ip4.addr;
1147     sa4->sin_family = AF_INET;
1148     sa4->sin_len = sizeof(struct sockaddr_in);
1149     sa4->sin_port = htons((u16_t )port_nr);
1150     ai->ai_family = AF_INET;
1151 
1152     /* set up addrinfo */
1153     if (hints != RT_NULL)
1154     {
1155         /* copy socktype & protocol from hints if specified */
1156         ai->ai_socktype = hints->ai_socktype;
1157         ai->ai_protocol = hints->ai_protocol;
1158     }
1159     if (nodename != RT_NULL)
1160     {
1161         /* copy nodename to canonname if specified */
1162         ai->ai_canonname = ((char *) ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_storage));
1163         memcpy(ai->ai_canonname, nodename, namelen);
1164         ai->ai_canonname[namelen] = 0;
1165     }
1166     ai->ai_addrlen = sizeof(struct sockaddr_storage);
1167     ai->ai_addr = (struct sockaddr *) sa;
1168 
1169     *res = ai;
1170 
1171     return 0;
1172 }
1173 
at_freeaddrinfo(struct addrinfo * ai)1174 void at_freeaddrinfo(struct addrinfo *ai)
1175 {
1176     struct addrinfo *next;
1177 
1178     while (ai != NULL)
1179     {
1180         next = ai->ai_next;
1181         rt_free(ai);
1182         ai = next;
1183     }
1184 }
1185 
at_socket_device_register(const struct at_device_ops * ops)1186 void at_socket_device_register(const struct at_device_ops *ops)
1187 {
1188     RT_ASSERT(ops);
1189     RT_ASSERT(ops->at_connect);
1190     RT_ASSERT(ops->at_closesocket);
1191     RT_ASSERT(ops->at_send);
1192     RT_ASSERT(ops->at_domain_resolve);
1193     RT_ASSERT(ops->at_set_event_cb);
1194     at_dev_ops = (struct at_device_ops *) ops;
1195 }
1196 
1197 #endif /* AT_USING_SOCKET */
1198