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;
+}

Reply via email to