You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2021/11/29 08:05:01 UTC

[incubator-nuttx-apps] branch master updated: netutils/dhcpc: add non-blocking interface

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/incubator-nuttx-apps.git


The following commit(s) were added to refs/heads/master by this push:
     new e0fc53b  netutils/dhcpc: add non-blocking interface
e0fc53b is described below

commit e0fc53b23c8ff1c4390456e54d2fcf98a703f671
Author: songlinzhang <so...@xiaomi.com>
AuthorDate: Mon Oct 11 15:43:26 2021 +0800

    netutils/dhcpc: add non-blocking interface
    
    Signed-off-by: songlinzhang <so...@xiaomi.com>
---
 include/netutils/dhcpc.h |   4 ++
 netutils/dhcpc/dhcpc.c   | 152 +++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 145 insertions(+), 11 deletions(-)

diff --git a/include/netutils/dhcpc.h b/include/netutils/dhcpc.h
index b0fb5a1..8ec6707 100644
--- a/include/netutils/dhcpc.h
+++ b/include/netutils/dhcpc.h
@@ -63,6 +63,8 @@ struct dhcpc_state
   uint32_t       lease_time;      /* Lease expires in this number of seconds */
 };
 
+typedef void (*dhcpc_callback_t)(FAR struct dhcpc_state *presult);
+
 /****************************************************************************
  * Public Function Prototypes
  ****************************************************************************/
@@ -78,6 +80,8 @@ extern "C"
 FAR void *dhcpc_open(FAR const char *interface,
                      FAR const void *mac_addr, int mac_len);
 int  dhcpc_request(FAR void *handle, FAR struct dhcpc_state *presult);
+int  dhcpc_request_async(FAR void *handle, dhcpc_callback_t callback);
+void dhcpc_cancel(FAR void *handle);
 void dhcpc_close(FAR void *handle);
 
 #undef EXTERN
diff --git a/netutils/dhcpc/dhcpc.c b/netutils/dhcpc/dhcpc.c
index 008f16a..2ff771b 100644
--- a/netutils/dhcpc/dhcpc.c
+++ b/netutils/dhcpc/dhcpc.c
@@ -52,6 +52,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <debug.h>
+#include <pthread.h>
 
 #include <arpa/inet.h>
 #include <netinet/udp.h>
@@ -129,12 +130,15 @@ struct dhcp_msg
 struct dhcpc_state_s
 {
   FAR const char    *interface;
-  FAR const void    *ds_macaddr;
-  int                ds_maclen;
   int                sockfd;
   struct in_addr     ipaddr;
   struct in_addr     serverid;
   struct dhcp_msg    packet;
+  bool               cancel;
+  pthread_t          thread;              /* Thread ID of the DHCPC thread */
+  dhcpc_callback_t   callback;            /* Thread callback of the DHCPC thread */
+  int                maclen;
+  uint8_t            macaddr[1];
 };
 
 /****************************************************************************
@@ -229,11 +233,10 @@ static int dhcpc_sendmsg(FAR struct dhcpc_state_s *pdhcpc,
   memset(&pdhcpc->packet, 0, sizeof(struct dhcp_msg));
   pdhcpc->packet.op    = DHCP_REQUEST;
   pdhcpc->packet.htype = DHCP_HTYPE_ETHERNET;
-  pdhcpc->packet.hlen  = pdhcpc->ds_maclen;
+  pdhcpc->packet.hlen  = pdhcpc->maclen;
   memcpy(pdhcpc->packet.xid, xid, 4);
-  memcpy(pdhcpc->packet.chaddr, pdhcpc->ds_macaddr, pdhcpc->ds_maclen);
-  memset(&pdhcpc->packet.chaddr[pdhcpc->ds_maclen],
-         0, 16 - pdhcpc->ds_maclen);
+  memcpy(pdhcpc->packet.chaddr, pdhcpc->macaddr, pdhcpc->maclen);
+  memset(&pdhcpc->packet.chaddr[pdhcpc->maclen], 0, 16 - pdhcpc->maclen);
   memcpy(pdhcpc->packet.options, magic_cookie, sizeof(magic_cookie));
 
   /* Add the common header options */
