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