Browse Source

[components][at] 优化AT组件,并解决内存泄露

1.优化at server endmark判断,支持自动识别'\r''\n'"\r\n"。
2.优化at_recvfrom,修复大数据量时sem多次释放造成的接收错误。
3.修复at组件中可能存在的内存泄露。
4.优化部分代码逻辑,减少冗余代码。
yangpengya 1 year ago
parent
commit
a8d5a645f2

+ 0 - 19
components/net/at/Kconfig

@@ -26,25 +26,6 @@ if RT_USING_AT
             int "The maximum length of server commands buffer"
             default 256
 
-        choice
-            prompt "The commands new line sign"
-            help
-                This end mark can used for AT server determine the end of commands ,
-                it can choose "\r", "\n" or "\r\n"
-
-            default AT_CMD_END_MARK_CRLF
-
-            config AT_CMD_END_MARK_CRLF
-                bool "\\r\\n"
-
-            config AT_CMD_END_MARK_CR
-                bool "\\r"
-
-            config AT_CMD_END_MARK_LF
-                bool "\\n"
-
-        endchoice
-
     endif
 
     config AT_USING_CLIENT

+ 68 - 160
components/net/at/at_socket/at_socket.c

@@ -717,16 +717,13 @@ static int ipaddr_to_ipstr(const struct sockaddr *sockaddr, char *ipstr)
 }
 
 #ifdef AT_USING_SOCKET_SERVER
