netutils/dhcpc: add non-blocking interface
Signed-off-by: songlinzhang <songlinzhang@xiaomi.com>
This commit is contained in:
parent
c9f736005a
commit
e0fc53b23c
@ -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
|
||||
|
@ -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],
|
||||
@ -445,6 +448,47 @@ static uint8_t dhcpc_parsemsg(FAR struct dhcpc_state_s *pdhcpc, int buflen,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* 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->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);
|
||||
@ -560,6 +609,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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user