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