-static int (*store_at_socket_temporary)(struct at_device *device, enum at_socket_type type);
 static void at_connect_notice_cb(struct at_socket *sock, at_socket_evt_t event, const char *buff, size_t bfsz)
 {
     RT_ASSERT(buff);
     RT_ASSERT(sock == RT_NULL);
     RT_ASSERT(event == AT_SOCKET_EVT_CONNECTED);
 
-    extern struct netdev *netdev_default;
-    struct netdev *netdev = RT_NULL;
-    struct at_device *device = RT_NULL;
+    int new_socket;
     struct at_socket *new_sock = RT_NULL;
     rt_base_t level;
     rt_slist_t *node = RT_NULL;
@@ -734,51 +731,17 @@ static void at_connect_notice_cb(struct at_socket *sock, at_socket_evt_t event,
     char *socket_info = RT_NULL;
     int base_socket = 0;
 
-    if (netdev_default && netdev_is_up(netdev_default) &&
-            netdev_family_get(netdev_default) == AF_AT)
-    {
-        netdev = netdev_default;
-    }
-    else
-    {
-        /* get network interface device by protocol family AF_AT */
-        netdev = netdev_get_by_family(AF_AT);
-        if (netdev == RT_NULL)
-        {
-            return;
-        }
-    }
-
-    device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
-    if (device == RT_NULL)
-    {
-        return;
-    }
-
     /* avoid use bottom driver to alloc "socket" */
-    store_at_socket_temporary = device->class->socket_ops->at_socket;
-    device->class->socket_ops->at_socket = RT_NULL;
-    new_sock = alloc_socket_by_device(device, AT_SOCKET_TCP);
-    if (new_sock == RT_NULL)
+    new_socket = at_socket(AF_AT, SOCK_STREAM, 0);
+    if (new_socket == -1)
     {
         return;
     }
-    new_sock->type = AT_SOCKET_TCP;
+    new_sock = at_get_socket(new_socket);
     new_sock->state = AT_SOCKET_CONNECT;
-
-    /* set AT socket receive data callback function */
-    new_sock->ops->at_set_event_cb(AT_SOCKET_EVT_RECV, at_recv_notice_cb);
-    new_sock->ops->at_set_event_cb(AT_SOCKET_EVT_CLOSED, at_closed_notice_cb);
-    new_sock->ops->at_set_event_cb(AT_SOCKET_EVT_CONNECTED, at_connect_notice_cb);
-    device->class->socket_ops->at_socket = store_at_socket_temporary;
-
-    /* put incoming "socket" to the listen socket receiver packet list */
     sscanf(buff, "SOCKET:%d", &base_socket);
     LOG_D("ACCEPT BASE SOCKET: %d", base_socket);
     new_sock->user_data = (void *)base_socket;
-    socket_info = rt_malloc(AT_SOCKET_INFO_LEN);
-    rt_memset(socket_info, 0, AT_SOCKET_INFO_LEN);
-    rt_sprintf(socket_info, "SOCKET:%d", new_sock->socket);
 
     /* find out the listen socket */
     level = rt_hw_interrupt_disable();
@@ -793,16 +756,23 @@ static void at_connect_notice_cb(struct at_socket *sock, at_socket_evt_t event,
     }
     rt_hw_interrupt_enable(level);
 
-    if(at_sock == RT_NULL)
+    if (at_sock == RT_NULL)
     {
+        at_closesocket(new_socket);
         return;
     }
 
+    /* put incoming "socket" to the listen socket receiver packet list */
+    socket_info = rt_malloc(AT_SOCKET_INFO_LEN);
+    rt_memset(socket_info, 0, AT_SOCKET_INFO_LEN);
+    rt_sprintf(socket_info, "SOCKET:%d", new_sock->socket);
+
     /* wakeup the "accept" function */
     rt_mutex_take(at_sock->recv_lock, RT_WAITING_FOREVER);
     if (at_recvpkt_put(&(at_sock->recvpkt_list), socket_info, AT_SOCKET_INFO_LEN) != RT_EOK)
     {
-        rt_free((void *)buff);
+        at_closesocket(new_socket);
+        rt_free(socket_info);
         rt_mutex_release(at_sock->recv_lock);
         return;
     }
@@ -866,8 +836,7 @@ int at_listen(int socket, int backlog)
     sock = at_get_socket(socket);
     if (sock == RT_NULL)
     {
-        result = -1;
-        goto __exit;
+        return -1;
     }
 
     if (sock->state != AT_SOCKET_OPEN)
@@ -890,10 +859,7 @@ __exit:
 
     if (result < 0)
     {
-        if (sock != RT_NULL)
-        {
-            at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
-        }
+        at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
     }
 
     return result;
@@ -911,8 +877,7 @@ int at_connect(int socket, const struct sockaddr *name, socklen_t namelen)
     sock = at_get_socket(socket);
     if (sock == RT_NULL)
     {
-        result = -1;
-        goto __exit;
+        return -1;
     }
 
     if (sock->state != AT_SOCKET_OPEN)
@@ -938,13 +903,9 @@ __exit:
 
     if (result < 0)
     {
-        if (sock != RT_NULL)
-        {
-            at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
-        }
+        at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
     }
-
-    if (sock)
+    else
     {
         at_do_event_changes(sock, AT_EVENT_SEND, RT_TRUE);
     }
@@ -966,8 +927,7 @@ int at_accept(int socket, struct sockaddr *name, socklen_t *namelen)
     sock = at_get_socket(socket);
     if (sock == RT_NULL)
     {
-        result = -1;
-        goto __exit;
+        return -1;
     }
 
     if (sock->state != AT_SOCKET_LISTEN)
@@ -990,16 +950,11 @@ int at_accept(int socket, struct sockaddr *name, socklen_t *namelen)
         rt_mutex_take(sock->recv_lock, RT_WAITING_FOREVER);
         at_recvpkt_get(&(sock->recvpkt_list), (char *) &receive_buff, AT_SOCKET_INFO_LEN);
         rt_mutex_release(sock->recv_lock);
+        at_do_event_changes(sock, AT_EVENT_RECV, RT_FALSE);
     }
 
     sscanf(&receive_buff[0], "SOCKET:%d", &new_socket);
     new_sock = at_get_socket(new_socket);
-    if (sock == RT_NULL)
-    {
-        result = -1;
-        goto __exit;
-    }
-    new_sock->state = AT_SOCKET_CONNECT;
     ip4_addr_set_any(&remote_addr);
     ipaddr_port_to_socketaddr(name, &remote_addr, &remote_port);
     LOG_D("Accept: [socket :%d, base_socket:%d]", new_socket, (int)new_sock->user_data);
@@ -1007,10 +962,7 @@ int at_accept(int socket, struct sockaddr *name, socklen_t *namelen)
 __exit:
     if (result < 0)
     {
-        if (sock != RT_NULL)
-        {
-            at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
-        }
+        at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
     }
 
     return new_sock->socket;
@@ -1025,15 +977,14 @@ int at_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *f
 
     if (mem == RT_NULL || len == 0)
     {
-        LOG_E("AT recvfrom input data or length error!");
-        return -1;
+        /* if the requested number of bytes to receive from a stream socket was 0. */
+        return 0;
     }
 
     sock = at_get_socket(socket);
     if (sock == RT_NULL)
     {
-        result = -1;
-        goto __exit;
+        return -1;
     }
 
     /* if the socket type is UDP, need to connect socket first */
@@ -1048,106 +999,68 @@ int at_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *f
 
         if (sock->ops->at_connect(sock, ipstr, remote_port, sock->type, RT_TRUE) < 0)
         {
-            result = -1;
-            goto __exit;
+            at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
+            /* socket shutdown */
+            return 0;
         }
         sock->state = AT_SOCKET_CONNECT;
     }
 
