From cca2f40ae05a6eff108febbf39c7198a9c64c9ea Mon Sep 17 00:00:00 2001 From: liuxianliang Date: Thu, 2 Jun 2022 19:47:12 +0800 Subject: [PATCH] [add] implement about "AT server". --- components/net/at/Kconfig | 8 + components/net/at/at_socket/at_socket.c | 279 +++++++++++++++++++++++- components/net/at/at_socket/at_socket.h | 32 +++ components/net/sal/impl/af_inet_at.c | 8 + 4 files changed, 325 insertions(+), 2 deletions(-) diff --git a/components/net/at/Kconfig b/components/net/at/Kconfig index 59a367df4b..43c2bec1b6 100644 --- a/components/net/at/Kconfig +++ b/components/net/at/Kconfig @@ -60,6 +60,14 @@ if RT_USING_AT select SAL_USING_AT default n + if AT_USING_SOCKET + + config AT_USING_SOCKET_SERVER + bool "Enable BSD Socket API support about AT server" + default n + + endif + endif if AT_USING_SERVER || AT_USING_CLIENT diff --git a/components/net/at/at_socket/at_socket.c b/components/net/at/at_socket/at_socket.c index cf15b590e0..3b04cc5b36 100644 --- a/components/net/at/at_socket/at_socket.c +++ b/components/net/at/at_socket/at_socket.c @@ -6,9 +6,13 @@ * Change Logs: * Date Author Notes * 2018-06-06 chenyong first version + * 2022-06-02 xianxistu add implement about "AT server" */ #include +#ifdef AT_USING_SOCKET_SERVER +#include +#endif #include #include #include @@ -48,6 +52,9 @@ typedef enum { AT_EVENT_ERROR, } at_event_t; +#ifdef AT_USING_SOCKET_SERVER +static void at_connect_notice_cb(struct at_socket *sock, at_socket_evt_t event, const char *buff, size_t bfsz); +#endif /* the global of sockets list */ static rt_slist_t _socket_list = RT_SLIST_OBJECT_INIT(_socket_list); @@ -78,6 +85,34 @@ struct at_socket *at_get_socket(int socket) return RT_NULL; } +#ifdef AT_USING_SOCKET_SERVER +struct at_socket *at_get_base_socket(int base_socket) +{ + rt_base_t level; + 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) + { + at_sock = rt_slist_entry(node, struct at_socket, list); + if (base_socket == (int)at_sock->user_data && at_sock->state != AT_SOCKET_LISTEN) + { + 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; +} +#endif + /* get a block to the AT socket receive list*/ static rt_err_t at_recvpkt_put(rt_slist_t *rlist, const char *ptr, size_t length) { @@ -457,6 +492,9 @@ int at_socket(int domain, int type, int protocol) /* set AT socket receive data callback function */ 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); +#ifdef AT_USING_SOCKET_SERVER + sock->ops->at_set_event_cb(AT_SOCKET_EVT_CONNECTED, at_connect_notice_cb); +#endif return sock->socket; } @@ -587,6 +625,26 @@ static int socketaddr_to_ipaddr_port(const struct sockaddr *sockaddr, ip_addr_t return 0; } +#ifdef AT_USING_SOCKET_SERVER +/* set socketaddr structure information by IP address and port */ +static int ipaddr_port_to_socketaddr(struct sockaddr *sockaddr, ip_addr_t *addr, uint16_t *port) +{ + struct sockaddr_in* sin = (struct sockaddr_in*) (void *) sockaddr; + +#if NETDEV_IPV4 && NETDEV_IPV6 + sin->sin_addr.s_addr = addr->u_addr.ip4.addr; +#elif NETDEV_IPV4 + sin->sin_addr.s_addr = addr->addr; +#elif NETDEV_IPV6 +#error "not support IPV6." +#endif /* NETDEV_IPV4 && NETDEV_IPV6 */ + + sin->sin_port = (uint16_t) HTONS_PORT(*port); + + return 0; +} +#endif + int at_bind(int socket, const struct sockaddr *name, socklen_t namelen) { struct at_socket *sock = RT_NULL; @@ -608,7 +666,7 @@ int at_bind(int socket, const struct sockaddr *name, socklen_t namelen) 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) + if (ip_addr_cmp(&input_ipaddr, &local_ipaddr) != 0) { struct at_socket *new_sock = RT_NULL; struct at_device *new_device = RT_NULL; @@ -637,6 +695,11 @@ int at_bind(int socket, const struct sockaddr *name, socklen_t namelen) new_sock->state = AT_SOCKET_OPEN; } +#ifdef AT_USING_SOCKET_SERVER + /* store 'port' into at_socket */ + sock->listen.port = port; +#endif + return 0; } @@ -651,6 +714,103 @@ static int ipaddr_to_ipstr(const struct sockaddr *sockaddr, char *ipstr) return 0; } +#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; + struct at_socket *new_sock = RT_NULL; + rt_base_t level; + rt_slist_t *node = RT_NULL; + struct at_socket *at_sock = RT_NULL; + 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) + { + return; + } + new_sock->type = AT_SOCKET_TCP; + 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(); + rt_slist_for_each(node, &_socket_list) + { + at_sock = rt_slist_entry(node, struct at_socket, list); + if (at_sock && at_sock->magic == AT_SOCKET_MAGIC && at_sock->listen.is_listen == RT_TRUE) + { + break; + } + at_sock = RT_NULL; + } + rt_hw_interrupt_enable(level); + + if(at_sock == RT_NULL) + { + return; + } + + /* 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); + rt_mutex_release(at_sock->recv_lock); + return; + } + rt_mutex_release(at_sock->recv_lock); + rt_sem_release(at_sock->recv_notice); + + at_do_event_changes(at_sock, AT_EVENT_RECV, RT_TRUE); +} +#endif + static void at_recv_notice_cb(struct at_socket *sock, at_socket_evt_t event, const char *buff, size_t bfsz) { RT_ASSERT(buff); @@ -695,6 +855,49 @@ static void at_closed_notice_cb(struct at_socket *sock, at_socket_evt_t event, c rt_sem_release(sock->recv_notice); } +#ifdef AT_USING_SOCKET_SERVER +int at_listen(int socket, int backlog) +{ + struct at_socket *sock = RT_NULL; + int result = 0; + + sock = at_get_socket(socket); + if (sock == RT_NULL) + { + result = -1; + goto __exit; + } + + if (sock->state != AT_SOCKET_OPEN) + { + LOG_E("Socket(%d) connect state is %d.", sock->socket, sock->state); + result = -1; + goto __exit; + } + + if (sock->ops->at_listen(sock, backlog) < 0) + { + result = -1; + goto __exit; + } + + sock->listen.is_listen = RT_TRUE; + sock->state = AT_SOCKET_LISTEN; + +__exit: + + if (result < 0) + { + if (sock != RT_NULL) + { + at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE); + } + } + + return result; +} +#endif + int at_connect(int socket, const struct sockaddr *name, socklen_t namelen) { struct at_socket *sock = RT_NULL; @@ -747,6 +950,71 @@ __exit: return result; } +#ifdef AT_USING_SOCKET_SERVER +int at_accept(int socket, struct sockaddr *name, socklen_t *namelen) +{ + struct at_socket *sock = RT_NULL; + struct at_socket *new_sock = RT_NULL; + char receive_buff[AT_SOCKET_INFO_LEN]; + ip_addr_t remote_addr; + uint16_t remote_port = 0; + int new_socket = -1; + int result = 0; + + sock = at_get_socket(socket); + if (sock == RT_NULL) + { + result = -1; + goto __exit; + } + + if (sock->state != AT_SOCKET_LISTEN) + { + LOG_E("Socket(%d) connect state is %d.", sock->socket, sock->state); + result = -1; + goto __exit; + } + + /* wait the receive semaphore, waiting for info */ + if (rt_sem_take(sock->recv_notice, RT_WAITING_FOREVER) < 0) + { + errno = EAGAIN; + result = -1; + goto __exit; + } + else + { + /* get receive buffer to receiver ring buffer */ + 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); + } + + 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); + +__exit: + if (result < 0) + { + if (sock != RT_NULL) + { + at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE); + } + } + + return new_sock->socket; +} +#endif + int at_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) { struct at_socket *sock = RT_NULL; @@ -843,7 +1111,14 @@ int at_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *f { break; } - + else + { + /* we have no data to receive but are woken up, + which means the socket have been closed. */ + errno = EIO; + result = -1; + goto __exit; + } } } diff --git a/components/net/at/at_socket/at_socket.h b/components/net/at/at_socket/at_socket.h index caac6d2d5d..97c158fac5 100644 --- a/components/net/at/at_socket/at_socket.h +++ b/components/net/at/at_socket/at_socket.h @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2018-06-06 chenYong first version + * 2022-06-02 xianxistu add implement about "AT server" */ #ifndef __AT_SOCKET_H__ @@ -32,6 +33,10 @@ extern "C" { /* sal socket magic word */ #define AT_SOCKET_MAGIC 0xA100 +#ifdef AT_USING_SOCKET_SERVER +#define AT_SOCKET_INFO_LEN (sizeof("SOCKET:") + 4) +#endif + /* Current state of the AT socket. */ enum at_socket_state { @@ -53,6 +58,9 @@ typedef enum { AT_SOCKET_EVT_RECV, AT_SOCKET_EVT_CLOSED, +#ifdef AT_USING_SOCKET_SERVER + AT_SOCKET_EVT_CONNECTED, +#endif } at_socket_evt_t; struct at_socket; @@ -72,6 +80,9 @@ struct at_socket_ops 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); int (*at_socket)(struct at_device *device, enum at_socket_type type); +#ifdef AT_USING_SOCKET_SERVER + int (*at_listen)(struct at_socket *socket, int backlog); +#endif }; /* AT receive package list structure */ @@ -84,12 +95,24 @@ struct at_recv_pkt }; typedef struct at_recv_pkt *at_recv_pkt_t; +#ifdef AT_USING_SOCKET_SERVER +struct at_listen_state +{ + uint16_t is_listen; + uint16_t port; +}; +#endif + struct at_socket { /* AT socket magic word */ uint32_t magic; int socket; +#ifdef AT_USING_SOCKET_SERVER + struct at_listen_state listen; +#endif + /* device releated information for the socket */ void *device; /* type of the AT socket (TCP, UDP or RAW) */ @@ -129,7 +152,13 @@ int at_socket(int domain, int type, int protocol); int at_closesocket(int socket); int at_shutdown(int socket, int how); int at_bind(int socket, const struct sockaddr *name, socklen_t namelen); +#ifdef AT_USING_SOCKET_SERVER +int at_listen(int socket, int backlog); +#endif int at_connect(int socket, const struct sockaddr *name, socklen_t namelen); +#ifdef AT_USING_SOCKET_SERVER +int at_accept(int socket, struct sockaddr *name, socklen_t *namelen); +#endif int at_sendto(int socket, const void *data, size_t size, int flags, const struct sockaddr *to, socklen_t tolen); int at_send(int socket, const void *data, size_t size, int flags); int at_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen); @@ -141,6 +170,9 @@ 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); +#ifdef AT_USING_SOCKET_SERVER +struct at_socket *at_get_base_socket(int base_socket); +#endif #ifndef RT_USING_SAL diff --git a/components/net/sal/impl/af_inet_at.c b/components/net/sal/impl/af_inet_at.c index e5cc8720f6..30c5324447 100644 --- a/components/net/sal/impl/af_inet_at.c +++ b/components/net/sal/impl/af_inet_at.c @@ -69,9 +69,17 @@ static const struct sal_socket_ops at_socket_ops = at_socket, at_closesocket, at_bind, +#ifdef AT_USING_SOCKET_SERVER + at_listen, +#else NULL, +#endif at_connect, +#ifdef AT_USING_SOCKET_SERVER + at_accept, +#else NULL, +#endif at_sendto, at_recvfrom, at_getsockopt, -- GitLab