This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
The following commit(s) were added to refs/heads/master by this push:
new b0b90ac72 apps/net: add http connectivity check API
b0b90ac72 is described below
commit b0b90ac72886a7d2ee8d9a16e057a4b2c801984e
Author: meijian <[email protected]>
AuthorDate: Mon Oct 14 20:36:13 2024 +0800
apps/net: add http connectivity check API
Add netlib_check_httpconnectivity() to verify HTTP service connectivity by
sending GET request and validating status code.
Signed-off-by: meijian <[email protected]>
---
include/netutils/netlib.h | 4 +
netutils/netlib/CMakeLists.txt | 2 +
netutils/netlib/Makefile | 2 +
netutils/netlib/netlib_checkhttpconnectivity.c | 265 +++++++++++++++++++++++++
4 files changed, 273 insertions(+)
diff --git a/include/netutils/netlib.h b/include/netutils/netlib.h
index b28b880df..43febfcda 100644
--- a/include/netutils/netlib.h
+++ b/include/netutils/netlib.h
@@ -526,6 +526,10 @@ int netlib_check_ifconnectivity(FAR const char *ifname,
int netlib_get_iobinfo(FAR struct iob_stats_s *iob);
#endif
+int netlib_check_httpconnectivity(FAR const char *host,
+ FAR const char *getmsg,
+ int port, int expect_code);
+
#undef EXTERN
#ifdef __cplusplus
}
diff --git a/netutils/netlib/CMakeLists.txt b/netutils/netlib/CMakeLists.txt
index be87f33fa..49e8aa81e 100644
--- a/netutils/netlib/CMakeLists.txt
+++ b/netutils/netlib/CMakeLists.txt
@@ -161,6 +161,8 @@ if(CONFIG_NETUTILS_NETLIB)
list(APPEND SRCS netlib_checkipconnectivity.c netlib_checkifconnectivity.c)
endif()
+ list(APPEND SRCS netlib_checkhttpconnectivity.c)
+
target_sources(apps PRIVATE ${SRCS})
endif()
diff --git a/netutils/netlib/Makefile b/netutils/netlib/Makefile
index a55340c1f..4bfc8d9d4 100644
--- a/netutils/netlib/Makefile
+++ b/netutils/netlib/Makefile
@@ -160,4 +160,6 @@ ifeq ($(CONFIG_NETUTILS_PING),y)
CSRCS += netlib_checkipconnectivity.c netlib_checkifconnectivity.c
endif
+CSRCS += netlib_checkhttpconnectivity.c
+
include $(APPDIR)/Application.mk
diff --git a/netutils/netlib/netlib_checkhttpconnectivity.c
b/netutils/netlib/netlib_checkhttpconnectivity.c
new file mode 100644
index 000000000..c29d86292
--- /dev/null
+++ b/netutils/netlib/netlib_checkhttpconnectivity.c
@@ -0,0 +1,265 @@
+/****************************************************************************
+ * apps/netutils/netlib/netlib_checkhttpconnectivity.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <debug.h>
+
+#ifdef CONFIG_LIBC_NETDB
+# include <netdb.h>
+#endif
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: eai_to_errno
+ *
+ * Description:
+ * Convert EAI_* error code to errno value for unified error handling.
+ *
+ * Parameters:
+ * eai_error The EAI_* error code from getaddrinfo().
+ *
+ * Return:
+ * Corresponding errno value.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_LIBC_NETDB
+static int eai_to_errno(int eai_error)
+{
+ switch (eai_error)
+ {
+ case EAI_AGAIN:
+ return EAGAIN; /* Temporary failure, try again */
+
+ case EAI_BADFLAGS:
+ return EINVAL; /* Invalid flags */
+
+ case EAI_FAIL:
+ return EHOSTUNREACH; /* Non-recoverable failure */
+
+ case EAI_FAMILY:
+ return EAFNOSUPPORT; /* Address family not supported */
+
+ case EAI_MEMORY:
+ return ENOMEM; /* Memory allocation failure */
+
+ case EAI_NONAME:
+ return EHOSTUNREACH; /* Host name not found */
+
+ case EAI_SERVICE:
+ return EINVAL; /* Service not recognized */
+
+ case EAI_SOCKTYPE:
+ return EINVAL; /* Socket type not supported */
+
+ case EAI_SYSTEM:
+ return errno; /* System error, use errno */
+
+ case EAI_OVERFLOW:
+ return EOVERFLOW; /* Buffer overflow */
+
+ default:
+ return EINVAL; /* Unknown error, use invalid argument */
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: httpget_gethostip
+ *
+ * Description:
+ * Check the http status code
+ *
+ * Parameters:
+ * hostname The host name to use in the nslookup.
+ * dest The location to return the IPv4 address.
+ *
+ * Return:
+ * 0 on success; a negative errno value on failure.
+ *
+ ****************************************************************************/
+
+static int httpget_gethostip(FAR const char *hostname,
+ FAR struct in_addr *dest)
+{
+#ifdef CONFIG_LIBC_NETDB
+ /* Netdb DNS client support is enabled */
+
+ int ret;
+ FAR struct addrinfo hint;
+ FAR struct addrinfo *info;
+ FAR struct sockaddr_in *addr;
+
+ memset(&hint, 0, sizeof(hint));
+ hint.ai_family = AF_INET;
+
+ ret = getaddrinfo(hostname, NULL, &hint, &info);
+ if (ret != OK)
+ {
+ return -eai_to_errno(ret);
+ }
+
+ addr = (FAR struct sockaddr_in *)info->ai_addr;
+ memcpy(dest, &addr->sin_addr, sizeof(struct in_addr));
+
+ freeaddrinfo(info);
+ return OK;
+
+#else /* CONFIG_LIBC_NETDB */
+ /* No host name support */
+
+ /* Convert strings to numeric IPv4 address */
+
+ int ret = inet_pton(AF_INET, hostname, dest);
+
+ /* The inet_pton() function returns 1 if the conversion succeeds. It will
+ * return 0 if the input is not a valid IPv4 dotted-decimal string or -1
+ * with errno set to EAFNOSUPPORT if the address family argument is
+ * unsupported.
+ */
+
+ if (ret != 1)
+ {
+ /* ret == 0: invalid IP address string, set errno to EINVAL
+ * ret == -1: system error, errno is already set to EAFNOSUPPORT
+ */
+
+ if (ret == 0)
+ {
+ set_errno(EINVAL);
+ }
+
+ return -errno;
+ }
+
+ return OK;
+
+#endif /* CONFIG_LIBC_NETDB */
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: netlib_check_httpconnectivity
+ *
+ * Description:
+ * Check the http status code
+ *
+ * Parameters:
+ * host The remote host to check
+ * getmsg The http GET message
+ * port The port of remote host
+ * expect_code The except http code of http code
+ *
+ * Return:
+ * 0 on success; a nagtive on failure.
+ *
+ ****************************************************************************/
+
+int netlib_check_httpconnectivity(FAR const char *host,
+ FAR const char *getmsg,
+ int port, int expect_code)
+{
+ int sock;
+ int ret;
+ int status_code = -1;
+ struct sockaddr_in server_addr;
+ char buf[256];
+
+ ret = httpget_gethostip(host, &server_addr.sin_addr);
+ if (ret < 0)
+ {
+ nerr("Failed to get host ip");
+ return ret;
+ }
+
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock < 0)
+ {
+ nerr("Failed to create socket");
+ return -errno;
+ }
+
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = htons(port);
+
+ ret = connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
+ if (ret < 0)
+ {
+ perror("Connection failed");
+ goto exit_with_socket;
+ }
+
+ snprintf(buf, sizeof(buf),
+ "GET /%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n",
+ getmsg, host);
+
+ ret = send(sock, buf, strlen(buf), 0);
+ if (ret < 0)
+ {
+ perror("send failed");
+ goto exit_with_socket;
+ }
+
+ if ((ret = recv(sock, buf, sizeof(buf), 0)) < 0)
+ {
+ perror("recv failed");
+ goto exit_with_socket;
+ }
+
+ /* get the http code, and check with except code */
+
+ if (sscanf(buf, "HTTP/1.1 %d", &status_code) == 1 &&
+ status_code == expect_code)
+ {
+ ninfo("HTTP connectivity is ok");
+ ret = OK;
+ }
+ else
+ {
+ nerr("HTTP connectivity is not ok status code: %d\n", status_code);
+ ret = -status_code;
+ }
+
+exit_with_socket:
+ close(sock);
+ return ret;
+}