-    /* receive packet list last transmission of remaining data */
-    rt_mutex_take(sock->recv_lock, RT_WAITING_FOREVER);
-    if((recv_len = at_recvpkt_get(&(sock->recvpkt_list), (char *)mem, len)) > 0)
-    {
-        rt_mutex_release(sock->recv_lock);
-        goto __exit;
-    }
-    rt_mutex_release(sock->recv_lock);
-
-    /* socket passively closed, receive function return 0 */
-    if (sock->state == AT_SOCKET_CLOSED)
-    {
-        result = 0;
-        goto __exit;
-    }
-    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;
-        goto __exit;
-    }
-
-    /* non-blocking sockets receive data */
-    if (flags & MSG_DONTWAIT)
-    {
-        goto __exit;
-    }
-
-    /* set AT socket receive timeout */
-    if ((timeout = sock->recv_timeout) == 0)
-    {
-        timeout = RT_WAITING_FOREVER;
-    }
-    else
-    {
-        timeout = rt_tick_from_millisecond(timeout);
-    }
-
     while (1)
     {
-        /* wait the receive semaphore */
-        if (rt_sem_take(sock->recv_notice, timeout) < 0)
+        if (sock->state == AT_SOCKET_CLOSED)
         {
-            LOG_D("AT socket (%d) receive timeout (%d)!", socket, timeout);
-            errno = EAGAIN;
-            result = -1;
-            goto __exit;
+            /* socket passively closed, receive function return 0 */
+            result = 0;
+            break;
         }
-        else
-        {
 
-            /* get receive buffer to receiver ring buffer */
-            rt_mutex_take(sock->recv_lock, RT_WAITING_FOREVER);
-            recv_len = at_recvpkt_get(&(sock->recvpkt_list), (char *) mem, len);
-            rt_mutex_release(sock->recv_lock);
-            if (recv_len > 0)
-            {
-                break;
-            }
-            else
+        rt_sem_control(sock->recv_notice, RT_IPC_CMD_RESET, RT_NULL);
+        /* receive packet list last transmission of remaining data */
+        rt_mutex_take(sock->recv_lock, RT_WAITING_FOREVER);
+        recv_len = at_recvpkt_get(&(sock->recvpkt_list), (char *)mem, len);
+        rt_mutex_release(sock->recv_lock);
+        if (recv_len > 0)
+        {
+            if (rt_slist_isempty(&sock->recvpkt_list))
             {
-                /* we have no data to receive but are woken up,
-                    which means the socket have been closed. */
-                errno = EIO;
-                result = -1;
-                goto __exit;
+                at_do_event_clean(sock, AT_EVENT_RECV);
             }
+            errno = 0;
+            result = recv_len;
+            break;
         }
-    }
 
-__exit:
+        if (flags & MSG_DONTWAIT)
+        {
+            errno = EAGAIN;
+            result = -1;
+            break;
+        }
 
-    if (sock != RT_NULL)
-    {
-        if (recv_len > 0)
+        /* set AT socket receive timeout */
+        if (sock->recv_timeout == 0)
         {
-            result = recv_len;
-            at_do_event_changes(sock, AT_EVENT_RECV, RT_FALSE);
-            errno = 0;
-            if (!rt_slist_isempty(&sock->recvpkt_list))
-            {
-                at_do_event_changes(sock, AT_EVENT_RECV, RT_TRUE);
-            }
-            else
-            {
-                at_do_event_clean(sock, AT_EVENT_RECV);
-            }
+            timeout = RT_WAITING_FOREVER;
         }
         else
         {
-            at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
+            timeout = rt_tick_from_millisecond(sock->recv_timeout);
+        }
+        if (rt_sem_take(sock->recv_notice, timeout) != RT_EOK)
+        {
+            LOG_D("AT socket (%d) receive timeout (%d)!", socket, timeout);
+            errno = EAGAIN;
+            result = -1;
+            break;
         }
     }
 
+    if (result <= 0)
+    {
+        at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
+    }
+
     return result;
 }
 
