@@ -83,9 +83,11 @@ static struct sm_socket {
8383 int family ; /* Socket address family */
8484 int fd ; /* Socket descriptor. */
8585 uint16_t cid ; /* PDP Context ID, 0: primary; 1~10: secondary */
86+ uint16_t local_port ; /* Explicitly bound local port. */
8687 int send_flags ; /* Send flags */
8788 bool send_cb_set : 1 ; /* Send callback set */
8889 bool connected : 1 ; /* Connected flag. */
90+ bool listen : 1 ; /* Listen flag for TCP server sockets. */
8991 struct sm_async_poll async_poll ; /* Async poll info. */
9092 struct sm_send_ntf send_ntf ; /* Send notification info. */
9193} socks [SM_MAX_SOCKET_COUNT ];
@@ -120,9 +122,11 @@ static void init_socket(struct sm_socket *socket)
120122 socket -> family = AF_UNSPEC ;
121123 socket -> fd = INVALID_SOCKET ;
122124 socket -> cid = 0 ;
125+ socket -> local_port = 0 ;
123126 socket -> send_flags = 0 ;
124127 socket -> send_cb_set = false;
125128 socket -> connected = false;
129+ socket -> listen = false;
126130 socket -> send_ntf = (struct sm_send_ntf ){0 };
127131 socket -> async_poll = (struct sm_async_poll ){0 };
128132}
@@ -877,7 +881,7 @@ static int sec_sockopt_get(struct sm_socket *sock, enum at_sec_sockopt at_option
877881 return ret ;
878882}
879883
880- int bind_to_local_addr (struct sm_socket * sock , uint16_t port )
884+ static int bind_to_local_addr (struct sm_socket * sock , uint16_t port )
881885{
882886 int ret ;
883887
@@ -936,6 +940,7 @@ int bind_to_local_addr(struct sm_socket *sock, uint16_t port)
936940 return - EINVAL ;
937941 }
938942
943+ sock -> local_port = port ;
939944 return 0 ;
940945}
941946
@@ -1955,6 +1960,161 @@ STATIC int handle_at_recvfrom(enum at_parser_cmd_type cmd_type, struct at_parser
19551960 return err ;
19561961}
19571962
1963+ int do_listen (struct sm_socket * sock )
1964+ {
1965+ int ret ;
1966+
1967+ if (sock -> type != NRF_SOCK_STREAM || sock -> local_port == 0 ||
1968+ sock -> sec_tag != SEC_TAG_TLS_INVALID ) {
1969+ return - EOPNOTSUPP ;
1970+ }
1971+
1972+ /* Set the socket to non-blocking mode, so accept() won't block. */
1973+ ret = nrf_fcntl (sock -> fd , NRF_F_SETFL , NRF_O_NONBLOCK );
1974+ if (ret ) {
1975+ LOG_ERR ("nrf_fcntl() failed: %d" , - errno );
1976+ return - errno ;
1977+ }
1978+
1979+ /* nRF modem ignores the backlog parameter. Backlog in modem is fixed to 2. */
1980+ ret = nrf_listen (sock -> fd , 2 );
1981+ if (ret ) {
1982+ LOG_ERR ("nrf_listen() failed: %d" , - errno );
1983+ return - errno ;
1984+ }
1985+
1986+ sock -> role = AT_SOCKET_ROLE_SERVER ;
1987+ sock -> listen = true;
1988+
1989+ return 0 ;
1990+ }
1991+
1992+ SM_AT_CMD_CUSTOM (xlisten , "AT#XLISTEN" , handle_at_listen );
1993+ STATIC int handle_at_listen (enum at_parser_cmd_type cmd_type , struct at_parser * parser , uint32_t )
1994+ {
1995+ int err = - EINVAL ;
1996+ int fd ;
1997+
1998+ struct sm_socket * sock = NULL ;
1999+
2000+ switch (cmd_type ) {
2001+ case AT_PARSER_CMD_TYPE_SET :
2002+ err = at_parser_num_get (parser , 1 , & fd );
2003+ if (err ) {
2004+ return err ;
2005+ }
2006+ sock = find_socket (fd );
2007+ if (sock == NULL ) {
2008+ return - EINVAL ;
2009+ }
2010+ err = do_listen (sock );
2011+ break ;
2012+
2013+ case AT_PARSER_CMD_TYPE_READ :
2014+ for (int i = 0 ; i < SM_MAX_SOCKET_COUNT ; i ++ ) {
2015+ if (socks [i ].fd != INVALID_SOCKET && socks [i ].listen ) {
2016+ rsp_send ("\r\n#XLISTEN: %d,%d,%d\r\n" , socks [i ].fd , socks [i ].cid ,
2017+ socks [i ].local_port );
2018+ }
2019+ }
2020+ err = 0 ;
2021+ break ;
2022+
2023+ case AT_PARSER_CMD_TYPE_TEST :
2024+ rsp_send ("\r\n#XLISTEN: <handle>\r\n" );
2025+ err = 0 ;
2026+ break ;
2027+
2028+ default :
2029+ break ;
2030+ }
2031+
2032+ return err ;
2033+ }
2034+
2035+ int do_accept (struct sm_socket * sock )
2036+ {
2037+ int ret ;
2038+ struct sockaddr remote ;
2039+ socklen_t addrlen = sizeof (struct sockaddr );
2040+ char peer_addr [NRF_INET6_ADDRSTRLEN ] = {0 };
2041+ uint16_t peer_port = 0 ;
2042+
2043+ if (sock -> type != NRF_SOCK_STREAM || !sock -> listen ) {
2044+ return - EOPNOTSUPP ;
2045+ }
2046+
2047+ ret = nrf_accept (sock -> fd , (struct nrf_sockaddr * )& remote , (nrf_socklen_t * )& addrlen );
2048+ if (ret < 0 ) {
2049+ LOG_ERR ("nrf_accept() failed: %d" , - errno );
2050+ return - errno ;
2051+ }
2052+
2053+ struct sm_socket * new_sock = find_avail_socket ();
2054+ if (new_sock == NULL ) {
2055+ LOG_ERR ("Max socket count reached, closing accepted socket" );
2056+ nrf_close (ret );
2057+ return - EINVAL ;
2058+ }
2059+ init_socket (new_sock );
2060+ new_sock -> fd = ret ;
2061+ new_sock -> family = remote .sa_family ;
2062+ new_sock -> type = NRF_SOCK_STREAM ;
2063+ new_sock -> role = AT_SOCKET_ROLE_SERVER ;
2064+ new_sock -> cid = sock -> cid ;
2065+ new_sock -> connected = true;
2066+
2067+ util_get_peer_addr (& remote , peer_addr , & peer_port );
2068+ rsp_send ("\r\n#XACCEPT: %d,%d,\"%s\",%d\r\n" , new_sock -> fd , new_sock -> cid , peer_addr ,
2069+ peer_port );
2070+
2071+ /* Update poll events for xapoll and automatic data reception */
2072+ new_sock -> async_poll .adr_flags = poll_ctx .adr_flags ;
2073+ new_sock -> async_poll .adr_hex = poll_ctx .adr_hex ;
2074+ new_sock -> async_poll .xapoll_events_requested = poll_ctx .xapoll_events_requested ;
2075+ update_poll_events (new_sock ,
2076+ NRF_POLLIN | NRF_POLLOUT | NRF_POLLERR | NRF_POLLHUP | NRF_POLLNVAL ,
2077+ true);
2078+
2079+ /* Restore POLLIN for listening socket. */
2080+ update_poll_events (sock , NRF_POLLIN , true);
2081+
2082+ return 0 ;
2083+ }
2084+
2085+ SM_AT_CMD_CUSTOM (xaccept , "AT#XACCEPT" , handle_at_accept );
2086+ STATIC int handle_at_accept (enum at_parser_cmd_type cmd_type , struct at_parser * parser , uint32_t )
2087+ {
2088+ int err = - EINVAL ;
2089+ int fd ;
2090+
2091+ struct sm_socket * sock = NULL ;
2092+
2093+ switch (cmd_type ) {
2094+ case AT_PARSER_CMD_TYPE_SET :
2095+ err = at_parser_num_get (parser , 1 , & fd );
2096+ if (err ) {
2097+ return err ;
2098+ }
2099+ sock = find_socket (fd );
2100+ if (sock == NULL ) {
2101+ return - EINVAL ;
2102+ }
2103+ err = do_accept (sock );
2104+ break ;
2105+
2106+ case AT_PARSER_CMD_TYPE_TEST :
2107+ rsp_send ("\r\n#XACCEPT: <handle>\r\n" );
2108+ err = 0 ;
2109+ break ;
2110+
2111+ default :
2112+ break ;
2113+ }
2114+
2115+ return err ;
2116+ }
2117+
19582118SM_AT_CMD_CUSTOM (xgetaddrinfo , "AT#XGETADDRINFO" , handle_at_getaddrinfo );
19592119STATIC int handle_at_getaddrinfo (enum at_parser_cmd_type cmd_type , struct at_parser * parser ,
19602120 uint32_t param_count )
0 commit comments