From 2f87894e580d339abc3f78c96a6a7579a758f5c1 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 23 Jan 2024 17:10:19 +0100 Subject: [PATCH 1/2] fix(netif): Add missing SNTP get-reachablitiy API --- components/esp_netif/include/esp_netif_sntp.h | 13 +++++++++- components/esp_netif/lwip/esp_netif_sntp.c | 14 +++++++++- .../test_app_esp_netif/main/esp_netif_test.c | 15 ++++++++++- components/lwip/apps/sntp/sntp.c | 16 +++++++++++- components/lwip/include/apps/esp_sntp.h | 26 ++++++++++++++++++- components/lwip/test_apps/main/lwip_test.c | 10 ++++++- 6 files changed, 88 insertions(+), 6 deletions(-) diff --git a/components/esp_netif/include/esp_netif_sntp.h b/components/esp_netif/include/esp_netif_sntp.h index 87f1245d5a..51d7e42bd4 100644 --- a/components/esp_netif/include/esp_netif_sntp.h +++ b/components/esp_netif/include/esp_netif_sntp.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -107,6 +107,17 @@ void esp_netif_sntp_deinit(void); */ esp_err_t esp_netif_sntp_sync_wait(TickType_t tout); +/** + * @brief Returns SNTP server's reachability shift register as described in RFC 5905. + * + * @param index Index of the SERVER + * @param reachability reachability shift register + * @return ESP_OK on success, + * ESP_ERR_INVALID_STATE if SNTP not initialized + * ESP_ERR_INVALID_ARG if invalid arguments + */ +esp_err_t esp_netif_sntp_reachability(unsigned int index, unsigned int *reachability); + /** * @} */ diff --git a/components/esp_netif/lwip/esp_netif_sntp.c b/components/esp_netif/lwip/esp_netif_sntp.c index 1aadcbef69..e6fe54f37f 100644 --- a/components/esp_netif/lwip/esp_netif_sntp.c +++ b/components/esp_netif/lwip/esp_netif_sntp.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -177,3 +177,15 @@ esp_err_t esp_netif_sntp_start(void) { return esp_netif_tcpip_exec(sntp_start_api, NULL); } + +esp_err_t esp_netif_sntp_reachability(unsigned int index, unsigned int *reachability) +{ + if (index >= SNTP_MAX_SERVERS || reachability == NULL) { + return ESP_ERR_INVALID_ARG; + } + if (s_storage == NULL || sntp_enabled() == 0) { + return ESP_ERR_INVALID_STATE; + } + *reachability = sntp_getreachability(index); + return ESP_OK; +} diff --git a/components/esp_netif/test_apps/test_app_esp_netif/main/esp_netif_test.c b/components/esp_netif/test_apps/test_app_esp_netif/main/esp_netif_test.c index 472a8de7ad..79f70ac27a 100644 --- a/components/esp_netif/test_apps/test_app_esp_netif/main/esp_netif_test.c +++ b/components/esp_netif/test_apps/test_app_esp_netif/main/esp_netif_test.c @@ -48,7 +48,20 @@ TEST(esp_netif, init_and_destroy_sntp) { esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("127.0.0.1"); config.start = false; - esp_netif_sntp_init(&config); + TEST_ESP_OK(esp_netif_sntp_init(&config)); + // Cannot initialize multiple times + TEST_ASSERT_NOT_EQUAL(ESP_OK, esp_netif_sntp_init(&config)); + // Try again to see that the state didn't change + TEST_ASSERT_NOT_EQUAL(ESP_OK, esp_netif_sntp_init(&config)); + esp_netif_sntp_deinit(); + + // Can initialize again once it's destroyed + TEST_ESP_OK(esp_netif_sntp_init(&config)); + + // Test the reachability API + size_t reachability = 0; + // Invalid state is expected since SNTP service didn't start + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, esp_netif_sntp_reachability(0, &reachability)); esp_netif_sntp_deinit(); } diff --git a/components/lwip/apps/sntp/sntp.c b/components/lwip/apps/sntp/sntp.c index 3b8cf283ae..8d8fbfbe90 100644 --- a/components/lwip/apps/sntp/sntp.c +++ b/components/lwip/apps/sntp/sntp.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -243,6 +243,20 @@ const ip_addr_t* esp_sntp_getserver(u8_t idx) return sntp_getserver(idx); } +uint8_t esp_sntp_getreachability(uint8_t idx) +{ +#if SNTP_MONITOR_SERVER_REACHABILITY + return sntp_getreachability(idx); +#endif + LWIP_ERROR("sntp_getreachability() in not enabled in lwipopts", false, ); + return 0; +} + +esp_sntp_operatingmode_t esp_sntp_getoperatingmode(void) +{ + return (esp_sntp_operatingmode_t)sntp_getoperatingmode(); +} + #if LWIP_DHCP_GET_NTP_SRV static void do_servermode_dhcp(void* ctx) { diff --git a/components/lwip/include/apps/esp_sntp.h b/components/lwip/include/apps/esp_sntp.h index 80d2a88129..162cb3ece2 100644 --- a/components/lwip/include/apps/esp_sntp.h +++ b/components/lwip/include/apps/esp_sntp.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -218,6 +218,20 @@ const ip_addr_t* esp_sntp_getserver(u8_t idx); */ bool esp_sntp_enabled(void); +/** + * @brief Gets the server reachability shift register as described in RFC 5905. + * @param idx Index of the SNTP server + * @return reachability shift register + */ +uint8_t esp_sntp_getreachability(uint8_t idx); + +/** + * @brief Get the configured operating mode + * + * @return operating mode enum + */ +esp_sntp_operatingmode_t esp_sntp_getoperatingmode(void); + #if LWIP_DHCP_GET_NTP_SRV /** * @brief Enable acquiring SNTP server from DHCP @@ -269,6 +283,16 @@ const ip_addr_t* sntp_getserver(u8_t idx) return esp_sntp_getserver(idx); } +static inline uint8_t sntp_getreachability(uint8_t idx) +{ + return esp_sntp_getreachability(idx); +} + +static inline esp_sntp_operatingmode_t sntp_getoperatingmode(void) +{ + return esp_sntp_getoperatingmode(); +} + #endif /* ESP_LWIP_COMPONENT_BUILD */ diff --git a/components/lwip/test_apps/main/lwip_test.c b/components/lwip/test_apps/main/lwip_test.c index 6a34edeb43..a738c87611 100644 --- a/components/lwip/test_apps/main/lwip_test.c +++ b/components/lwip/test_apps/main/lwip_test.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -294,8 +294,16 @@ void test_sntp_timestamps(int year, bool msb_flag) localtime_r(&now, &timeinfo); TEST_ASSERT_EQUAL(year, 1900 + timeinfo.tm_year); + // Check that the server 0 was reachable + TEST_ASSERT_EQUAL(1, esp_sntp_getreachability(0)); // close the SNTP and the fake server esp_sntp_stop(); + + // Test some other SNTP APIs + TEST_ASSERT_EQUAL(0, esp_sntp_getreachability(0)); + TEST_ASSERT_EQUAL(ESP_SNTP_OPMODE_POLL, esp_sntp_getoperatingmode()); + const ip_addr_t *server_ip = esp_sntp_getserver(0); + TEST_ASSERT_EQUAL(PP_HTONL(IPADDR_LOOPBACK), server_ip->u_addr.ip4.addr); close(sock); } From cea1893729df5af57eb64d202263c4a34376443e Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 8 Jan 2024 11:09:35 +0100 Subject: [PATCH 2/2] fix(esp_netif): Prevent running esp_netif_sntp_init() multiple times Closes https://github.com/espressif/esp-idf/issues/12854 --- components/esp_netif/lwip/esp_netif_sntp.c | 1 + docs/en/api-reference/network/esp_netif.rst | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/components/esp_netif/lwip/esp_netif_sntp.c b/components/esp_netif/lwip/esp_netif_sntp.c index e6fe54f37f..1a7da5e442 100644 --- a/components/esp_netif/lwip/esp_netif_sntp.c +++ b/components/esp_netif/lwip/esp_netif_sntp.c @@ -91,6 +91,7 @@ void esp_netif_sntp_renew_servers(void *handler_args, esp_event_base_t base, int esp_err_t esp_netif_sntp_init(const esp_sntp_config_t * config) { esp_err_t ret = ESP_OK; + ESP_RETURN_ON_FALSE(s_storage == NULL, ESP_ERR_INVALID_STATE, TAG, "esp_netif_sntp already initialized"); s_storage = calloc(1, sizeof(sntp_storage_t) + // allocate space for servers only if we are supposed to refresh the settings (config->renew_servers_after_new_IP ? config->num_of_servers * sizeof(char*) : 0)); ESP_GOTO_ON_FALSE(s_storage != NULL, ESP_ERR_NO_MEM, err, TAG, "Failed to allocate SNTP storage"); diff --git a/docs/en/api-reference/network/esp_netif.rst b/docs/en/api-reference/network/esp_netif.rst index 4158166958..7610277e2a 100644 --- a/docs/en/api-reference/network/esp_netif.rst +++ b/docs/en/api-reference/network/esp_netif.rst @@ -253,8 +253,8 @@ You can find a brief introduction to SNTP in general, its initialization code an This section provides more details about specific use cases of SNTP service, with statically configured servers, or using DHCP provided servers, or both. The workflow is usually very simple: -1) Initialize and configure the service using :cpp:func:`esp_netif_sntp_init()`. -2) Start the service via :cpp:func:`esp_netif_sntp_start()`. This step is not needed if we auto-started the service in the previous step (default). It's useful to start the service explicitly after connecting, if we want to use DHCP obtained NTP servers. (This option needs to be enabled before connecting, but SNTP service should be started after) +1) Initialize and configure the service using :cpp:func:`esp_netif_sntp_init()`. This operations can only be called once (unless the SNTP service has been destroyed by :cpp:func:`esp_netif_sntp_deinit()`) +2) Start the service via :cpp:func:`esp_netif_sntp_start()`. This step is not needed if we auto-started the service in the previous step (default). It is useful to start the service explicitly after connecting if we want to use the DHCP-obtained NTP servers. Please note, this option needs to be enabled before connecting, but the SNTP service should be started after. 3) Wait for the system time to synchronize using :cpp:func:`esp_netif_sntp_sync_wait()` (only if needed). 4) Stop and destroy the service using :cpp:func:`esp_netif_sntp_deinit()`.