@@ -1164,15 +1077,13 @@ int at_sendto(int socket, const void *data, size_t size, int flags, const struct
     if (data == RT_NULL || size == 0)
     {
         LOG_E("AT sendto input data or size error!");
-        result = -1;
-        goto __exit;
+        return -1;
     }
 
     sock = at_get_socket(socket);
     if (sock == RT_NULL)
     {
-        result = -1;
-        goto __exit;
+        return -1;
     }
 
     switch (sock->type)
@@ -1232,10 +1143,7 @@ __exit:
 
     if (result < 0)
     {
-        if (sock != RT_NULL)
-        {
-            at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
-        }
+        at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
     }
     else
     {

+ 0 - 15
components/net/at/include/at.h

@@ -22,20 +22,6 @@ extern "C" {
 #define AT_SW_VERSION                  "1.3.1"
 
 #define AT_CMD_NAME_LEN                16
-#define AT_END_MARK_LEN                4
-
-#ifndef AT_CMD_MAX_LEN
-#define AT_CMD_MAX_LEN                 128
-#endif
-
-/* the server AT commands new line sign */
-#if defined(AT_CMD_END_MARK_CRLF)
-#define AT_CMD_END_MARK                "\r\n"
-#elif defined(AT_CMD_END_MARK_CR)
-#define AT_CMD_END_MARK                "\r"
-#elif defined(AT_CMD_END_MARK_LF)
-#define AT_CMD_END_MARK                "\n"
-#endif
 
 #ifndef AT_SERVER_RECV_BUFF_LEN
 #define AT_SERVER_RECV_BUFF_LEN        256
@@ -104,7 +90,6 @@ struct at_server
     char recv_buffer[AT_SERVER_RECV_BUFF_LEN];
     rt_size_t cur_recv_len;
     rt_sem_t rx_notice;
-    char end_mark[AT_END_MARK_LEN];
 
     rt_thread_t parser;
     void (*parser_entry)(struct at_server *server);

+ 3 - 13
components/net/at/src/at_cli.c

@@ -114,7 +114,6 @@ static void server_cli_parser(void)
     rt_base_t level;
     static rt_device_t device_bak;
     static rt_err_t (*getchar_bak)(struct at_server *server, char *ch, rt_int32_t timeout);
-    static char endmark_back[AT_END_MARK_LEN];
 
     /* backup server device and getchar function */
     {
@@ -123,16 +122,10 @@ static void server_cli_parser(void)
         device_bak = server->device;
         getchar_bak = server->get_char;
 
-        rt_memset(endmark_back, 0x00, AT_END_MARK_LEN);
-        rt_memcpy(endmark_back, server->end_mark, strlen(server->end_mark));
-
         /* setup server device as console device */
         server->device = rt_console_get_device();
         server->get_char = at_server_console_getchar;
 
-        rt_memset(server->end_mark, 0x00, AT_END_MARK_LEN);
-        server->end_mark[0] = '\r';
-
         rt_hw_interrupt_enable(level);
     }
 
@@ -154,9 +147,6 @@ static void server_cli_parser(void)
         server->device = device_bak;
         server->get_char = getchar_bak;
 
-        rt_memset(server->end_mark, 0x00, AT_END_MARK_LEN);
-        rt_memcpy(server->end_mark, endmark_back, strlen(endmark_back));
-
         rt_hw_interrupt_enable(level);
     }
 }
@@ -223,6 +213,9 @@ static void client_cli_parser(at_client_t  client)
             client->status = AT_STATUS_CLI;
         }
 
+        rt_sem_init(&client_rx_notice, "cli_r", 0, RT_IPC_FLAG_FIFO);
+        client_rx_fifo = rt_ringbuffer_create(AT_CLI_FIFO_SIZE);
+
         /* backup client device RX indicate */
         {
             level = rt_hw_interrupt_disable();
@@ -231,9 +224,6 @@ static void client_cli_parser(at_client_t  client)
             rt_hw_interrupt_enable(level);
         }
 
