From b5ad12573fe92b710eefc862b1d0891e97a25d18 Mon Sep 17 00:00:00 2001 From: chenyong <1521761801@qq.com> Date: Mon, 27 May 2019 11:49:23 +0800 Subject: [PATCH] [net][at] update AT component V1.3.0, change as follows: - AT Socket feature supports multi-client connections; - Fix `send data error, current socket (0) state (0) is error` issue when the socket is closed; - Improve dirty data processing when AT device hard reset; - Improve `at_obj_set_urc_table()` fucntion, Support for setting multiple URC tables; - Improve RAW data print format; --- components/net/at/Kconfig | 2 +- components/net/at/at_socket/at_socket.c | 414 +++++++++++++++--------- components/net/at/at_socket/at_socket.h | 25 +- components/net/at/include/at.h | 30 +- components/net/at/src/at_client.c | 157 ++++++--- components/net/at/src/at_utils.c | 2 +- 6 files changed, 406 insertions(+), 224 deletions(-) diff --git a/components/net/at/Kconfig b/components/net/at/Kconfig index b1909f86bf..5a4a644761 100644 --- a/components/net/at/Kconfig +++ b/components/net/at/Kconfig @@ -83,7 +83,7 @@ if RT_USING_AT config AT_SW_VERSION_NUM hex - default 0x10200 + default 0x10300 help sfotware module version number diff --git a/components/net/at/at_socket/at_socket.c b/components/net/at/at_socket/at_socket.c index f08a374bf0..a3b36a06ae 100644 --- a/components/net/at/at_socket/at_socket.c +++ b/components/net/at/at_socket/at_socket.c @@ -15,11 +15,15 @@ #include #include +#include #ifdef SAL_USING_POSIX #include #endif +#include +#include + #define LOG_TAG "at.skt" #include @@ -32,10 +36,6 @@ ((unsigned char *)&addr)[2], \ ((unsigned char *)&addr)[3] -#if !defined(AT_DEVICE_SOCKETS_NUM) || defined(AT_DEVICE_NOT_SELECTED) -#error The AT socket device is not selected, please select it through the env menuconfig. -#endif - /* The maximum number of sockets structure */ #ifndef AT_SOCKETS_NUM #define AT_SOCKETS_NUM AT_DEVICE_SOCKETS_NUM @@ -47,31 +47,41 @@ typedef enum { AT_EVENT_ERROR, } at_event_t; -/* the global array of available sockets */ -static struct at_socket sockets[AT_SOCKETS_NUM] = { 0 }; -/* AT device socket options */ -static struct at_device_ops *at_dev_ops = RT_NULL; + +/* the global of sockets list */ +static rt_slist_t _socket_list = RT_SLIST_OBJECT_INIT(_socket_list); struct at_socket *at_get_socket(int socket) { - if (socket < 0 || socket >= AT_SOCKETS_NUM) - { - return RT_NULL; - } + rt_base_t level; + size_t list_num = 0; + rt_slist_t *node = RT_NULL; + struct at_socket *at_sock = RT_NULL; - /* check socket structure valid or not */ - if (sockets[socket].magic != AT_SOCKET_MAGIC) - { - return RT_NULL; - } + level = rt_hw_interrupt_disable(); - return &sockets[socket]; + rt_slist_for_each(node, &_socket_list) + { + if (socket == (list_num++)) + { + at_sock = rt_slist_entry(node, struct at_socket, list); + if (at_sock && at_sock->magic == AT_SOCKET_MAGIC) + { + rt_hw_interrupt_enable(level); + return at_sock; + } + } + } + + rt_hw_interrupt_enable(level); + + return RT_NULL; } /* get a block to the AT socket receive list*/ static size_t at_recvpkt_put(rt_slist_t *rlist, const char *ptr, size_t length) { - at_recv_pkt_t pkt; + at_recv_pkt_t pkt = RT_NULL; pkt = (at_recv_pkt_t) rt_calloc(1, sizeof(struct at_recv_pkt)); if (pkt == RT_NULL) @@ -92,11 +102,13 @@ static size_t at_recvpkt_put(rt_slist_t *rlist, const char *ptr, size_t length) /* delete and free all receive buffer list */ static int at_recvpkt_all_delete(rt_slist_t *rlist) { - at_recv_pkt_t pkt; - rt_slist_t *node; + at_recv_pkt_t pkt = RT_NULL; + rt_slist_t *node = RT_NULL; - if(rt_slist_isempty(rlist)) + if (rt_slist_isempty(rlist)) + { return 0; + } for(node = rt_slist_first(rlist); node; node = rt_slist_next(node)) { @@ -105,7 +117,7 @@ static int at_recvpkt_all_delete(rt_slist_t *rlist) { rt_free(pkt->buff); } - if(pkt) + if (pkt) { rt_free(pkt); pkt = RT_NULL; @@ -118,14 +130,16 @@ static int at_recvpkt_all_delete(rt_slist_t *rlist) /* delete and free specified list block */ static int at_recvpkt_node_delete(rt_slist_t *rlist, rt_slist_t *node) { - at_recv_pkt_t pkt; + at_recv_pkt_t pkt = RT_NULL; - if(rt_slist_isempty(rlist)) + if (rt_slist_isempty(rlist)) + { return 0; + } rt_slist_remove(rlist, node); - pkt= rt_slist_entry(node, struct at_recv_pkt, list); + pkt = rt_slist_entry(node, struct at_recv_pkt, list); if (pkt->buff) { rt_free(pkt->buff); @@ -139,15 +153,17 @@ static int at_recvpkt_node_delete(rt_slist_t *rlist, rt_slist_t *node) return 0; } -/* get a block from AT socket receive list */ +/* get a block from AT socket receive buffer list */ static size_t at_recvpkt_get(rt_slist_t *rlist, char *mem, size_t len) { - rt_slist_t *node; - at_recv_pkt_t pkt; + rt_slist_t *node = RT_NULL; + at_recv_pkt_t pkt = RT_NULL; size_t content_pos = 0, page_pos = 0; - if(rt_slist_isempty(rlist)) + if (rt_slist_isempty(rlist)) + { return 0; + } for (node = rt_slist_first(rlist); node; node = rt_slist_next(node)) { @@ -191,7 +207,6 @@ static void at_do_event_changes(struct at_socket *sock, at_event_t event, rt_boo #ifdef SAL_USING_POSIX rt_wqueue_wakeup(&sock->wait_head, (void*) POLLOUT); #endif - } else if (sock->sendevent) { @@ -208,7 +223,6 @@ static void at_do_event_changes(struct at_socket *sock, at_event_t event, rt_boo #ifdef SAL_USING_POSIX rt_wqueue_wakeup(&sock->wait_head, (void*) POLLIN); #endif - } else if (sock->rcvevent) { @@ -225,7 +239,6 @@ static void at_do_event_changes(struct at_socket *sock, at_event_t event, rt_boo #ifdef SAL_USING_POSIX rt_wqueue_wakeup(&sock->wait_head, (void*) POLLERR); #endif - } else if (sock->errevent) { @@ -262,20 +275,20 @@ static void at_do_event_clean(struct at_socket *sock, at_event_t event) } } -static struct at_socket *alloc_socket(void) +static struct at_socket *alloc_socket_by_device(struct at_device *device) { static rt_mutex_t at_slock = RT_NULL; - char name[RT_NAME_MAX]; - struct at_socket *sock; - int idx; + struct at_socket *sock = RT_NULL; + char name[RT_NAME_MAX] = {0}; + int idx = 0; - if(at_slock == RT_NULL) + if (at_slock == RT_NULL) { /* create AT socket lock */ - at_slock = rt_mutex_create("at_s", RT_IPC_FLAG_FIFO); + at_slock = rt_mutex_create("at_slock", RT_IPC_FLAG_FIFO); if (at_slock == RT_NULL) { - LOG_E("No memory for AT socket lock!"); + LOG_E("No memory for socket allocation lock!"); return RT_NULL; } } @@ -283,34 +296,58 @@ static struct at_socket *alloc_socket(void) rt_mutex_take(at_slock, RT_WAITING_FOREVER); /* find an empty at socket entry */ - for (idx = 0; idx < AT_SOCKETS_NUM && sockets[idx].magic; idx++); + for (idx = 0; idx < device->class->socket_num && device->sockets[idx].magic; idx++); /* can't find an empty protocol family entry */ - if (idx == AT_SOCKETS_NUM) + if (idx == device->class->socket_num) { goto __err; } - sock = &(sockets[idx]); + /* add device socket to global socket list */ + { + rt_base_t level; + + level = rt_hw_interrupt_disable(); + + rt_slist_init(&(device->sockets[idx].list)); + rt_slist_append(&_socket_list, &(device->sockets[idx].list)); + + rt_hw_interrupt_enable(level); + } + + sock = &(device->sockets[idx]); + /* the socket descriptor is the number of sockte lists */ + sock->socket = rt_slist_len(&_socket_list) - 1; + /* the socket operations is the specify operations of the device */ + sock->ops = device->class->socket_ops; + /* the user-data is the at device socket descriptor */ + sock->user_data = (void *) idx; + sock->device = (void *) device; sock->magic = AT_SOCKET_MAGIC; - sock->socket = idx; sock->state = AT_SOCKET_NONE; sock->rcvevent = RT_NULL; sock->sendevent = RT_NULL; sock->errevent = RT_NULL; rt_slist_init(&sock->recvpkt_list); +#ifdef SAL_USING_POSIX + rt_wqueue_init(&sock->wait_head); +#endif - rt_snprintf(name, RT_NAME_MAX, "%s%d", "at_sr", idx); + rt_snprintf(name, RT_NAME_MAX, "%s%d", "at_skt", idx); /* create AT socket receive mailbox */ if ((sock->recv_notice = rt_sem_create(name, 0, RT_IPC_FLAG_FIFO)) == RT_NULL) { + LOG_E("No memory socket receive notic semaphore create."); goto __err; } - rt_snprintf(name, RT_NAME_MAX, "%s%d", "at_sr", idx); + rt_snprintf(name, RT_NAME_MAX, "%s%d", "at_skt", idx); /* create AT socket receive ring buffer lock */ if((sock->recv_lock = rt_mutex_create(name, RT_IPC_FLAG_FIFO)) == RT_NULL) { + LOG_E("No memory for socket receive mutex create."); + rt_sem_delete(sock->recv_notice); goto __err; } @@ -322,13 +359,42 @@ __err: return RT_NULL; } +static struct at_socket *alloc_socket(int domain) +{ + extern struct netdev *netdev_default; + struct netdev *netdev = RT_NULL; + struct at_device *device = RT_NULL; + + if (netdev_default && netdev_is_up(netdev_default)) + { + netdev = netdev_default; + } + else + { + /* get network interface device by protocol family */ + netdev = netdev_get_by_family(domain); + if (netdev == RT_NULL) + { + return RT_NULL; + } + } + + device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name); + if (device == RT_NULL) + { + return RT_NULL; + } + + return alloc_socket_by_device(device); +} + int at_socket(int domain, int type, int protocol) { - struct at_socket *sock; + struct at_socket *sock = RT_NULL; enum at_socket_type socket_type; /* check socket family protocol */ - RT_ASSERT(domain == AF_AT||domain == AF_INET); + RT_ASSERT(domain == AF_AT || domain == AF_INET); //TODO check protocol @@ -348,17 +414,13 @@ int at_socket(int domain, int type, int protocol) } /* allocate and initialize a new AT socket */ - sock = alloc_socket(); - if(sock == RT_NULL) + sock = alloc_socket(domain); + if (sock == RT_NULL) { - LOG_E("Allocate a new AT socket failed!"); - return RT_NULL; + return -1; } sock->type = socket_type; - -#ifdef SAL_USING_POSIX - rt_wqueue_init(&sock->wait_head); -#endif + sock->state = AT_SOCKET_OPEN; return sock->socket; } @@ -380,21 +442,41 @@ static int free_socket(struct at_socket *sock) at_recvpkt_all_delete(&sock->recvpkt_list); } - memset(sock, 0x00, sizeof(struct at_socket)); + /* delect socket from socket list */ + { + rt_base_t level; + int list_num = 0; + rt_slist_t *node = RT_NULL; + struct at_socket *at_sock = RT_NULL; + + level = rt_hw_interrupt_disable(); + + rt_slist_for_each(node, &_socket_list) + { + if (sock->socket == (list_num++)) + { + at_sock = rt_slist_entry(node, struct at_socket, list); + if (at_sock) + { + rt_slist_remove(&_socket_list, &at_sock->list); + break; + } + } + } + + rt_hw_interrupt_enable(level); + } + + rt_memset(sock, 0x00, sizeof(struct at_socket)); return 0; } int at_closesocket(int socket) { - struct at_socket *sock; + struct at_socket *sock = RT_NULL; enum at_socket_state last_state; - if (at_dev_ops == RT_NULL) - { - return -1; - } - /* deal with TCP server actively disconnect */ rt_thread_delay(rt_tick_from_millisecond(100)); @@ -409,9 +491,9 @@ int at_closesocket(int socket) /* the rt_at_socket_close is need some time, so change state in advance */ sock->state = AT_SOCKET_CLOSED; - if (last_state == AT_SOCKET_CONNECT) + if (last_state != AT_SOCKET_CLOSED) { - if (at_dev_ops->at_closesocket(socket) != 0) + if (sock->ops->at_closesocket(sock) != 0) { free_socket(sock); return -1; @@ -424,12 +506,8 @@ int at_closesocket(int socket) int at_shutdown(int socket, int how) { - struct at_socket *sock; - - if (at_dev_ops == RT_NULL) - { - return -1; - } + struct at_socket *sock = RT_NULL; + enum at_socket_state last_state; sock = at_get_socket(socket); if (sock == RT_NULL) @@ -437,9 +515,14 @@ int at_shutdown(int socket, int how) return -1; } - if (sock->state == AT_SOCKET_CONNECT) + last_state = sock->state; + + /* the rt_at_socket_close is need some time, so change state in advance */ + sock->state = AT_SOCKET_CLOSED; + + if (last_state != AT_SOCKET_CLOSED) { - if (at_dev_ops->at_closesocket(socket) != 0) + if (sock->ops->at_closesocket(sock) != 0) { free_socket(sock); return -1; @@ -450,17 +533,6 @@ int at_shutdown(int socket, int how) return 0; } -int at_bind(int socket, const struct sockaddr *name, socklen_t namelen) -{ - - if (at_get_socket(socket) == RT_NULL) - { - return -1; - } - - return 0; -} - /* get IP address and port by socketaddr structure information */ static int socketaddr_to_ipaddr_port(const struct sockaddr *sockaddr, ip_addr_t *addr, uint16_t *port) { @@ -479,6 +551,59 @@ static int socketaddr_to_ipaddr_port(const struct sockaddr *sockaddr, ip_addr_t return 0; } +int at_bind(int socket, const struct sockaddr *name, socklen_t namelen) +{ + struct at_socket *sock = RT_NULL; + struct at_device *device = RT_NULL; + ip_addr_t input_ipaddr, local_ipaddr; + uint16_t port = 0; + + sock = at_get_socket(socket); + if (sock == RT_NULL) + { + return -1; + } + + /* get current device ip address */ + device = (struct at_device *) sock->device; + ip_addr_copy(local_ipaddr, device->netdev->ip_addr); + + /* prase ip address and port from sockaddr structure */ + socketaddr_to_ipaddr_port(name, &input_ipaddr, &port); + + /* input ip address is different from device ip address */ + if (ip_addr_cmp(&input_ipaddr, &local_ipaddr) == 0) + { + struct at_socket *new_sock = RT_NULL; + struct at_device *new_device = RT_NULL; + enum at_socket_type type = sock->type; + + /* close old socket */ + if (at_closesocket(socket) < 0) + { + return -1; + } + + extern struct at_device *at_device_get_by_ipaddr(ip_addr_t *ip_addr); + new_device = at_device_get_by_ipaddr(&input_ipaddr); + if (new_device == RT_NULL) + { + return -1; + } + + /* allocate new socket */ + new_sock = alloc_socket_by_device(new_device); + if (new_sock == RT_NULL) + { + return -1; + } + new_sock->type = type; + new_sock->state = AT_SOCKET_OPEN; + } + + return 0; +} + /* ipaddr structure change to IP address */ static int ipaddr_to_ipstr(const struct sockaddr *sockaddr, char *ipstr) { @@ -490,17 +615,16 @@ static int ipaddr_to_ipstr(const struct sockaddr *sockaddr, char *ipstr) return 0; } -static void at_recv_notice_cb(int socket, at_socket_evt_t event, const char *buff, size_t bfsz) +static void at_recv_notice_cb(struct at_socket *sock, at_socket_evt_t event, const char *buff, size_t bfsz) { - struct at_socket *sock; - RT_ASSERT(buff); - RT_ASSERT(bfsz); RT_ASSERT(event == AT_SOCKET_EVT_RECV); - - sock = at_get_socket(socket); - if (sock == RT_NULL) - return ; + + /* check the socket object status */ + if (sock->magic != AT_SOCKET_MAGIC) + { + return; + } /* put receive buffer to receiver packet list */ rt_mutex_take(sock->recv_lock, RT_WAITING_FOREVER); @@ -512,15 +636,16 @@ static void at_recv_notice_cb(int socket, at_socket_evt_t event, const char *buf at_do_event_changes(sock, AT_EVENT_RECV, RT_TRUE); } -static void at_closed_notice_cb(int socket, at_socket_evt_t event, const char *buff, size_t bfsz) +static void at_closed_notice_cb(struct at_socket *sock, at_socket_evt_t event, const char *buff, size_t bfsz) { - struct at_socket *sock; - RT_ASSERT(event == AT_SOCKET_EVT_CLOSED); - if ((sock = at_get_socket(socket)) == RT_NULL) - return ; - + /* check the socket object status */ + if (sock->magic != AT_SOCKET_MAGIC) + { + return; + } + at_do_event_changes(sock, AT_EVENT_RECV, RT_TRUE); at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE); @@ -530,17 +655,12 @@ static void at_closed_notice_cb(int socket, at_socket_evt_t event, const char *b int at_connect(int socket, const struct sockaddr *name, socklen_t namelen) { - struct at_socket *sock; + struct at_socket *sock = RT_NULL; ip_addr_t remote_addr; - uint16_t remote_port; + uint16_t remote_port = 0; char ipstr[16] = { 0 }; int result = 0; - if (at_dev_ops == RT_NULL) - { - return -1; - } - sock = at_get_socket(socket); if (sock == RT_NULL) { @@ -548,7 +668,7 @@ int at_connect(int socket, const struct sockaddr *name, socklen_t namelen) goto __exit; } - if (sock->state != AT_SOCKET_NONE) + if (sock->state != AT_SOCKET_OPEN) { LOG_E("Socket(%d) connect state is %d.", sock->socket, sock->state); result = -1; @@ -559,7 +679,7 @@ int at_connect(int socket, const struct sockaddr *name, socklen_t namelen) socketaddr_to_ipaddr_port(name, &remote_addr, &remote_port); ipaddr_to_ipstr(name, ipstr); - if (at_dev_ops->at_connect(socket, ipstr, remote_port, sock->type, RT_TRUE) < 0) + if (sock->ops->at_connect(sock, ipstr, remote_port, sock->type, RT_TRUE) < 0) { result = -1; goto __exit; @@ -568,8 +688,8 @@ int at_connect(int socket, const struct sockaddr *name, socklen_t namelen) sock->state = AT_SOCKET_CONNECT; /* set AT socket receive data callback function */ - at_dev_ops->at_set_event_cb(AT_SOCKET_EVT_RECV, at_recv_notice_cb); - at_dev_ops->at_set_event_cb(AT_SOCKET_EVT_CLOSED, at_closed_notice_cb); + sock->ops->at_set_event_cb(AT_SOCKET_EVT_RECV, at_recv_notice_cb); + sock->ops->at_set_event_cb(AT_SOCKET_EVT_CLOSED, at_closed_notice_cb); __exit: @@ -591,9 +711,8 @@ __exit: int at_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) { - struct at_socket *sock; - int timeout; - int result = 0; + struct at_socket *sock = RT_NULL; + int timeout, result = 0; size_t recv_len = 0; if (mem == RT_NULL || len == 0) @@ -602,11 +721,6 @@ int at_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *f return -1; } - if (at_dev_ops == RT_NULL) - { - return -1; - } - sock = at_get_socket(socket); if (sock == RT_NULL) { @@ -615,24 +729,24 @@ int at_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *f } /* if the socket type is UDP, nead to connect socket first */ - if (from && sock->type == AT_SOCKET_UDP && sock->state == AT_SOCKET_NONE) + if (from && sock->type == AT_SOCKET_UDP && sock->state == AT_SOCKET_OPEN) { ip_addr_t remote_addr; - uint16_t remote_port; + uint16_t remote_port = 0; char ipstr[16] = { 0 }; socketaddr_to_ipaddr_port(from, &remote_addr, &remote_port); ipaddr_to_ipstr(from, ipstr); - if (at_dev_ops->at_connect(socket, ipstr, remote_port, sock->type, RT_TRUE) < 0) + if (sock->ops->at_connect(sock, ipstr, remote_port, sock->type, RT_TRUE) < 0) { result = -1; goto __exit; } sock->state = AT_SOCKET_CONNECT; /* set AT socket receive data callback function */ - at_dev_ops->at_set_event_cb(AT_SOCKET_EVT_RECV, at_recv_notice_cb); - at_dev_ops->at_set_event_cb(AT_SOCKET_EVT_CLOSED, at_closed_notice_cb); + sock->ops->at_set_event_cb(AT_SOCKET_EVT_RECV, at_recv_notice_cb); + sock->ops->at_set_event_cb(AT_SOCKET_EVT_CLOSED, at_closed_notice_cb); } /* receive packet list last transmission of remaining data */ @@ -650,7 +764,7 @@ int at_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *f result = 0; goto __exit; } - else if (sock->state != AT_SOCKET_CONNECT) + else if (sock->state != AT_SOCKET_CONNECT && sock->state != AT_SOCKET_OPEN) { LOG_E("received data error, current socket (%d) state (%d) is error.", socket, sock->state); result = -1; @@ -664,7 +778,7 @@ int at_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *f } /* set AT socket receive timeout */ - if((timeout = sock->recv_timeout) == 0) + if ((timeout = sock->recv_timeout) == 0) { timeout = RT_WAITING_FOREVER; } @@ -739,15 +853,9 @@ int at_recv(int s, void *mem, size_t len, int flags) int at_sendto(int socket, const void *data, size_t size, int flags, const struct sockaddr *to, socklen_t tolen) { - struct at_socket *sock; + struct at_socket *sock = RT_NULL; int len, result = 0; - if (at_dev_ops == RT_NULL) - { - result = -1; - goto __exit; - } - if (data == RT_NULL || size == 0) { LOG_E("AT sendto input data or size error!"); @@ -765,14 +873,19 @@ int at_sendto(int socket, const void *data, size_t size, int flags, const struct switch (sock->type) { case AT_SOCKET_TCP: - if (sock->state != AT_SOCKET_CONNECT) + if (sock->state == AT_SOCKET_CLOSED) + { + result = 0; + goto __exit; + } + else if (sock->state != AT_SOCKET_CONNECT && sock->state != AT_SOCKET_OPEN) { LOG_E("send data error, current socket (%d) state (%d) is error.", socket, sock->state); result = -1; goto __exit; } - if ((len = at_dev_ops->at_send(sock->socket, (const char *) data, size, sock->type)) < 0) + if ((len = sock->ops->at_send(sock, (const char *) data, size, sock->type)) < 0) { result = -1; goto __exit; @@ -780,27 +893,27 @@ int at_sendto(int socket, const void *data, size_t size, int flags, const struct break; case AT_SOCKET_UDP: - if (to && sock->state == AT_SOCKET_NONE) + if (to && sock->state == AT_SOCKET_OPEN) { ip_addr_t remote_addr; - uint16_t remote_port; + uint16_t remote_port = 0; char ipstr[16] = { 0 }; socketaddr_to_ipaddr_port(to, &remote_addr, &remote_port); ipaddr_to_ipstr(to, ipstr); - if (at_dev_ops->at_connect(socket, ipstr, remote_port, sock->type, RT_TRUE) < 0) + if (sock->ops->at_connect(sock, ipstr, remote_port, sock->type, RT_TRUE) < 0) { result = -1; goto __exit; } sock->state = AT_SOCKET_CONNECT; /* set AT socket receive data callback function */ - at_dev_ops->at_set_event_cb(AT_SOCKET_EVT_RECV, at_recv_notice_cb); - at_dev_ops->at_set_event_cb(AT_SOCKET_EVT_CLOSED, at_closed_notice_cb); + sock->ops->at_set_event_cb(AT_SOCKET_EVT_RECV, at_recv_notice_cb); + sock->ops->at_set_event_cb(AT_SOCKET_EVT_CLOSED, at_closed_notice_cb); } - if ((len = at_dev_ops->at_send(sock->socket, (char *) data, size, sock->type)) < 0) + if ((len = sock->ops->at_send(sock, (char *) data, size, sock->type)) < 0) { result = -1; goto __exit; @@ -973,6 +1086,7 @@ static uint32_t ipstr_to_u32(char *ipstr) struct hostent *at_gethostbyname(const char *name) { + struct at_device *device = RT_NULL; ip_addr_t addr; char ipstr[16] = { 0 }; /* buffer variables for at_gethostbyname() */ @@ -989,7 +1103,8 @@ struct hostent *at_gethostbyname(const char *name) return RT_NULL; } - if (at_dev_ops == RT_NULL) + device = at_device_get_first_initialized(); + if (device == RT_NULL) { return RT_NULL; } @@ -998,7 +1113,7 @@ struct hostent *at_gethostbyname(const char *name) if (idx < strlen(name)) { - if (at_dev_ops->at_domain_resolve(name, ipstr) < 0) + if (device->class->socket_ops->at_domain_resolve(name, ipstr) < 0) { return RT_NULL; } @@ -1042,6 +1157,7 @@ int at_getaddrinfo(const char *nodename, const char *servname, size_t total_size = 0; size_t namelen = 0; int ai_family = 0; + struct at_device *device = RT_NULL; if (res == RT_NULL) { @@ -1049,7 +1165,8 @@ int at_getaddrinfo(const char *nodename, const char *servname, } *res = RT_NULL; - if (at_dev_ops == RT_NULL) + device = at_device_get_first_initialized(); + if (device == RT_NULL) { return EAI_FAIL; } @@ -1103,7 +1220,7 @@ int at_getaddrinfo(const char *nodename, const char *servname, if(idx < strlen(nodename)) { - if (at_dev_ops->at_domain_resolve((char *) nodename, ip_str) != 0) + if (device->class->socket_ops->at_domain_resolve((char *) nodename, ip_str) != 0) { return EAI_FAIL; } @@ -1201,15 +1318,4 @@ void at_freeaddrinfo(struct addrinfo *ai) } } -void at_socket_device_register(const struct at_device_ops *ops) -{ - RT_ASSERT(ops); - RT_ASSERT(ops->at_connect); - RT_ASSERT(ops->at_closesocket); - RT_ASSERT(ops->at_send); - RT_ASSERT(ops->at_domain_resolve); - RT_ASSERT(ops->at_set_event_cb); - at_dev_ops = (struct at_device_ops *) ops; -} - #endif /* AT_USING_SOCKET */ diff --git a/components/net/at/at_socket/at_socket.h b/components/net/at/at_socket/at_socket.h index 526f8d618a..d98fa05f24 100644 --- a/components/net/at/at_socket/at_socket.h +++ b/components/net/at/at_socket/at_socket.h @@ -36,6 +36,7 @@ extern "C" { enum at_socket_state { AT_SOCKET_NONE, + AT_SOCKET_OPEN, AT_SOCKET_LISTEN, AT_SOCKET_CONNECT, AT_SOCKET_CLOSED @@ -54,18 +55,19 @@ typedef enum AT_SOCKET_EVT_CLOSED, } at_socket_evt_t; -typedef void (*at_evt_cb_t)(int socket, at_socket_evt_t event, const char *buff, size_t bfsz); - struct at_socket; + +typedef void (*at_evt_cb_t)(struct at_socket *socket, at_socket_evt_t event, const char *buff, size_t bfsz); + /* A callback prototype to inform about events for AT socket */ typedef void (* at_socket_callback)(struct at_socket *conn, int event, uint16_t len); -/* AT device socket options function */ -struct at_device_ops +/* AT socket operations function */ +struct at_socket_ops { - int (*at_connect)(int socket, char *ip, int32_t port, enum at_socket_type type, rt_bool_t is_client); - int (*at_closesocket)(int socket); - int (*at_send)(int socket, const char *buff, size_t bfsz, enum at_socket_type type); + int (*at_connect)(struct at_socket *socket, char *ip, int32_t port, enum at_socket_type type, rt_bool_t is_client); + int (*at_closesocket)(struct at_socket *socket); + int (*at_send)(struct at_socket *socket, const char *buff, size_t bfsz, enum at_socket_type type); int (*at_domain_resolve)(const char *name, char ip[16]); void (*at_set_event_cb)(at_socket_evt_t event, at_evt_cb_t cb); }; @@ -86,10 +88,14 @@ struct at_socket uint32_t magic; int socket; + /* device releated information for the socket */ + void *device; /* type of the AT socket (TCP, UDP or RAW) */ enum at_socket_type type; /* current state of the AT socket */ enum at_socket_state state; + /* sockets operations */ + const struct at_socket_ops *ops; /* receive semaphore, received data release semaphore */ rt_sem_t recv_notice; rt_mutex_t recv_lock; @@ -111,6 +117,10 @@ struct at_socket #ifdef SAL_USING_POSIX rt_wqueue_t wait_head; #endif + rt_slist_t list; + + /* user-specific data */ + void *user_data; }; int at_socket(int domain, int type, int protocol); @@ -129,7 +139,6 @@ int at_getaddrinfo(const char *nodename, const char *servname, const struct addr void at_freeaddrinfo(struct addrinfo *ai); struct at_socket *at_get_socket(int socket); -void at_socket_device_register(const struct at_device_ops *ops); #ifndef RT_USING_SAL diff --git a/components/net/at/include/at.h b/components/net/at/include/at.h index 10e4c8833b..dc2abef353 100644 --- a/components/net/at/include/at.h +++ b/components/net/at/include/at.h @@ -18,7 +18,7 @@ extern "C" { #endif -#define AT_SW_VERSION "1.2.0" +#define AT_SW_VERSION "1.3.0" #define AT_CMD_NAME_LEN 16 #define AT_END_MARK_LEN 4 @@ -124,9 +124,11 @@ struct at_response { /* response buffer */ char *buf; - /* the maximum response buffer size */ + /* the maximum response buffer size, it set by `at_create_resp()` function */ rt_size_t buf_size; - /* the number of setting response lines + /* the length of current response buffer */ + rt_size_t buf_len; + /* the number of setting response lines, it set by `at_create_resp()` function * == 0: the response data will auto return when received 'OK' or 'ERROR' * != 0: the response data will return when received setting lines number data */ rt_size_t line_num; @@ -138,15 +140,24 @@ struct at_response typedef struct at_response *at_response_t; +struct at_client; + /* URC(Unsolicited Result Code) object, such as: 'RING', 'READY' request by AT server */ struct at_urc { const char *cmd_prefix; const char *cmd_suffix; - void (*func)(const char *data, rt_size_t size); + void (*func)(struct at_client *client, const char *data, rt_size_t size); }; typedef struct at_urc *at_urc_t; +struct at_urc_table +{ + size_t urc_size; + const struct at_urc *urc; +}; +typedef struct at_urc *at_urc_table_t; + struct at_client { rt_device_t device; @@ -154,9 +165,12 @@ struct at_client at_status_t status; char end_sign; - char *recv_buffer; + /* the current received one line data buffer */ + char *recv_line_buf; + /* The length of the currently received one line data */ + rt_size_t recv_line_len; + /* The maximum supported receive data length */ rt_size_t recv_bufsz; - rt_size_t cur_recv_len; rt_sem_t rx_notice; rt_mutex_t lock; @@ -164,7 +178,7 @@ struct at_client rt_sem_t resp_notice; at_resp_status_t resp_status; - const struct at_urc *urc_table; + struct at_urc_table *urc_table; rt_size_t urc_table_size; rt_thread_t parser; @@ -207,7 +221,7 @@ rt_size_t at_client_obj_recv(at_client_t client, char *buf, rt_size_t size, rt_i void at_obj_set_end_sign(at_client_t client, char ch); /* Set URC(Unsolicited Result Code) table */ -void at_obj_set_urc_table(at_client_t client, const struct at_urc * table, rt_size_t size); +int at_obj_set_urc_table(at_client_t client, const struct at_urc * table, rt_size_t size); /* AT client send commands to AT server and waiter response */ int at_obj_exec_cmd(at_client_t client, at_response_t resp, const char *cmd_expr, ...); diff --git a/components/net/at/src/at_client.c b/components/net/at/src/at_client.c index 41433834cc..ba4009738d 100644 --- a/components/net/at/src/at_client.c +++ b/components/net/at/src/at_client.c @@ -301,13 +301,18 @@ int at_obj_exec_cmd(at_client_t client, at_response_t resp, const char *cmd_expr client->resp_status = AT_RESP_OK; client->resp = resp; + if (resp != RT_NULL) + { + resp->buf_len = 0; + resp->line_counts = 0; + } + va_start(args, cmd_expr); at_vprintfln(client->device, cmd_expr, args); va_end(args); if (resp != RT_NULL) { - resp->line_counts = 0; if (rt_sem_take(client->resp_notice, resp->timeout) != RT_EOK) { cmd = at_get_last_cmd(&cmd_size); @@ -348,17 +353,18 @@ int at_client_obj_wait_connect(at_client_t client, rt_uint32_t timeout) rt_err_t result = RT_EOK; at_response_t resp = RT_NULL; rt_tick_t start_time = 0; + char *client_name = client->device->parent.name; if (client == RT_NULL) { - LOG_E("input AT Client object is NULL, please create or get AT Client object!"); + LOG_E("input AT client object is NULL, please create or get AT Client object!"); return -RT_ERROR; } - resp = at_create_resp(16, 0, rt_tick_from_millisecond(500)); + resp = at_create_resp(64, 0, rt_tick_from_millisecond(300)); if (resp == RT_NULL) { - LOG_E("No memory for response object!"); + LOG_E("no memory for AT client(%s) response object.", client_name); return -RT_ENOMEM; } @@ -372,12 +378,13 @@ int at_client_obj_wait_connect(at_client_t client, rt_uint32_t timeout) /* Check whether it is timeout */ if (rt_tick_get() - start_time > rt_tick_from_millisecond(timeout)) { - LOG_E("wait connect timeout (%d millisecond)!", timeout); + LOG_E("wait AT client(%s) connect timeout(%d tick).", client_name, timeout); result = -RT_ETIMEOUT; break; } /* Check whether it is already connected */ + resp->buf_len = 0; resp->line_counts = 0; rt_device_write(client->device, 0, "AT\r\n", 4); @@ -417,7 +424,7 @@ rt_size_t at_client_obj_send(at_client_t client, const char *buf, rt_size_t size } #ifdef AT_PRINT_RAW_CMD - at_print_raw_cmd("send", buf, size); + at_print_raw_cmd("sendline", buf, size); #endif return rt_device_write(client->device, 0, buf, size); @@ -518,14 +525,14 @@ void at_obj_set_end_sign(at_client_t client, char ch) * @param table URC table * @param size table size */ -void at_obj_set_urc_table(at_client_t client, const struct at_urc *urc_table, rt_size_t table_sz) +int at_obj_set_urc_table(at_client_t client, const struct at_urc *urc_table, rt_size_t table_sz) { rt_size_t idx; if (client == RT_NULL) { LOG_E("input AT Client object is NULL, please create or get AT Client object!"); - return; + return -RT_ERROR; } for (idx = 0; idx < table_sz; idx++) @@ -534,8 +541,47 @@ void at_obj_set_urc_table(at_client_t client, const struct at_urc *urc_table, rt RT_ASSERT(urc_table[idx].cmd_suffix); } - client->urc_table = urc_table; - client->urc_table_size = table_sz; + if (client->urc_table_size == 0) + { + client->urc_table = (struct at_urc_table *) rt_calloc(1, sizeof(struct at_urc_table)); + if (client->urc_table == RT_NULL) + { + return -RT_ENOMEM; + } + + client->urc_table[0].urc = urc_table; + client->urc_table[0].urc_size = table_sz; + client->urc_table_size++; + } + else + { + struct at_urc_table *old_urc_table = RT_NULL; + size_t old_table_size = client->urc_table_size * sizeof(struct at_urc_table); + + old_urc_table = (struct at_urc_table *) rt_malloc(old_table_size); + if (old_urc_table == RT_NULL) + { + return -RT_ENOMEM; + } + rt_memcpy(old_urc_table, client->urc_table, old_table_size); + + /* realloc urc table space */ + client->urc_table = (struct at_urc_table *) rt_realloc(client->urc_table, + old_table_size + sizeof(struct at_urc_table)); + if (client->urc_table == RT_NULL) + { + rt_free(old_urc_table); + return -RT_ENOMEM; + } + rt_memcpy(client->urc_table, old_urc_table, old_table_size); + client->urc_table[client->urc_table_size].urc = urc_table; + client->urc_table[client->urc_table_size].urc_size = table_sz; + client->urc_table_size++; + + rt_free(old_urc_table); + } + + return RT_EOK; } /** @@ -579,30 +625,38 @@ at_client_t at_client_get_first(void) static const struct at_urc *get_urc_obj(at_client_t client) { - rt_size_t i, prefix_len, suffix_len; - rt_size_t buf_sz; + rt_size_t i, j, prefix_len, suffix_len; + rt_size_t bufsz; char *buffer = RT_NULL; + const struct at_urc *urc = RT_NULL; + struct at_urc_table *urc_table = RT_NULL; if (client->urc_table == RT_NULL) { return RT_NULL; } - buffer = client->recv_buffer; - buf_sz = client->cur_recv_len; + buffer = client->recv_line_buf; + bufsz = client->recv_line_len; for (i = 0; i < client->urc_table_size; i++) { - prefix_len = strlen(client->urc_table[i].cmd_prefix); - suffix_len = strlen(client->urc_table[i].cmd_suffix); - if (buf_sz < prefix_len + suffix_len) + for (j = 0; j < client->urc_table[i].urc_size; j++) { - continue; - } - if ((prefix_len ? !strncmp(buffer, client->urc_table[i].cmd_prefix, prefix_len) : 1) - && (suffix_len ? !strncmp(buffer + buf_sz - suffix_len, client->urc_table[i].cmd_suffix, suffix_len) : 1)) - { - return &client->urc_table[i]; + urc_table = client->urc_table + i; + urc = urc_table->urc + j; + + prefix_len = rt_strlen(urc->cmd_prefix); + suffix_len = rt_strlen(urc->cmd_suffix); + if (bufsz < prefix_len + suffix_len) + { + continue; + } + if ((prefix_len ? !rt_strncmp(buffer, urc->cmd_prefix, prefix_len) : 1) + && (suffix_len ? !rt_strncmp(buffer + bufsz - suffix_len, urc->cmd_suffix, suffix_len) : 1)) + { + return urc; + } } } @@ -615,8 +669,8 @@ static int at_recv_readline(at_client_t client) char ch = 0, last_ch = 0; rt_bool_t is_full = RT_FALSE; - memset(client->recv_buffer, 0x00, client->recv_bufsz); - client->cur_recv_len = 0; + rt_memset(client->recv_line_buf, 0x00, client->recv_bufsz); + client->recv_line_len = 0; while (1) { @@ -624,8 +678,8 @@ static int at_recv_readline(at_client_t client) if (read_len < client->recv_bufsz) { - client->recv_buffer[read_len++] = ch; - client->cur_recv_len = read_len; + client->recv_line_buf[read_len++] = ch; + client->recv_line_len = read_len; } else { @@ -639,8 +693,8 @@ static int at_recv_readline(at_client_t client) if (is_full) { LOG_E("read line failed. The line data length is out of buffer size(%d)!", client->recv_bufsz); - memset(client->recv_buffer, 0x00, client->recv_bufsz); - client->cur_recv_len = 0; + rt_memset(client->recv_line_buf, 0x00, client->recv_bufsz); + client->recv_line_len = 0; return -RT_EFULL; } break; @@ -649,7 +703,7 @@ static int at_recv_readline(at_client_t client) } #ifdef AT_PRINT_RAW_CMD - at_print_raw_cmd("recvline", client->recv_buffer, read_len); + at_print_raw_cmd("recvline", client->recv_line_buf, read_len); #endif return read_len; @@ -657,9 +711,7 @@ static int at_recv_readline(at_client_t client) static void client_parser(at_client_t client) { - int resp_buf_len = 0; const struct at_urc *urc; - rt_size_t line_counts = 0; while(1) { @@ -670,39 +722,42 @@ static void client_parser(at_client_t client) /* current receive is request, try to execute related operations */ if (urc->func != RT_NULL) { - urc->func(client->recv_buffer, client->cur_recv_len); + urc->func(client, client->recv_line_buf, client->recv_line_len); } } else if (client->resp != RT_NULL) { + at_response_t resp = client->resp; + /* current receive is response */ - client->recv_buffer[client->cur_recv_len - 1] = '\0'; - if (resp_buf_len + client->cur_recv_len < client->resp->buf_size) + client->recv_line_buf[client->recv_line_len - 1] = '\0'; + if (resp->buf_len + client->recv_line_len < resp->buf_size) { /* copy response lines, separated by '\0' */ - memcpy(client->resp->buf + resp_buf_len, client->recv_buffer, client->cur_recv_len); - resp_buf_len += client->cur_recv_len; + rt_memcpy(resp->buf + resp->buf_len, client->recv_line_buf, client->recv_line_len); - line_counts++; + /* update the current response information */ + resp->buf_len += client->recv_line_len; + resp->line_counts++; } else { client->resp_status = AT_RESP_BUFF_FULL; - LOG_E("Read response buffer failed. The Response buffer size is out of buffer size(%d)!", client->resp->buf_size); + LOG_E("Read response buffer failed. The Response buffer size is out of buffer size(%d)!", resp->buf_size); } /* check response result */ - if (memcmp(client->recv_buffer, AT_RESP_END_OK, strlen(AT_RESP_END_OK)) == 0 - && client->resp->line_num == 0) + if (rt_memcmp(client->recv_line_buf, AT_RESP_END_OK, rt_strlen(AT_RESP_END_OK)) == 0 + && resp->line_num == 0) { /* get the end data by response result, return response state END_OK. */ client->resp_status = AT_RESP_OK; } - else if (strstr(client->recv_buffer, AT_RESP_END_ERROR) - || (memcmp(client->recv_buffer, AT_RESP_END_FAIL, strlen(AT_RESP_END_FAIL)) == 0)) + else if (rt_strstr(client->recv_line_buf, AT_RESP_END_ERROR) + || (rt_memcmp(client->recv_line_buf, AT_RESP_END_FAIL, rt_strlen(AT_RESP_END_FAIL)) == 0)) { client->resp_status = AT_RESP_ERROR; } - else if (line_counts == client->resp->line_num && client->resp->line_num) + else if (resp->line_counts == resp->line_num && resp->line_num) { /* get the end data by response line, return response state END_OK.*/ client->resp_status = AT_RESP_OK; @@ -711,15 +766,13 @@ static void client_parser(at_client_t client) { continue; } - client->resp->line_counts = line_counts; client->resp = RT_NULL; rt_sem_release(client->resp_notice); - resp_buf_len = 0, line_counts = 0; } else { -// log_d("unrecognized line: %.*s", client->cur_recv_len, client->recv_buffer); +// log_d("unrecognized line: %.*s", client->recv_line_len, client->recv_line_buf); } } } @@ -754,9 +807,9 @@ static int at_client_para_init(at_client_t client) client->status = AT_STATUS_UNINITIALIZED; - client->cur_recv_len = 0; - client->recv_buffer = (char *) rt_calloc(1, client->recv_bufsz); - if (client->recv_buffer == RT_NULL) + client->recv_line_len = 0; + client->recv_line_buf = (char *) rt_calloc(1, client->recv_bufsz); + if (client->recv_line_buf == RT_NULL) { LOG_E("AT client initialize failed! No memory for receive buffer."); result = -RT_ENOMEM; @@ -829,9 +882,9 @@ __exit: rt_device_close(client->device); } - if (client->recv_buffer) + if (client->recv_line_buf) { - rt_free(client->recv_buffer); + rt_free(client->recv_line_buf); } rt_memset(client, 0x00, sizeof(struct at_client)); diff --git a/components/net/at/src/at_utils.c b/components/net/at/src/at_utils.c index 73a25da04e..7d26425f56 100644 --- a/components/net/at/src/at_utils.c +++ b/components/net/at/src/at_utils.c @@ -70,7 +70,7 @@ rt_size_t at_vprintf(rt_device_t device, const char *format, va_list args) last_cmd_len = vsnprintf(send_buf, sizeof(send_buf), format, args); #ifdef AT_PRINT_RAW_CMD - at_print_raw_cmd("send", send_buf, last_cmd_len); + at_print_raw_cmd("sendline", send_buf, last_cmd_len); #endif return rt_device_write(device, 0, send_buf, last_cmd_len);