From 53c009e62631bae569fa849c6b6c9e70a10b3afe Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 17 Mar 2022 13:07:05 +0100 Subject: [PATCH] lwip: Update socket API to include port-version of sockets/netdb Added socket extention to the lwip hooks for implementing non-vanilla {get/set}sockopts() --- .../asio/port/include/esp_asio_config.h | 4 +- components/lwip/CMakeLists.txt | 1 + components/lwip/include/lwip/netdb.h | 31 +++++ .../lwip/sockets.h} | 44 +------ components/lwip/port/esp32/include/lwipopts.h | 2 +- .../lwip/port/esp32/include/sockets_ext.h | 24 ++++ .../lwip/port/esp32/include/sys/socket.h | 1 - components/lwip/port/esp32/sockets_ext.c | 108 ++++++++++++++++++ tools/ci/check_public_headers_exceptions.txt | 1 + 9 files changed, 171 insertions(+), 45 deletions(-) create mode 100644 components/lwip/include/lwip/netdb.h rename components/lwip/{port/esp32/include/esp_cpp_sockets.h => include/lwip/sockets.h} (66%) create mode 100644 components/lwip/port/esp32/include/sockets_ext.h create mode 100644 components/lwip/port/esp32/sockets_ext.c diff --git a/components/asio/port/include/esp_asio_config.h b/components/asio/port/include/esp_asio_config.h index d80717ed9a..f8e34d617a 100644 --- a/components/asio/port/include/esp_asio_config.h +++ b/components/asio/port/include/esp_asio_config.h @@ -19,9 +19,9 @@ # endif // CONFIG_COMPILER_RTTI // -// LWIP compatibility inet and address macros/functions +// Use system sockets // -# include "esp_cpp_sockets.h" +# include "sys/socket.h" // // Specific ASIO feature flags diff --git a/components/lwip/CMakeLists.txt b/components/lwip/CMakeLists.txt index d49b11022e..e2d35384eb 100644 --- a/components/lwip/CMakeLists.txt +++ b/components/lwip/CMakeLists.txt @@ -1,4 +1,5 @@ set(include_dirs + include include/apps include/apps/sntp lwip/src/include diff --git a/components/lwip/include/lwip/netdb.h b/components/lwip/include/lwip/netdb.h new file mode 100644 index 0000000000..cc395bac61 --- /dev/null +++ b/components/lwip/include/lwip/netdb.h @@ -0,0 +1,31 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include_next "lwip/netdb.h" +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(CONFIG_ESP_NETIF_TCPIP_LWIP_ORIG) || defined(CONFIG_ESP_NETIF_TCPIP_LWIP) + +static inline int gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) +{ return lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop); } +static inline struct hostent *gethostbyname(const char *name) +{ return lwip_gethostbyname(name); } +static inline void freeaddrinfo(struct addrinfo *ai) +{ lwip_freeaddrinfo(ai); } +static inline int getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res) +{ return lwip_getaddrinfo(nodename, servname, hints, res); } + +#endif // CONFIG_ESP_NETIF_TCPIP_LWIP_ORIG || CONFIG_ESP_NETIF_TCPIP_LWIP + +#ifdef __cplusplus +} +#endif diff --git a/components/lwip/port/esp32/include/esp_cpp_sockets.h b/components/lwip/include/lwip/sockets.h similarity index 66% rename from components/lwip/port/esp32/include/esp_cpp_sockets.h rename to components/lwip/include/lwip/sockets.h index e71dd36ab1..1b475e3719 100644 --- a/components/lwip/port/esp32/include/esp_cpp_sockets.h +++ b/components/lwip/include/lwip/sockets.h @@ -5,9 +5,8 @@ */ #pragma once -#include "sys/poll.h" -#include "lwip/sockets.h" -#include "netdb.h" +#include_next "lwip/sockets.h" +#include "sdkconfig.h" #ifdef __cplusplus extern "C" { @@ -15,44 +14,6 @@ extern "C" { #if defined(CONFIG_ESP_NETIF_TCPIP_LWIP_ORIG) || defined(CONFIG_ESP_NETIF_TCPIP_LWIP) -// lwIP's socket API is mostly implemented as macros, -// but ASIO uses the same symbols in different namespaces, where macros wouldn't work. -// Here we have to undefined the symbols for ASIO build and declare as standard functions -#undef getaddrinfo -#undef gethostbyname_r -#undef gethostbyname -#undef freeaddrinfo -#undef accept -#undef bind -#undef shutdown -#undef getpeername -#undef getsockname -#undef setsockopt -#undef setsockopt -#undef getsockopt -#undef closesocket -#undef connect -#undef listen -#undef recvmsg -#undef recv -#undef recvfrom -#undef sendmsg -#undef send -#undef sendto -#undef socket -#undef inet_ntop -#undef inet_pton -#undef poll -#undef select - -static inline int gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) -{ return lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop); } -static inline struct hostent *gethostbyname(const char *name) -{ return lwip_gethostbyname(name); } -static inline void freeaddrinfo(struct addrinfo *ai) -{ lwip_freeaddrinfo(ai); } -static inline int getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res) -{ return lwip_getaddrinfo(nodename, servname, hints, res); } static inline int accept(int s,struct sockaddr *addr,socklen_t *addrlen) { return lwip_accept(s,addr,addrlen); } static inline int bind(int s,const struct sockaddr *name, socklen_t namelen) @@ -91,6 +52,7 @@ static inline const char *inet_ntop(int af, const void *src, char *dst, socklen_ { return lwip_inet_ntop(af, src, dst, size); } static inline int inet_pton(int af, const char *src, void *dst) { return lwip_inet_pton(af, src, dst); } + #endif // CONFIG_ESP_NETIF_TCPIP_LWIP_ORIG || CONFIG_ESP_NETIF_TCPIP_LWIP #ifdef __cplusplus diff --git a/components/lwip/port/esp32/include/lwipopts.h b/components/lwip/port/esp32/include/lwipopts.h index 9f36d970ce..362283ad20 100644 --- a/components/lwip/port/esp32/include/lwipopts.h +++ b/components/lwip/port/esp32/include/lwipopts.h @@ -804,7 +804,7 @@ * While this helps code completion, it might conflict with existing libraries. * (only used if you use sockets.c) */ -#define LWIP_COMPAT_SOCKETS 1 +#define LWIP_COMPAT_SOCKETS 0 /** * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. diff --git a/components/lwip/port/esp32/include/sockets_ext.h b/components/lwip/port/esp32/include/sockets_ext.h new file mode 100644 index 0000000000..48ffcf61e1 --- /dev/null +++ b/components/lwip/port/esp32/include/sockets_ext.h @@ -0,0 +1,24 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define IPV6_MULTICAST_IF 0x300 +#define IPV6_MULTICAST_HOPS 0x301 +#define IPV6_MULTICAST_LOOP 0x302 + +struct lwip_sock; + +bool lwip_setsockopt_impl_ext(struct lwip_sock* sock, int level, int optname, const void *optval, uint32_t optlen, int *err); +bool lwip_getsockopt_impl_ext(struct lwip_sock* sock, int level, int optname, void *optval, uint32_t *optlen, int *err); +#ifdef __cplusplus +} +#endif diff --git a/components/lwip/port/esp32/include/sys/socket.h b/components/lwip/port/esp32/include/sys/socket.h index eaaa1e0fec..5ea4db4ab8 100644 --- a/components/lwip/port/esp32/include/sys/socket.h +++ b/components/lwip/port/esp32/include/sys/socket.h @@ -30,7 +30,6 @@ * */ -#include "esp_cpp_sockets.h" #include "lwip/sockets.h" /* SOMAXCONN is expected to be found in this header too, diff --git a/components/lwip/port/esp32/sockets_ext.c b/components/lwip/port/esp32/sockets_ext.c new file mode 100644 index 0000000000..fb1454b21b --- /dev/null +++ b/components/lwip/port/esp32/sockets_ext.c @@ -0,0 +1,108 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "lwip/sockets.h" +#include "lwip/priv/sockets_priv.h" +#include "lwip/api.h" +#include "lwip/sys.h" +#include "lwip/tcp.h" +#include "lwip/raw.h" +#include "lwip/udp.h" + +#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype) do { \ + if (((optlen) < sizeof(opttype)) || ((sock)->conn == NULL) || ((sock)->conn->pcb.tcp == NULL)) { *err=EINVAL; goto exit; } }while(0) + +#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, opttype, netconntype) do { \ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype); \ + if (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) != netconntype) { *err=ENOPROTOOPT; goto exit; } } while(0) + + +bool lwip_setsockopt_impl_ext(struct lwip_sock* sock, int level, int optname, const void *optval, socklen_t optlen, int *err) +{ +#if LWIP_IPV6 + if (level != IPPROTO_IPV6) +#endif /* LWIP_IPV6 */ + { + return false; + } + +#if LWIP_IPV6 + switch (optname) { + default: + return false; + case IPV6_MULTICAST_IF: /* NB: like IP_MULTICAST_IF, this takes an IP not an index */ + { + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); + udp_set_multicast_netif_index(sock->conn->pcb.udp, (u8_t)(*(const u8_t*)optval)); + } + break; + case IPV6_MULTICAST_HOPS: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); + udp_set_multicast_ttl(sock->conn->pcb.udp, (u8_t)(*(const u8_t*)optval)); + break; + case IPV6_MULTICAST_LOOP: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); + if (*(const u8_t*)optval) { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP); + } else { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP); + } + break; + } +exit: + return true; +#endif /* LWIP_IPV6 */ +} + +bool lwip_getsockopt_impl_ext(struct lwip_sock* sock, int level, int optname, void *optval, uint32_t *optlen, int *err) +{ +#if LWIP_IPV6 + if (level != IPPROTO_IPV6) +#endif /* LWIP_IPV6 */ + { + return false; + } + +#if LWIP_IPV6 + switch (optname) { + default: + return false; + case IPV6_MULTICAST_IF: /* NB: like IP_MULTICAST_IF, this returns an IP not an index */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { + *err = ENOPROTOOPT; + goto exit; + } + *(u8_t*)optval = udp_get_multicast_netif_index(sock->conn->pcb.udp); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt_ext(IPPROTO_IPV6, IPV6_MULTICAST_IF) = 0x%"X32_F"\n", + *(u32_t *)optval)); + break; + case IPV6_MULTICAST_HOPS: + printf("IPV6_MULTICAST_HOPS\n"); + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { + *err = ENOPROTOOPT; + goto exit; + } + *(u8_t*)optval = udp_get_multicast_ttl(sock->conn->pcb.udp); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt_ext(IPPROTO_IPV6, IP_MULTICAST_LOOP) = %d\n", + *(int *)optval)); + break; + case IPV6_MULTICAST_LOOP: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t); + if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_MULTICAST_LOOP) != 0) { + *(u8_t*)optval = 1; + } else { + *(u8_t*)optval = 0; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt_ext(IPPROTO_IPV6, IP_MULTICAST_LOOP) = %d\n", + *(int *)optval)); + break; + } +exit: + return true; +#endif /* LWIP_IPV6 */ +} diff --git a/tools/ci/check_public_headers_exceptions.txt b/tools/ci/check_public_headers_exceptions.txt index 6bb5848ba0..049116b585 100644 --- a/tools/ci/check_public_headers_exceptions.txt +++ b/tools/ci/check_public_headers_exceptions.txt @@ -143,5 +143,6 @@ components/openssl/include/openssl/ssl.h components/ulp/include/ulp_common.h components/ulp/include/esp32s2/ulp_riscv.h components/lwip/include/apps/sntp/sntp.h +components/lwip/include/lwip/sockets.h components/mbedtls/esp_crt_bundle/include/esp_crt_bundle.h components/wifi_provisioning/include/wifi_provisioning/scheme_softap.h