-        rt_sem_init(&client_rx_notice, "cli_r", 0, RT_IPC_FLAG_FIFO);
-        client_rx_fifo = rt_ringbuffer_create(AT_CLI_FIFO_SIZE);
-
         at_client = rt_thread_create("at_cli", at_client_entry, RT_NULL, 512, 8, 8);
         if (client_rx_fifo && at_client)
         {

+ 20 - 37
components/net/at/src/at_client.c

@@ -146,7 +146,6 @@ at_response_t at_resp_set_info(at_response_t resp, rt_size_t buf_size, rt_size_t
 const char *at_resp_get_line(at_response_t resp, rt_size_t resp_line)
 {
     char *resp_buf = resp->buf;
-    char *resp_line_buf = RT_NULL;
     rt_size_t line_num = 1;
 
     RT_ASSERT(resp);
@@ -161,9 +160,7 @@ const char *at_resp_get_line(at_response_t resp, rt_size_t resp_line)
     {
         if (resp_line == line_num)
         {
-            resp_line_buf = resp_buf;
-
-            return resp_line_buf;
+            return resp_buf;
         }
 
         resp_buf += strlen(resp_buf) + 1;
@@ -184,7 +181,6 @@ const char *at_resp_get_line(at_response_t resp, rt_size_t resp_line)
 const char *at_resp_get_line_by_kw(at_response_t resp, const char *keyword)
 {
     char *resp_buf = resp->buf;
-    char *resp_line_buf = RT_NULL;
     rt_size_t line_num = 1;
 
     RT_ASSERT(resp);
@@ -194,9 +190,7 @@ const char *at_resp_get_line_by_kw(at_response_t resp, const char *keyword)
     {
         if (strstr(resp_buf, keyword))
         {
-            resp_line_buf = resp_buf;
-
-            return resp_line_buf;
+            return resp_buf;
         }
 
         resp_buf += strlen(resp_buf) + 1;
@@ -332,17 +326,14 @@ int at_obj_exec_cmd(at_client_t client, at_response_t resp, const char *cmd_expr
             LOG_W("execute command (%.*s) timeout (%d ticks)!", client->last_cmd_len, client->send_buf, resp->timeout);
             client->resp_status = AT_RESP_TIMEOUT;
             result = -RT_ETIMEOUT;
-            goto __exit;
         }
-        if (client->resp_status != AT_RESP_OK)
+        else if (client->resp_status != AT_RESP_OK)
         {
             LOG_E("execute command (%.*s) failed!", client->last_cmd_len, client->send_buf);
             result = -RT_ERROR;
-            goto __exit;
         }
     }
 
-__exit:
     client->resp = RT_NULL;
 
     rt_mutex_release(client->lock);
@@ -401,9 +392,7 @@ int at_client_obj_wait_connect(at_client_t client, rt_uint32_t timeout)
         resp->line_counts = 0;
         at_utils_send(client->device, 0, "AT\r\n", 4);
 
-        if (rt_sem_take(client->resp_notice, resp->timeout) != RT_EOK)
-            continue;
-        else
+        if (rt_sem_take(client->resp_notice, resp->timeout) == RT_EOK)
             break;
     }
 
@@ -494,25 +483,23 @@ rt_size_t at_client_obj_recv(at_client_t client, char *buf, rt_size_t size, rt_i
         return 0;
     }
 
-    while (1)
+    while (size)
     {
         rt_size_t read_len;
 
         rt_sem_control(client->rx_notice, RT_IPC_CMD_RESET, RT_NULL);
 
         read_len = rt_device_read(client->device, 0, buf + len, size);
-        if(read_len > 0)
+        if (read_len > 0)
         {
             len += read_len;
             size -= read_len;
-            if(size == 0)
+        }
+        else
+        {
+            if (rt_sem_take(client->rx_notice, rt_tick_from_millisecond(timeout)) != RT_EOK)
                 break;
-
-            continue;
         }
-
-        if(rt_sem_take(client->rx_notice, rt_tick_from_millisecond(timeout)) != RT_EOK)
-            break;
     }
 
 #ifdef AT_PRINT_RAW_CMD
@@ -676,7 +663,6 @@ static const struct at_urc *get_urc_obj(at_client_t client)
 
 static int at_recv_readline(at_client_t client)
 {
-    rt_size_t read_len = 0;
     char ch = 0, last_ch = 0;
     rt_bool_t is_full = RT_FALSE;
 
@@ -687,10 +673,9 @@ static int at_recv_readline(at_client_t client)
     {
         at_client_getchar(client, &ch, RT_WAITING_FOREVER);
 
-        if (read_len < client->recv_bufsz)
+        if (client->recv_line_len < client->recv_bufsz)
         {
-            client->recv_line_buf[read_len++] = ch;
-            client->recv_line_len = read_len;
+            client->recv_line_buf[client->recv_line_len++] = ch;
         }
         else
         {
@@ -714,10 +699,10 @@ static int at_recv_readline(at_client_t client)
     }
 
 #ifdef AT_PRINT_RAW_CMD
-    at_print_raw_cmd("recvline", client->recv_line_buf, read_len);
+    at_print_raw_cmd("recvline", client->recv_line_buf, client->recv_line_len);
 #endif
 
-    return read_len;
+    return client->recv_line_len;
 }
 
 static void client_parser(at_client_t client)
@@ -882,7 +867,6 @@ static int at_client_para_init(at_client_t client)
     if (client->parser == RT_NULL)
     {
         result = -RT_ENOMEM;
-        goto __exit;
     }
 
 __exit:
@@ -903,14 +887,14 @@ __exit:
             rt_sem_delete(client->resp_notice);
         }
 
-        if (client->device)
+        if (client->recv_line_buf)
         {
-            rt_device_close(client->device);
+            rt_free(client->recv_line_buf);
         }
 
-        if (client->recv_line_buf)
+        if (client->send_buf)
         {
-            rt_free(client->recv_line_buf);
+            rt_free(client->send_buf);
         }
 
         rt_memset(client, 0x00, sizeof(struct at_client));
@@ -928,6 +912,7 @@ __exit:
  *
  * @param dev_name AT client device name
  * @param recv_bufsz the maximum number of receive buffer length
+ * @param send_bufsz the maximum number of send command length
  *
  * @return 0 : initialize success
  *        -1 : initialize failed
@@ -974,6 +959,7 @@ int at_client_init(const char *dev_name, rt_size_t recv_bufsz, rt_size_t send_bu
     {
         RT_ASSERT(client->device->type == RT_Device_Class_Char);
 
+        rt_device_set_rx_indicate(client->device, at_client_rx_ind);
         /* using DMA mode first */
         open_result = rt_device_open(client->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_DMA_RX);
         /* using interrupt mode when DMA mode not supported */
@@ -982,14 +968,11 @@ int at_client_init(const char *dev_name, rt_size_t recv_bufsz, rt_size_t send_bu
             open_result = rt_device_open(client->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
         }
         RT_ASSERT(open_result == RT_EOK);
-
-        rt_device_set_rx_indicate(client->device, at_client_rx_ind);
     }
     else
     {
         LOG_E("AT client initialize failed! Not find the device(%s).", dev_name);
         result = -RT_ERROR;
-        goto __exit;
     }
 
 __exit:

+ 71 - 87
components/net/at/src/at_server.c

@@ -311,70 +311,59 @@ static rt_err_t at_check_args(const char *args, const char *args_format)
     return RT_EOK;
 }
 
-static rt_err_t at_cmd_process(at_cmd_t cmd, const char *cmd_args)
+static at_result_t at_cmd_process(at_cmd_t cmd, const char *cmd_args)
 {
-    at_result_t result = AT_RESULT_OK;
-
     RT_ASSERT(cmd);
     RT_ASSERT(cmd_args);
 
-    if (cmd_args[0] == AT_CMD_EQUAL_MARK && cmd_args[1] == AT_CMD_QUESTION_MARK && cmd_args[2] == AT_CMD_CR)
+    /* AT+TEST=? */
+    if (cmd_args[0] == AT_CMD_EQUAL_MARK && cmd_args[1] == AT_CMD_QUESTION_MARK)
     {
         if (cmd->test == RT_NULL)
         {
-            at_server_print_result(AT_RESULT_CMD_ERR);
-            return -RT_ERROR;
+            return AT_RESULT_CMD_ERR;
         }
 
-        result = cmd->test();
-        at_server_print_result(result);
+        return cmd->test();
     }
-    else if (cmd_args[0] == AT_CMD_QUESTION_MARK && cmd_args[1] == AT_CMD_CR)
+    /* AT+TEST? */
+    else if (cmd_args[0] == AT_CMD_QUESTION_MARK)
     {
         if (cmd->query == RT_NULL)
         {
-            at_server_print_result(AT_RESULT_CMD_ERR);
-            return -RT_ERROR;
+            return AT_RESULT_CMD_ERR;
         }
 
-        result = cmd->query();
-        at_server_print_result(result);
+        return cmd->query();
     }
+    /* AT+TEST=1 or ATE1 */
     else if (cmd_args[0] == AT_CMD_EQUAL_MARK
-            || (cmd_args[0] >= AT_CMD_CHAR_0 && cmd_args[0] <= AT_CMD_CHAR_9 && cmd_args[1] == AT_CMD_CR))
+            || (cmd_args[0] >= AT_CMD_CHAR_0 && cmd_args[0] <= AT_CMD_CHAR_9 && (cmd_args[1] == AT_CMD_CR || cmd_args[1] == AT_CMD_LF)))
     {
         if (cmd->setup == RT_NULL)
         {
-            at_server_print_result(AT_RESULT_CMD_ERR);
-            return -RT_ERROR;
+            return AT_RESULT_CMD_ERR;
         }
 
         if(at_check_args(cmd_args, cmd->args_expr) < 0)
         {
-            at_server_print_result(AT_RESULT_CHECK_FAILE);
-            return -RT_ERROR;
+            return AT_RESULT_CHECK_FAILE;
         }
 
-        result = cmd->setup(cmd_args);
-        at_server_print_result(result);
+        return cmd->setup(cmd_args);
     }
-    else if (cmd_args[0] == AT_CMD_CR)
+    /* AT+TEST */
+    else if (cmd_args[0] == AT_CMD_CR || cmd_args[0] == AT_CMD_LF)
     {
         if (cmd->exec == RT_NULL)
         {
-            at_server_print_result(AT_RESULT_CMD_ERR);
-            return -RT_ERROR;
+            return AT_RESULT_CMD_ERR;
         }
 
-        result = cmd->exec();
-        at_server_print_result(result);
-    }
-    else
-    {
-        return -RT_ERROR;
+        return cmd->exec();
     }
 
-    return RT_EOK;
+    return AT_RESULT_FAILE;
 }
 
 static at_cmd_t at_find_cmd(const char *cmd)
@@ -400,10 +389,10 @@ static rt_err_t at_cmd_get_name(const char *cmd_buffer, char *cmd_name)
     RT_ASSERT(cmd_name);
     RT_ASSERT(cmd_buffer);
 
-    for (i = 0; i < strlen(cmd_buffer); i++)
+    for (i = 0; i < strlen(cmd_buffer) && i < AT_CMD_NAME_LEN; i++)
     {
         if (*(cmd_buffer + i) == AT_CMD_QUESTION_MARK || *(cmd_buffer + i) == AT_CMD_EQUAL_MARK
-                || *(cmd_buffer + i) == AT_CMD_CR
+                || *(cmd_buffer + i) == AT_CMD_CR || *(cmd_buffer + i) == AT_CMD_LF
                 || (*(cmd_buffer + i) >= AT_CMD_CHAR_0 && *(cmd_buffer + i) <= AT_CMD_CHAR_9))
         {
             cmd_name_len = i;
@@ -443,6 +432,7 @@ static void server_parser(at_server_t server)
     char cur_cmd_name[AT_CMD_NAME_LEN] = { 0 };
     at_cmd_t cur_cmd = RT_NULL;
     char *cur_cmd_args = RT_NULL, ch, last_ch;
+    at_result_t result;
 
     RT_ASSERT(server);
     RT_ASSERT(server->status != AT_STATUS_UNINITIALIZED);
@@ -455,66 +445,54 @@ static void server_parser(at_server_t server)
             break;
         }
 
-        if (server->echo_mode)
+        if (ch == BACKSPACE_KEY || ch == DELECT_KEY)
         {
-            if (ch == AT_CMD_CR || (ch == AT_CMD_LF && last_ch != AT_CMD_CR))
-            {
-                at_server_printf("%c%c", AT_CMD_CR, AT_CMD_LF);
-            }
-            else if (ch == AT_CMD_LF)
-            {
-                // skip the end sign check
-            }
-            else if (ch == BACKSPACE_KEY || ch == DELECT_KEY)
+            if (server->cur_recv_len)
+                server->cur_recv_len--;
+            if (server->echo_mode)
+                at_server_printf("\b \b");
+        }
+        else if (ch == AT_CMD_LF && last_ch == AT_CMD_CR)
+        {
+            /* skip '\n' if we get "\r\n" */
+        }
+        else
+        {
+            if (server->cur_recv_len < sizeof(server->recv_buffer) - 1)
             {
-                if (server->cur_recv_len)
+                server->recv_buffer[server->cur_recv_len++] = ch;
+                if (ch == AT_CMD_CR || ch == AT_CMD_LF)
                 {
-                    server->recv_buffer[--server->cur_recv_len] = 0;
-                    at_server_printf("\b \b");
+                    if (server->echo_mode)
+                        at_server_printf("%c%c", AT_CMD_CR, AT_CMD_LF);
+                    server->recv_buffer[server->cur_recv_len] = '\0';
+                    result = AT_RESULT_FAILE;
+                    if (at_cmd_get_name(server->recv_buffer, cur_cmd_name) == RT_EOK)
+                    {
+                        cur_cmd = at_find_cmd(cur_cmd_name);
+                        if (cur_cmd)
+                        {
+                            cur_cmd_args = server->recv_buffer + strlen(cur_cmd_name);
+                            result = at_cmd_process(cur_cmd, cur_cmd_args);
+                        }
+                    }
+
+                    at_server_print_result(result);
+                    server->cur_recv_len = 0;
                 }
-
-                continue;
-            }
-            else if (ch == AT_CMD_NULL)
-            {
-                continue;
+                else
+                {
+                    if (server->echo_mode)
+                        at_server_printf("%c", ch);
+                }
+                last_ch = ch;
             }
             else
             {
-                at_server_printf("%c", ch);
+                /* server receive buffer overflow!!! */
+                server->cur_recv_len = 0;
             }
         }
-
-        server->recv_buffer[server->cur_recv_len++] = ch;
-        last_ch = ch;
-
-        if(!strstr(server->recv_buffer, server->end_mark))
-        {
-            continue;
-        }
-
-        if (at_cmd_get_name(server->recv_buffer, cur_cmd_name) < 0)
-        {
-            at_server_print_result(AT_RESULT_CMD_ERR);
-            goto __retry;
-        }
-
-        cur_cmd = at_find_cmd(cur_cmd_name);
-        if (!cur_cmd)
-        {
-            at_server_print_result(AT_RESULT_CMD_ERR);
-            goto __retry;
-        }
-
-        cur_cmd_args = server->recv_buffer + strlen(cur_cmd_name);
-        if (at_cmd_process(cur_cmd, cur_cmd_args) < 0)
-        {
-            goto __retry;
-        }
-
-__retry:
-        rt_memset(server->recv_buffer, 0x00, AT_SERVER_RECV_BUFF_LEN);
-        server->cur_recv_len = 0;
     }
 }
 
@@ -586,6 +564,7 @@ int at_server_init(void)
     {
         RT_ASSERT(at_server_local->device->type == RT_Device_Class_Char);
 
+        rt_device_set_rx_indicate(at_server_local->device, at_rx_ind);
         /* using DMA mode first */
         open_result = rt_device_open(at_server_local->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_DMA_RX);
         /* using interrupt mode when DMA mode not supported */
@@ -594,8 +573,6 @@ int at_server_init(void)
             open_result = rt_device_open(at_server_local->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
         }
         RT_ASSERT(open_result == RT_EOK);
-
-        rt_device_set_rx_indicate(at_server_local->device, at_rx_ind);
     }
     else
     {
@@ -605,7 +582,6 @@ int at_server_init(void)
     }
 
     at_server_local->get_char = at_server_getchar;
-    rt_memcpy(at_server_local->end_mark, AT_CMD_END_MARK, sizeof(AT_CMD_END_MARK));
 
     at_server_local->parser_entry = server_parser;
     at_server_local->parser = rt_thread_create("at_svr",
@@ -617,7 +593,6 @@ int at_server_init(void)
     if (at_server_local->parser == RT_NULL)
     {
         result = -RT_ENOMEM;
-        goto __exit;
     }
 
 __exit:
@@ -633,7 +608,16 @@ __exit:
     {
         if (at_server_local)
         {
+            if (at_server_local->rx_notice)
+            {
+                rt_sem_delete(at_server_local->rx_notice);
+            }
+            if (at_server_local->device)
+            {
+                rt_device_close(at_server_local->device);
+            }
             rt_free(at_server_local);
+            at_server_local = RT_NULL;
         }
 
         LOG_E("RT-Thread AT server (V%s) initialize failed(%d).", AT_SW_VERSION, result);

+ 3 - 0
components/net/sal/impl/af_inet_at.c

@@ -81,6 +81,8 @@ static const struct sal_socket_ops at_socket_ops =
     NULL,
 #endif
     at_sendto,
+    NULL,
+    NULL,
     at_recvfrom,
     at_getsockopt,
     at_setsockopt,
@@ -88,6 +90,7 @@ static const struct sal_socket_ops at_socket_ops =
     NULL,
     NULL,
     NULL,
+    NULL,
 #ifdef SAL_USING_POSIX
     at_poll,
 #endif /* SAL_USING_POSIX */