updated picoTCP to 1.4.0, lowered build optimization levels to -O2, improved selftest

This commit is contained in:
Joseph Henry
2017-06-05 14:26:06 -07:00
parent 47a80e8954
commit 19839eeac9
367 changed files with 107850 additions and 3813 deletions

View File

@@ -1,8 +1,8 @@
/*********************************************************************
PicoTCP. Copyright (c) 2012-2015 Altran Intelligent Systems. Some rights reserved.
See LICENSE and COPYING for usage.
PicoTCP. Copyright (c) 2012-2017 Altran Intelligent Systems. Some rights reserved.
See COPYING, LICENSE.GPLv2 and LICENSE.GPLv3 for usage.
Authors: Kristof Roelants, Frederik Van Slycken
Authors: Kristof Roelants, Frederik Van Slycken, Maxime Vincent
*********************************************************************/
@@ -15,8 +15,12 @@
#include "pico_eth.h"
#if (defined PICO_SUPPORT_DHCPC && defined PICO_SUPPORT_UDP)
#define dhcpc_dbg(...) do {} while(0)
/* #define dhcpc_dbg dbg */
#ifdef DEBUG_DHCP_CLIENT
#define dhcpc_dbg dbg
#else
#define dhcpc_dbg(...) do {} while(0)
#endif
/* timer values */
#define DHCP_CLIENT_REINIT 6000 /* msec */
@@ -30,6 +34,13 @@
#define DHCP_CLIENT_MAXMSGZISE (PICO_IP_MRU - PICO_SIZE_IP4HDR)
#define PICO_DHCP_HOSTNAME_MAXLEN 64U
/* Mockables */
#if defined UNIT_TEST
# define MOCKABLE __attribute__((weak))
#else
# define MOCKABLE
#endif
static char dhcpc_host_name[PICO_DHCP_HOSTNAME_MAXLEN] = "";
static char dhcpc_domain_name[PICO_DHCP_HOSTNAME_MAXLEN] = "";
@@ -60,6 +71,7 @@ struct dhcp_client_timer
uint8_t state;
unsigned int type;
uint32_t xid;
uint32_t timer_id;
};
struct pico_dhcp_client_cookie
@@ -91,6 +103,7 @@ static int reset(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf);
static int8_t pico_dhcp_client_msg(struct pico_dhcp_client_cookie *dhcpc, uint8_t msg_type);
static void pico_dhcp_client_wakeup(uint16_t ev, struct pico_socket *s);
static void pico_dhcp_state_machine(uint8_t event, struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf);
static void pico_dhcp_client_callback(struct pico_dhcp_client_cookie *dhcpc, int code);
static const struct pico_ip4 bcast_netmask = {
.addr = 0xFFFFFFFF
@@ -109,7 +122,7 @@ static int dhcp_cookies_cmp(void *ka, void *kb)
return (a->xid < b->xid) ? (-1) : (1);
}
PICO_TREE_DECLARE(DHCPCookies, dhcp_cookies_cmp);
static PICO_TREE_DECLARE(DHCPCookies, dhcp_cookies_cmp);
static struct pico_dhcp_client_cookie *pico_dhcp_client_add_cookie(uint32_t xid, struct pico_device *dev, void (*cb)(void *dhcpc, int code), uint32_t *uid)
{
@@ -137,7 +150,11 @@ static struct pico_dhcp_client_cookie *pico_dhcp_client_add_cookie(uint32_t xid,
dhcpc->cb = cb;
dhcpc->dev = dev;
pico_tree_insert(&DHCPCookies, dhcpc);
if (pico_tree_insert(&DHCPCookies, dhcpc)) {
PICO_FREE(dhcpc);
return NULL;
}
return dhcpc;
}
@@ -180,20 +197,30 @@ static void pico_dhcp_client_timer_handler(pico_time now, void *arg);
static void pico_dhcp_client_reinit(pico_time now, void *arg);
static struct dhcp_client_timer *pico_dhcp_timer_add(uint8_t type, uint32_t time, struct pico_dhcp_client_cookie *ck)
{
struct dhcp_client_timer *t;
struct dhcp_client_timer *t = ck->timer[type];
if (t) {
/* Stale timer, mark to be freed in the callback */
t->state = DHCP_CLIENT_TIMER_STOPPED;
}
/* allocate a new timer, the old one is still in the timer tree, and will be freed as soon as it expires */
t = PICO_ZALLOC(sizeof(struct dhcp_client_timer));
if (!t)
return NULL;
t->state = DHCP_CLIENT_TIMER_STARTED;
t->xid = ck->xid;
t->type = type;
pico_timer_add(time, pico_dhcp_client_timer_handler, t);
if (ck->timer[type]) {
ck->timer[type]->state = DHCP_CLIENT_TIMER_STOPPED;
t->timer_id = pico_timer_add(time, pico_dhcp_client_timer_handler, t);
if (!t->timer_id) {
dhcpc_dbg("DHCP: Failed to start timer\n");
PICO_FREE(t);
return NULL;
}
/* store timer struct reference in cookie */
ck->timer[type] = t;
return t;
}
@@ -234,28 +261,25 @@ static void pico_dhcp_client_timer_handler(pico_time now, void *arg)
(void) now;
if (t->state != DHCP_CLIENT_TIMER_STOPPED) {
dhcpc = pico_dhcp_client_find_cookie(t->xid);
if (dhcpc && dhcpc->timer) {
if (dhcpc) {
t->state = DHCP_CLIENT_TIMER_STOPPED;
if ((t->type == PICO_DHCPC_TIMER_INIT) && (dhcpc->state < DHCP_CLIENT_STATE_SELECTING)) {
/* this was an INIT timer */
pico_dhcp_client_reinit(now, dhcpc);
} else if (t->type != PICO_DHCPC_TIMER_INIT) {
/* this was NOT an INIT timer */
dhcpc->event = (uint8_t)dhcp_get_timer_event(dhcpc, t->type);
if (dhcpc->event != PICO_DHCP_EVENT_NONE)
pico_dhcp_state_machine(dhcpc->event, dhcpc, NULL);
}
}
}
/* stale timer, it's associated struct should be freed */
if (t->state == DHCP_CLIENT_TIMER_STOPPED)
PICO_FREE(t);
}
static void pico_dhcp_client_timer_stop(struct pico_dhcp_client_cookie *dhcpc, int type)
{
if (dhcpc->timer[type]) {
dhcpc->timer[type]->state = DHCP_CLIENT_TIMER_STOPPED;
}
}
static void pico_dhcp_client_reinit(pico_time now, void *arg)
{
struct pico_dhcp_client_cookie *dhcpc = (struct pico_dhcp_client_cookie *)arg;
@@ -268,8 +292,7 @@ static void pico_dhcp_client_reinit(pico_time now, void *arg)
if (++dhcpc->retry > DHCP_CLIENT_RETRIES) {
pico_err = PICO_ERR_EAGAIN;
if (dhcpc->cb)
dhcpc->cb(dhcpc, PICO_DHCP_ERROR);
pico_dhcp_client_callback(dhcpc, PICO_DHCP_ERROR);
pico_dhcp_client_del_cookie(dhcpc->xid);
return;
@@ -285,27 +308,39 @@ static void pico_dhcp_client_stop_timers(struct pico_dhcp_client_cookie *dhcpc)
int i;
dhcpc->retry = 0;
for (i = 0; i < PICO_DHCPC_TIMER_ARRAY_SIZE; i++)
pico_dhcp_client_timer_stop(dhcpc, i);
{
if (dhcpc->timer[i]) {
/* Do not cancel timer, but rather set it's state to be freed when it expires */
dhcpc->timer[i]->state = DHCP_CLIENT_TIMER_STOPPED;
dhcpc->timer[i] = NULL;
}
}
}
static void pico_dhcp_client_start_init_timer(struct pico_dhcp_client_cookie *dhcpc)
static int pico_dhcp_client_start_init_timer(struct pico_dhcp_client_cookie *dhcpc)
{
uint32_t time = 0;
/* timer value is doubled with every retry (exponential backoff) */
time = (uint32_t) (DHCP_CLIENT_RETRANS << dhcpc->retry);
pico_dhcp_timer_add(PICO_DHCPC_TIMER_INIT, time * 1000, dhcpc);
if (!pico_dhcp_timer_add(PICO_DHCPC_TIMER_INIT, time * 1000, dhcpc))
return -1;
return 0;
}
static void pico_dhcp_client_start_requesting_timer(struct pico_dhcp_client_cookie *dhcpc)
static int pico_dhcp_client_start_requesting_timer(struct pico_dhcp_client_cookie *dhcpc)
{
uint32_t time = 0;
/* timer value is doubled with every retry (exponential backoff) */
time = (uint32_t)(DHCP_CLIENT_RETRANS << dhcpc->retry);
pico_dhcp_timer_add(PICO_DHCPC_TIMER_REQUEST, time * 1000, dhcpc);
if (!pico_dhcp_timer_add(PICO_DHCPC_TIMER_REQUEST, time * 1000, dhcpc))
return -1;
return 0;
}
static void pico_dhcp_client_start_renewing_timer(struct pico_dhcp_client_cookie *dhcpc)
static int pico_dhcp_client_start_renewing_timer(struct pico_dhcp_client_cookie *dhcpc)
{
uint32_t halftime = 0;
@@ -316,12 +351,13 @@ static void pico_dhcp_client_start_renewing_timer(struct pico_dhcp_client_cookie
if (halftime < 60)
halftime = 60;
pico_dhcp_timer_add(PICO_DHCPC_TIMER_RENEW, halftime * 1000, dhcpc);
if (!pico_dhcp_timer_add(PICO_DHCPC_TIMER_RENEW, halftime * 1000, dhcpc))
return -1;
return;
return 0;
}
static void pico_dhcp_client_start_rebinding_timer(struct pico_dhcp_client_cookie *dhcpc)
static int pico_dhcp_client_start_rebinding_timer(struct pico_dhcp_client_cookie *dhcpc)
{
uint32_t halftime = 0;
@@ -330,18 +366,30 @@ static void pico_dhcp_client_start_rebinding_timer(struct pico_dhcp_client_cooki
if (halftime < 60)
halftime = 60;
pico_dhcp_timer_add(PICO_DHCPC_TIMER_REBIND, halftime * 1000, dhcpc);
if (!pico_dhcp_timer_add(PICO_DHCPC_TIMER_REBIND, halftime * 1000, dhcpc))
return -1;
return;
return 0;
}
static void pico_dhcp_client_start_reacquisition_timers(struct pico_dhcp_client_cookie *dhcpc)
static int pico_dhcp_client_start_reacquisition_timers(struct pico_dhcp_client_cookie *dhcpc)
{
pico_dhcp_client_stop_timers(dhcpc);
pico_dhcp_timer_add(PICO_DHCPC_TIMER_T1, dhcpc->t1_time * 1000, dhcpc);
pico_dhcp_timer_add(PICO_DHCPC_TIMER_T2, dhcpc->t2_time * 1000, dhcpc);
pico_dhcp_timer_add(PICO_DHCPC_TIMER_LEASE, dhcpc->lease_time * 1000, dhcpc);
if (!pico_dhcp_timer_add(PICO_DHCPC_TIMER_T1, dhcpc->t1_time * 1000, dhcpc))
goto fail;
if (!pico_dhcp_timer_add(PICO_DHCPC_TIMER_T2, dhcpc->t2_time * 1000, dhcpc))
goto fail;
if (!pico_dhcp_timer_add(PICO_DHCPC_TIMER_LEASE, dhcpc->lease_time * 1000, dhcpc))
goto fail;
return 0;
fail:
pico_dhcp_client_stop_timers(dhcpc);
return -1;
}
static int pico_dhcp_client_init(struct pico_dhcp_client_cookie *dhcpc)
@@ -357,7 +405,9 @@ static int pico_dhcp_client_init(struct pico_dhcp_client_cookie *dhcpc)
dhcpc->s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &pico_dhcp_client_wakeup);
if (!dhcpc->s) {
pico_dhcp_timer_add(PICO_DHCPC_TIMER_INIT, DHCP_CLIENT_REINIT, dhcpc);
if (!pico_dhcp_timer_add(PICO_DHCPC_TIMER_INIT, DHCP_CLIENT_REINIT, dhcpc))
return -1;
return 0;
}
@@ -365,24 +415,33 @@ static int pico_dhcp_client_init(struct pico_dhcp_client_cookie *dhcpc)
if (pico_socket_bind(dhcpc->s, &inaddr_any, &port) < 0) {
pico_socket_close(dhcpc->s);
dhcpc->s = NULL;
pico_dhcp_timer_add(PICO_DHCPC_TIMER_INIT, DHCP_CLIENT_REINIT, dhcpc);
if (!pico_dhcp_timer_add(PICO_DHCPC_TIMER_INIT, DHCP_CLIENT_REINIT, dhcpc))
return -1;
return 0;
}
if (pico_dhcp_client_msg(dhcpc, PICO_DHCP_MSG_DISCOVER) < 0) {
pico_socket_close(dhcpc->s);
dhcpc->s = NULL;
pico_dhcp_timer_add(PICO_DHCPC_TIMER_INIT, DHCP_CLIENT_REINIT, dhcpc);
if (!pico_dhcp_timer_add(PICO_DHCPC_TIMER_INIT, DHCP_CLIENT_REINIT, dhcpc))
return -1;
return 0;
}
dhcpc->retry = 0;
dhcpc->init_timestamp = PICO_TIME_MS();
pico_dhcp_client_start_init_timer(dhcpc);
if (pico_dhcp_client_start_init_timer(dhcpc) < 0) {
pico_socket_close(dhcpc->s);
dhcpc->s = NULL;
return -1;
}
return 0;
}
int pico_dhcp_initiate_negotiation(struct pico_device *dev, void (*cb)(void *dhcpc, int code), uint32_t *uid)
int MOCKABLE pico_dhcp_initiate_negotiation(struct pico_device *dev, void (*cb)(void *dhcpc, int code), uint32_t *uid)
{
uint8_t retry = 32;
uint32_t xid = 0;
@@ -478,22 +537,24 @@ static void pico_dhcp_client_recv_params(struct pico_dhcp_client_cookie *dhcpc,
break;
case PICO_DHCP_OPT_HOSTNAME:
{
{
uint32_t maxlen = PICO_DHCP_HOSTNAME_MAXLEN;
if (opt->len < maxlen)
maxlen = opt->len;
strncpy(dhcpc_host_name, opt->ext.string.txt, maxlen);
}
break;
}
break;
case PICO_DHCP_OPT_DOMAINNAME:
{
{
uint32_t maxlen = PICO_DHCP_HOSTNAME_MAXLEN;
if (opt->len < maxlen)
maxlen = opt->len;
strncpy(dhcpc_domain_name, opt->ext.string.txt, maxlen);
}
break;
}
break;
default:
dhcpc_dbg("DHCP client: WARNING unsupported option %u\n", opt->code);
@@ -514,7 +575,7 @@ static void pico_dhcp_client_recv_params(struct pico_dhcp_client_cookie *dhcpc,
static int recv_offer(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf)
{
struct pico_dhcp_hdr *hdr = (struct pico_dhcp_hdr *)buf;
struct pico_dhcp_opt *opt = DHCP_OPT(hdr,0);
struct pico_dhcp_opt *opt = DHCP_OPT(hdr, 0);
pico_dhcp_client_recv_params(dhcpc, opt);
if ((dhcpc->event != PICO_DHCP_MSG_OFFER) || !dhcpc->server_id.addr || !dhcpc->netmask.addr || !dhcpc->lease_time)
@@ -526,21 +587,42 @@ static int recv_offer(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf)
dhcpc->state = DHCP_CLIENT_STATE_REQUESTING;
dhcpc->retry = 0;
pico_dhcp_client_msg(dhcpc, PICO_DHCP_MSG_REQUEST);
pico_dhcp_client_start_requesting_timer(dhcpc);
if (pico_dhcp_client_start_requesting_timer(dhcpc) < 0)
return -1;
return 0;
}
static void pico_dhcp_client_update_link(struct pico_dhcp_client_cookie *dhcpc)
{
struct pico_ip4 any_address = {
0
};
struct pico_ip4 address = {
0
};
struct pico_ipv4_link *l;
dbg("DHCP client: update link\n");
pico_ipv4_link_del(dhcpc->dev, address);
l = pico_ipv4_link_by_dev(dhcpc->dev);
while(l) {
pico_ipv4_link_del(dhcpc->dev, l->address);
l = pico_ipv4_link_by_dev_next(dhcpc->dev, l);
}
pico_ipv4_link_add(dhcpc->dev, dhcpc->address, dhcpc->netmask);
/* If router option is received, use it as default gateway */
if (dhcpc->gateway.addr != 0U) {
pico_ipv4_route_add(any_address, any_address, dhcpc->gateway, 1, NULL);
}
}
static int recv_ack(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf)
{
struct pico_dhcp_hdr *hdr = (struct pico_dhcp_hdr *)buf;
struct pico_dhcp_opt *opt = DHCP_OPT(hdr,0);
struct pico_ip4 address = {
0
};
struct pico_ip4 any_address = {
0
};
struct pico_dhcp_opt *opt = DHCP_OPT(hdr, 0);
struct pico_ipv4_link *l;
pico_dhcp_client_recv_params(dhcpc, opt);
@@ -557,32 +639,28 @@ static int recv_ack(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf)
pico_socket_close(dhcpc->s);
dhcpc->s = NULL;
/* Delete all the links before adding the address */
pico_ipv4_link_del(dhcpc->dev, address);
/* Delete all the links before adding the new ip address
* in case the new address doesn't match the old one */
l = pico_ipv4_link_by_dev(dhcpc->dev);
while(l) {
pico_ipv4_link_del(dhcpc->dev, l->address);
l = pico_ipv4_link_by_dev_next(dhcpc->dev, l);
if (dhcpc->address.addr != (l->address).addr) {
pico_dhcp_client_update_link(dhcpc);
}
pico_ipv4_link_add(dhcpc->dev, dhcpc->address, dhcpc->netmask);
dbg("DHCP client: renewal time (T1) %u\n", (unsigned int)dhcpc->t1_time);
dbg("DHCP client: rebinding time (T2) %u\n", (unsigned int)dhcpc->t2_time);
dbg("DHCP client: lease time %u\n", (unsigned int)dhcpc->lease_time);
/* If router option is received, use it as default gateway */
if (dhcpc->gateway.addr != 0U) {
pico_ipv4_route_add(any_address, any_address, dhcpc->gateway, 1, NULL);
}
dhcpc->retry = 0;
dhcpc->renew_time = dhcpc->t2_time - dhcpc->t1_time;
dhcpc->rebind_time = dhcpc->lease_time - dhcpc->t2_time;
pico_dhcp_client_start_reacquisition_timers(dhcpc);
if (pico_dhcp_client_start_reacquisition_timers(dhcpc) < 0) {
pico_dhcp_client_callback(dhcpc, PICO_DHCP_ERROR);
return -1;
}
*(dhcpc->uid) = dhcpc->xid;
if (dhcpc->cb)
dhcpc->cb(dhcpc, PICO_DHCP_SUCCESS);
pico_dhcp_client_callback(dhcpc, PICO_DHCP_SUCCESS);
dhcpc->state = DHCP_CLIENT_STATE_BOUND;
return 0;
@@ -596,8 +674,7 @@ static int renew(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf)
dhcpc->s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &pico_dhcp_client_wakeup);
if (!dhcpc->s) {
dhcpc_dbg("DHCP client ERROR: failure opening socket on renew, aborting DHCP! (%s)\n", strerror(pico_err));
if (dhcpc->cb)
dhcpc->cb(dhcpc, PICO_DHCP_ERROR);
pico_dhcp_client_callback(dhcpc, PICO_DHCP_ERROR);
return -1;
}
@@ -606,15 +683,20 @@ static int renew(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf)
dhcpc_dbg("DHCP client ERROR: failure binding socket on renew, aborting DHCP! (%s)\n", strerror(pico_err));
pico_socket_close(dhcpc->s);
dhcpc->s = NULL;
if (dhcpc->cb)
dhcpc->cb(dhcpc, PICO_DHCP_ERROR);
pico_dhcp_client_callback(dhcpc, PICO_DHCP_ERROR);
return -1;
}
dhcpc->retry = 0;
pico_dhcp_client_msg(dhcpc, PICO_DHCP_MSG_REQUEST);
pico_dhcp_client_start_renewing_timer(dhcpc);
if (pico_dhcp_client_start_renewing_timer(dhcpc) < 0) {
pico_socket_close(dhcpc->s);
dhcpc->s = NULL;
pico_dhcp_client_callback(dhcpc, PICO_DHCP_ERROR);
return -1;
}
return 0;
}
@@ -626,7 +708,8 @@ static int rebind(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf)
dhcpc->state = DHCP_CLIENT_STATE_REBINDING;
dhcpc->retry = 0;
pico_dhcp_client_msg(dhcpc, PICO_DHCP_MSG_REQUEST);
pico_dhcp_client_start_rebinding_timer(dhcpc);
if (pico_dhcp_client_start_rebinding_timer(dhcpc) < 0)
return -1;
return 0;
}
@@ -649,8 +732,7 @@ static int reset(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf)
/* delete the link with the currently in use address */
pico_ipv4_link_del(dhcpc->dev, address);
if (dhcpc->cb)
dhcpc->cb(dhcpc, PICO_DHCP_RESET);
pico_dhcp_client_callback(dhcpc, PICO_DHCP_RESET);
if (dhcpc->state < DHCP_CLIENT_STATE_BOUND)
{
@@ -671,28 +753,33 @@ static int retransmit(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf)
{
case DHCP_CLIENT_STATE_INIT:
pico_dhcp_client_msg(dhcpc, PICO_DHCP_MSG_DISCOVER);
pico_dhcp_client_start_init_timer(dhcpc);
if (pico_dhcp_client_start_init_timer(dhcpc) < 0)
return -1;
break;
case DHCP_CLIENT_STATE_REQUESTING:
pico_dhcp_client_msg(dhcpc, PICO_DHCP_MSG_REQUEST);
pico_dhcp_client_start_requesting_timer(dhcpc);
if (pico_dhcp_client_start_requesting_timer(dhcpc) < 0)
return -1;
break;
case DHCP_CLIENT_STATE_RENEWING:
pico_dhcp_client_msg(dhcpc, PICO_DHCP_MSG_REQUEST);
pico_dhcp_client_start_renewing_timer(dhcpc);
if (pico_dhcp_client_start_renewing_timer(dhcpc) < 0)
return -1;
break;
case DHCP_CLIENT_STATE_REBINDING:
pico_dhcp_client_msg(dhcpc, PICO_DHCP_MSG_DISCOVER);
pico_dhcp_client_start_rebinding_timer(dhcpc);
if (pico_dhcp_client_start_rebinding_timer(dhcpc) < 0)
return -1;
break;
default:
dhcpc_dbg("DHCP client WARNING: retransmit in incorrect state (%u)!\n", dhcpc->state);
return -1;
}
return 0;
}
@@ -708,8 +795,7 @@ struct dhcp_action_entry {
static struct dhcp_action_entry dhcp_fsm[] =
{ /* event |offer |ack |nak |T1 |T2 |lease |retransmit */
/* state init-reboot */
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL },
/* state init-reboot */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL },
/* state rebooting */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL },
/* state init */ { recv_offer, NULL, NULL, NULL, NULL, NULL, retransmit },
/* state selecting */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL },
@@ -719,6 +805,12 @@ static struct dhcp_action_entry dhcp_fsm[] =
/* state rebinding */ { NULL, recv_ack, reset, NULL, NULL, reset, retransmit },
};
static void dhcp_action_call( int (*call)(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf), struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf)
{
if (call)
call(dhcpc, buf);
}
/* TIMERS REMARK:
* In state bound we have T1, T2 and the lease timer running. If T1 goes off, we attempt to renew.
* If the renew succeeds a new T1, T2 and lease timer is started. The former T2 and lease timer is
@@ -732,51 +824,37 @@ static void pico_dhcp_state_machine(uint8_t event, struct pico_dhcp_client_cooki
{
case PICO_DHCP_MSG_OFFER:
dhcpc_dbg("DHCP client: received OFFER\n");
if (dhcp_fsm[dhcpc->state].offer)
dhcp_fsm[dhcpc->state].offer(dhcpc, buf);
dhcp_action_call(dhcp_fsm[dhcpc->state].offer, dhcpc, buf);
break;
case PICO_DHCP_MSG_ACK:
dhcpc_dbg("DHCP client: received ACK\n");
if (dhcp_fsm[dhcpc->state].ack)
dhcp_fsm[dhcpc->state].ack(dhcpc, buf);
dhcp_action_call(dhcp_fsm[dhcpc->state].ack, dhcpc, buf);
break;
case PICO_DHCP_MSG_NAK:
dhcpc_dbg("DHCP client: received NAK\n");
if (dhcp_fsm[dhcpc->state].nak)
dhcp_fsm[dhcpc->state].nak(dhcpc, buf);
dhcp_action_call(dhcp_fsm[dhcpc->state].nak, dhcpc, buf);
break;
case PICO_DHCP_EVENT_T1:
dhcpc_dbg("DHCP client: received T1 timeout\n");
if (dhcp_fsm[dhcpc->state].timer1)
dhcp_fsm[dhcpc->state].timer1(dhcpc, NULL);
dhcp_action_call(dhcp_fsm[dhcpc->state].timer1, dhcpc, buf);
break;
case PICO_DHCP_EVENT_T2:
dhcpc_dbg("DHCP client: received T2 timeout\n");
if (dhcp_fsm[dhcpc->state].timer2)
dhcp_fsm[dhcpc->state].timer2(dhcpc, NULL);
dhcp_action_call(dhcp_fsm[dhcpc->state].timer2, dhcpc, buf);
break;
case PICO_DHCP_EVENT_LEASE:
dhcpc_dbg("DHCP client: received LEASE timeout\n");
if (dhcp_fsm[dhcpc->state].timer_lease)
dhcp_fsm[dhcpc->state].timer_lease(dhcpc, NULL);
dhcp_action_call(dhcp_fsm[dhcpc->state].timer_lease, dhcpc, buf);
break;
case PICO_DHCP_EVENT_RETRANSMIT:
dhcpc_dbg("DHCP client: received RETRANSMIT timeout\n");
if (dhcp_fsm[dhcpc->state].timer_retransmit)
dhcp_fsm[dhcpc->state].timer_retransmit(dhcpc, NULL);
dhcp_action_call(dhcp_fsm[dhcpc->state].timer_retransmit, dhcpc, buf);
break;
default:
@@ -790,7 +868,7 @@ static int16_t pico_dhcp_client_opt_parse(void *ptr, uint16_t len)
{
uint32_t optlen = len - (uint32_t)sizeof(struct pico_dhcp_hdr);
struct pico_dhcp_hdr *hdr = (struct pico_dhcp_hdr *)ptr;
struct pico_dhcp_opt *opt = DHCP_OPT(hdr,0);
struct pico_dhcp_opt *opt = DHCP_OPT(hdr, 0);
if (hdr->dhcp_magic != PICO_DHCPD_MAGIC_COOKIE)
return -1;
@@ -833,7 +911,7 @@ static int8_t pico_dhcp_client_msg(struct pico_dhcp_client_cookie *dhcpc, uint8_
}
/* specific options */
offset = (uint16_t)(offset + pico_dhcp_opt_maxmsgsize(DHCP_OPT(hdr,offset), DHCP_CLIENT_MAXMSGZISE));
offset = (uint16_t)(offset + pico_dhcp_opt_maxmsgsize(DHCP_OPT(hdr, offset), DHCP_CLIENT_MAXMSGZISE));
break;
case PICO_DHCP_MSG_REQUEST:
@@ -846,10 +924,10 @@ static int8_t pico_dhcp_client_msg(struct pico_dhcp_client_cookie *dhcpc, uint8_
}
/* specific options */
offset = (uint16_t)(offset + pico_dhcp_opt_maxmsgsize(DHCP_OPT(hdr,offset), DHCP_CLIENT_MAXMSGZISE));
offset = (uint16_t)(offset + pico_dhcp_opt_maxmsgsize(DHCP_OPT(hdr, offset), DHCP_CLIENT_MAXMSGZISE));
if (dhcpc->state == DHCP_CLIENT_STATE_REQUESTING) {
offset = (uint16_t)(offset + pico_dhcp_opt_reqip(DHCP_OPT(hdr,offset), &dhcpc->address));
offset = (uint16_t)(offset + pico_dhcp_opt_serverid(DHCP_OPT(hdr,offset), &dhcpc->server_id));
offset = (uint16_t)(offset + pico_dhcp_opt_reqip(DHCP_OPT(hdr, offset), &dhcpc->address));
offset = (uint16_t)(offset + pico_dhcp_opt_serverid(DHCP_OPT(hdr, offset), &dhcpc->server_id));
}
break;
@@ -859,9 +937,9 @@ static int8_t pico_dhcp_client_msg(struct pico_dhcp_client_cookie *dhcpc, uint8_
}
/* common options */
offset = (uint16_t)(offset + pico_dhcp_opt_msgtype(DHCP_OPT(hdr,offset), msg_type));
offset = (uint16_t)(offset + pico_dhcp_opt_paramlist(DHCP_OPT(hdr,offset)));
offset = (uint16_t)(offset + pico_dhcp_opt_end(DHCP_OPT(hdr,offset)));
offset = (uint16_t)(offset + pico_dhcp_opt_msgtype(DHCP_OPT(hdr, offset), msg_type));
offset = (uint16_t)(offset + pico_dhcp_opt_paramlist(DHCP_OPT(hdr, offset)));
offset = (uint16_t)(offset + pico_dhcp_opt_end(DHCP_OPT(hdr, offset)));
switch (dhcpc->state)
{
@@ -940,17 +1018,23 @@ out_discard_buf:
PICO_FREE(buf);
}
void *pico_dhcp_get_identifier(uint32_t xid)
static void pico_dhcp_client_callback(struct pico_dhcp_client_cookie *dhcpc, int code)
{
if(dhcpc->cb)
dhcpc->cb(dhcpc, code);
}
void *MOCKABLE pico_dhcp_get_identifier(uint32_t xid)
{
return (void *)pico_dhcp_client_find_cookie(xid);
}
struct pico_ip4 pico_dhcp_get_address(void*dhcpc)
struct pico_ip4 MOCKABLE pico_dhcp_get_address(void*dhcpc)
{
return ((struct pico_dhcp_client_cookie*)dhcpc)->address;
}
struct pico_ip4 pico_dhcp_get_gateway(void*dhcpc)
struct pico_ip4 MOCKABLE pico_dhcp_get_gateway(void*dhcpc)
{
return ((struct pico_dhcp_client_cookie*)dhcpc)->gateway;
}