@@ -434,7 +437,7 @@ static uint8_t dhcpc_parsemsg(FAR struct dhcpc_state_s *pdhcpc, int buflen,
   if (buflen >= 44 && pdhcpc->packet.op == DHCP_REPLY &&
       memcmp(pdhcpc->packet.xid, xid, sizeof(xid)) == 0 &&
       memcmp(pdhcpc->packet.chaddr,
-             pdhcpc->ds_macaddr, pdhcpc->ds_maclen) == 0)
+             pdhcpc->macaddr, pdhcpc->maclen) == 0)
     {
       memcpy(&presult->ipaddr.s_addr, pdhcpc->packet.yiaddr, 4);
       return dhcpc_parseoptions(presult, &pdhcpc->packet.options[4],
@@ -446,6 +449,47 @@ static uint8_t dhcpc_parsemsg(FAR struct dhcpc_state_s *pdhcpc, int buflen,
 }
 
 /****************************************************************************
+ * Name: dhcpc_run
+ ****************************************************************************/
+
+static void *dhcpc_run(void *args)
+{
+  FAR struct dhcpc_state_s *pdhcpc = (FAR struct dhcpc_state_s *)args;
+  struct dhcpc_state result;
+  int ret;
+
+  while (1)
+    {
+      ret = dhcpc_request(pdhcpc, &result);
+      if (ret == OK)
+        {
+          pdhcpc->callback(&result);
+        }
+      else
+        {
+          pdhcpc->callback(NULL);
+          nerr("dhcpc_request error\n");
+        }
+
+      if (pdhcpc->cancel)
+        {
+          return NULL;
+        }
+
+      while (result.lease_time)
+        {
+          result.lease_time = sleep(result.lease_time);
+          if (pdhcpc->cancel)
+            {
+              return NULL;
+            }
+        }
+    }
+
+  return NULL;
+}
+
+/****************************************************************************
  * Public Functions
  ****************************************************************************/
 
@@ -468,15 +512,15 @@ FAR void *dhcpc_open(FAR const char *interface, FAR const void *macaddr,
 
   /* Allocate an internal DHCP structure */
 
-  pdhcpc = (FAR struct dhcpc_state_s *)malloc(sizeof(struct dhcpc_state_s));
+  pdhcpc = malloc(sizeof(struct dhcpc_state_s) + maclen - 1);
   if (pdhcpc)
     {
       /* Initialize the allocated structure */
 
       memset(pdhcpc, 0, sizeof(struct dhcpc_state_s));
-      pdhcpc->interface  = interface;
-      pdhcpc->ds_macaddr = macaddr;
-      pdhcpc->ds_maclen  = maclen;
+      pdhcpc->interface = interface;
+      pdhcpc->maclen    = maclen;
+      memcpy(pdhcpc->macaddr, macaddr, pdhcpc->maclen);
 
       /* Create a UDP socket */
 
@@ -551,6 +595,11 @@ void dhcpc_close(FAR void *handle)
 
   if (pdhcpc)
     {
+      if (pdhcpc->thread)
+        {
+          dhcpc_cancel(pdhcpc);
+        }
+
       if (pdhcpc->sockfd)
         {
           close(pdhcpc->sockfd);
@@ -561,6 +610,46 @@ void dhcpc_close(FAR void *handle)
 }
 
 /****************************************************************************
+ * Name: dhcpc_cancel
+ ****************************************************************************/
+
+void dhcpc_cancel(FAR void *handle)
+{
+  struct dhcpc_state_s *pdhcpc = (struct dhcpc_state_s *)handle;
+  sighandler_t old;
+  int ret;
+
+  if (pdhcpc)
+    {
+      pdhcpc->cancel = true;
+
+      if (pdhcpc->thread)
+        {
+          old = signal(SIGQUIT, SIG_IGN);
+
+          /* Signal the dhcpc_run */
+
+          ret = pthread_kill(pdhcpc->thread, SIGQUIT);
+          if (ret != 0)
+            {
+              nerr("ERROR: pthread_kill DHCPC thread\n");
+            }
+
+          /* Wait for the end of dhcpc_run */
+
+          ret = pthread_join(pdhcpc->thread, NULL);
+          if (ret != 0)
+            {
+              nerr("ERROR: pthread_join DHCPC thread\n");
+            }
+
+          pdhcpc->thread = 0;
+          signal(SIGQUIT, old);
+        }
+    }
+}
+
+/****************************************************************************
  * Name: dhcpc_request
  ****************************************************************************/
 
@@ -599,6 +688,11 @@ int dhcpc_request(FAR void *handle, FAR struct dhcpc_state *presult)
   state = STATE_INITIAL;
   do
     {
+      if (pdhcpc->cancel)
+        {
+          return ERROR;
+        }
+
       /* Send the DISCOVER command */
 
       ninfo("Broadcast DISCOVER\n");
@@ -666,6 +760,11 @@ int dhcpc_request(FAR void *handle, FAR struct dhcpc_state *presult)
   retries = 0;
   do
     {
+      if (pdhcpc->cancel)
+        {
+          return ERROR;
+        }
+
       /* Send the REQUEST message to obtain the lease that was offered to
        * us.
        */
@@ -775,3 +874,34 @@ int dhcpc_request(FAR void *handle, FAR struct dhcpc_state *presult)
   ninfo("Lease expires in %" PRId32 " seconds\n", presult->lease_time);
   return OK;
 }
+
+/****************************************************************************
+ * Name: dhcpc_request_async
+ ****************************************************************************/
+
+int dhcpc_request_async(FAR void *handle, dhcpc_callback_t callback)
+{
+  FAR struct dhcpc_state_s *pdhcpc = (FAR struct dhcpc_state_s *)handle;
+  int ret;
+
+  if (!handle || !callback)
+    {
+      return ERROR;
+    }
+
+  if (pdhcpc->thread)
+    {
+      nerr("ERROR: DHCPC thread already running\n");
+      return ERROR;
+    }
+
+  pdhcpc->callback = callback;
+  ret = pthread_create(&pdhcpc->thread, NULL, dhcpc_run, pdhcpc);
+  if (ret != 0)
+    {
+      nerr("ERROR: Failed to start the DHCPC thread\n");
+      return ERROR;
+    }
+
+  return OK;
+}