mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-08-23 06:35:57 +00:00
mDNS: cleanup probing and announcing sequence
The implementation was not fully to the standard. This commit adds a nicer state machine implementation and multiple announce messages with a minimum of 2.
This commit is contained in:
parent
65eb36b10d
commit
ee7ed8c87d
|
@ -115,7 +115,7 @@ static mdns_name_result_cb_t mdns_name_result_cb;
|
||||||
#define MDNS_RESPONSE_DELAY (LWIP_RAND() %(MDNS_RESPONSE_DELAY_MAX - \
|
#define MDNS_RESPONSE_DELAY (LWIP_RAND() %(MDNS_RESPONSE_DELAY_MAX - \
|
||||||
MDNS_RESPONSE_DELAY_MIN) + MDNS_RESPONSE_DELAY_MIN)
|
MDNS_RESPONSE_DELAY_MIN) + MDNS_RESPONSE_DELAY_MIN)
|
||||||
|
|
||||||
/** Probing defines */
|
/** Probing & announcing defines */
|
||||||
#define MDNS_PROBE_DELAY_MS 250
|
#define MDNS_PROBE_DELAY_MS 250
|
||||||
#define MDNS_PROBE_COUNT 3
|
#define MDNS_PROBE_COUNT 3
|
||||||
#ifdef LWIP_RAND
|
#ifdef LWIP_RAND
|
||||||
|
@ -125,9 +125,12 @@ static mdns_name_result_cb_t mdns_name_result_cb;
|
||||||
#define MDNS_INITIAL_PROBE_DELAY_MS MDNS_PROBE_DELAY_MS
|
#define MDNS_INITIAL_PROBE_DELAY_MS MDNS_PROBE_DELAY_MS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MDNS_PROBING_NOT_STARTED 0
|
/* Delay between successive announcements (RFC6762 section 8.3)
|
||||||
#define MDNS_PROBING_ONGOING 1
|
* -> increase by a factor 2 with every response sent.
|
||||||
#define MDNS_PROBING_COMPLETE 2
|
*/
|
||||||
|
#define MDNS_ANNOUNCE_DELAY_MS 1000
|
||||||
|
/* Minimum 2 announces, may send up to 8 (RFC6762 section 8.3) */
|
||||||
|
#define MDNS_ANNOUNCE_COUNT 2
|
||||||
|
|
||||||
/** Information about received packet */
|
/** Information about received packet */
|
||||||
struct mdns_packet {
|
struct mdns_packet {
|
||||||
|
@ -187,7 +190,7 @@ struct mdns_answer {
|
||||||
u16_t rd_offset;
|
u16_t rd_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void mdns_probe(void* arg);
|
static void mdns_probe_and_announce(void* arg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construction to make mdns struct accessible from mdns_out.c
|
* Construction to make mdns struct accessible from mdns_out.c
|
||||||
|
@ -830,7 +833,8 @@ mdns_handle_question(struct mdns_packet *pkt, struct netif *netif)
|
||||||
int i;
|
int i;
|
||||||
err_t res;
|
err_t res;
|
||||||
|
|
||||||
if (mdns->probing_state != MDNS_PROBING_COMPLETE) {
|
if ((mdns->state != MDNS_STATE_COMPLETE) &&
|
||||||
|
(mdns->state != MDNS_STATE_ANNOUNCING)) {
|
||||||
/* Don't answer questions until we've verified our domains via probing */
|
/* Don't answer questions until we've verified our domains via probing */
|
||||||
/* @todo we should check incoming questions during probing for tiebreaking */
|
/* @todo we should check incoming questions during probing for tiebreaking */
|
||||||
return;
|
return;
|
||||||
|
@ -1115,9 +1119,11 @@ mdns_handle_response(struct mdns_packet *pkt, struct netif *netif)
|
||||||
mdns_domain_debug_print(&ans.info.domain);
|
mdns_domain_debug_print(&ans.info.domain);
|
||||||
LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", ans.info.type, ans.info.klass));
|
LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", ans.info.type, ans.info.klass));
|
||||||
|
|
||||||
/*"Apparently conflicting Multicast DNS responses received *before* the first probe packet is sent MUST
|
/* "Conflicting Multicast DNS responses received *before* the first probe
|
||||||
be silently ignored" so drop answer if we haven't started probing yet*/
|
* packet is sent MUST be silently ignored" so drop answer if we haven't
|
||||||
if ((mdns->probing_state == MDNS_PROBING_ONGOING) && (mdns->probes_sent > 0)) {
|
* started probing yet. */
|
||||||
|
if ((mdns->state == MDNS_STATE_PROBING) ||
|
||||||
|
(mdns->state == MDNS_STATE_ANNOUNCE_WAIT)) {
|
||||||
struct mdns_domain domain;
|
struct mdns_domain domain;
|
||||||
u8_t i;
|
u8_t i;
|
||||||
u8_t conflict = 0;
|
u8_t conflict = 0;
|
||||||
|
@ -1141,7 +1147,7 @@ mdns_handle_response(struct mdns_packet *pkt, struct netif *netif)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conflict != 0) {
|
if (conflict != 0) {
|
||||||
sys_untimeout(mdns_probe, netif);
|
sys_untimeout(mdns_probe_and_announce, netif);
|
||||||
if (mdns_name_result_cb != NULL) {
|
if (mdns_name_result_cb != NULL) {
|
||||||
mdns_name_result_cb(netif, MDNS_PROBING_CONFLICT);
|
mdns_name_result_cb(netif, MDNS_PROBING_CONFLICT);
|
||||||
}
|
}
|
||||||
|
@ -1322,22 +1328,20 @@ mdns_send_probe(struct netif* netif, const ip_addr_t *destination)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timer callback for probing network.
|
* Timer callback for probing and announcing on the network.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
mdns_probe(void* arg)
|
mdns_probe_and_announce(void* arg)
|
||||||
{
|
{
|
||||||
struct netif *netif = (struct netif *)arg;
|
struct netif *netif = (struct netif *)arg;
|
||||||
struct mdns_host* mdns = NETIF_TO_HOST(netif);
|
struct mdns_host* mdns = NETIF_TO_HOST(netif);
|
||||||
|
u32_t announce_delay;
|
||||||
|
|
||||||
if(mdns->probes_sent >= MDNS_PROBE_COUNT) {
|
|
||||||
/* probing successful, announce the new name */
|
switch (mdns->state) {
|
||||||
mdns->probing_state = MDNS_PROBING_COMPLETE;
|
case MDNS_STATE_OFF:
|
||||||
mdns_resp_announce(netif);
|
case MDNS_STATE_PROBE_WAIT:
|
||||||
if (mdns_name_result_cb != NULL) {
|
case MDNS_STATE_PROBING:
|
||||||
mdns_name_result_cb(netif, MDNS_PROBING_SUCCESSFUL);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
#if LWIP_IPV4
|
#if LWIP_IPV4
|
||||||
/*if ipv4 wait with probing until address is set*/
|
/*if ipv4 wait with probing until address is set*/
|
||||||
if (!ip4_addr_isany_val(*netif_ip4_addr(netif)) &&
|
if (!ip4_addr_isany_val(*netif_ip4_addr(netif)) &&
|
||||||
|
@ -1348,10 +1352,47 @@ mdns_probe(void* arg)
|
||||||
if (mdns_send_probe(netif, &v6group) == ERR_OK)
|
if (mdns_send_probe(netif, &v6group) == ERR_OK)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
mdns->probes_sent++;
|
mdns->state = MDNS_STATE_PROBING;
|
||||||
|
mdns->sent_num++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sys_timeout(MDNS_PROBE_DELAY_MS, mdns_probe, netif);
|
|
||||||
|
if (mdns->sent_num >= MDNS_PROBE_COUNT) {
|
||||||
|
mdns->state = MDNS_STATE_ANNOUNCE_WAIT;
|
||||||
|
mdns->sent_num = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sys_timeout(MDNS_PROBE_DELAY_MS, mdns_probe_and_announce, netif);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case MDNS_STATE_ANNOUNCE_WAIT:
|
||||||
|
case MDNS_STATE_ANNOUNCING:
|
||||||
|
if (mdns->sent_num == 0) {
|
||||||
|
/* probing was succesful, announce all records */
|
||||||
|
mdns->state = MDNS_STATE_ANNOUNCING;
|
||||||
|
/* Let the client know probing was successful */
|
||||||
|
if (mdns_name_result_cb != NULL) {
|
||||||
|
mdns_name_result_cb(netif, MDNS_PROBING_SUCCESSFUL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mdns_resp_announce(netif);
|
||||||
|
mdns->sent_num++;
|
||||||
|
|
||||||
|
if (mdns->sent_num >= MDNS_ANNOUNCE_COUNT) {
|
||||||
|
/* Announcing and probing complete */
|
||||||
|
mdns->state = MDNS_STATE_COMPLETE;
|
||||||
|
mdns->sent_num = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
announce_delay = MDNS_ANNOUNCE_DELAY_MS * (1 << (mdns->sent_num - 1));
|
||||||
|
sys_timeout(announce_delay, mdns_probe_and_announce, netif);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MDNS_STATE_COMPLETE:
|
||||||
|
default:
|
||||||
|
/* Do nothing */
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1381,8 +1422,6 @@ mdns_resp_add_netif(struct netif *netif, const char *hostname)
|
||||||
netif_set_client_data(netif, mdns_netif_client_id, mdns);
|
netif_set_client_data(netif, mdns_netif_client_id, mdns);
|
||||||
|
|
||||||
MEMCPY(&mdns->name, hostname, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(hostname)));
|
MEMCPY(&mdns->name, hostname, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(hostname)));
|
||||||
mdns->probes_sent = 0;
|
|
||||||
mdns->probing_state = MDNS_PROBING_NOT_STARTED;
|
|
||||||
|
|
||||||
/* Init delayed message structs with address and port */
|
/* Init delayed message structs with address and port */
|
||||||
#if LWIP_IPV4
|
#if LWIP_IPV4
|
||||||
|
@ -1439,9 +1478,7 @@ mdns_resp_remove_netif(struct netif *netif)
|
||||||
mdns = NETIF_TO_HOST(netif);
|
mdns = NETIF_TO_HOST(netif);
|
||||||
LWIP_ERROR("mdns_resp_remove_netif: Not an active netif", (mdns != NULL), return ERR_VAL);
|
LWIP_ERROR("mdns_resp_remove_netif: Not an active netif", (mdns != NULL), return ERR_VAL);
|
||||||
|
|
||||||
if (mdns->probing_state == MDNS_PROBING_ONGOING) {
|
sys_untimeout(mdns_probe_and_announce, netif);
|
||||||
sys_untimeout(mdns_probe, netif);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < MDNS_MAX_SERVICES; i++) {
|
for (i = 0; i < MDNS_MAX_SERVICES; i++) {
|
||||||
struct mdns_service *service = mdns->services[i];
|
struct mdns_service *service = mdns->services[i];
|
||||||
|
@ -1643,7 +1680,12 @@ mdns_resp_announce(struct netif *netif)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mdns->probing_state == MDNS_PROBING_COMPLETE) {
|
/* Do not announce if the mdns responder is off, waiting to probe, probing or
|
||||||
|
* waiting to announce. */
|
||||||
|
if (!( (mdns->state == MDNS_STATE_OFF)
|
||||||
|
|| (mdns->state == MDNS_STATE_PROBE_WAIT)
|
||||||
|
|| (mdns->state == MDNS_STATE_PROBING)
|
||||||
|
|| (mdns->state == MDNS_STATE_ANNOUNCE_WAIT))) {
|
||||||
/* Announce on IPv6 and IPv4 */
|
/* Announce on IPv6 and IPv4 */
|
||||||
#if LWIP_IPV6
|
#if LWIP_IPV6
|
||||||
mdns_announce(netif, &v6group);
|
mdns_announce(netif, &v6group);
|
||||||
|
@ -1693,14 +1735,13 @@ mdns_resp_restart(struct netif *netif)
|
||||||
if (mdns == NULL) {
|
if (mdns == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
/* Make sure timer is not running */
|
||||||
|
sys_untimeout(mdns_probe_and_announce, netif);
|
||||||
|
|
||||||
if (mdns->probing_state == MDNS_PROBING_ONGOING) {
|
|
||||||
sys_untimeout(mdns_probe, netif);
|
|
||||||
}
|
|
||||||
/* @todo if we've failed 15 times within a 10 second period we MUST wait 5 seconds (or wait 5 seconds every time except first)*/
|
/* @todo if we've failed 15 times within a 10 second period we MUST wait 5 seconds (or wait 5 seconds every time except first)*/
|
||||||
mdns->probes_sent = 0;
|
mdns->sent_num = 0;
|
||||||
mdns->probing_state = MDNS_PROBING_ONGOING;
|
mdns->state = MDNS_STATE_PROBE_WAIT;
|
||||||
sys_timeout(MDNS_INITIAL_PROBE_DELAY_MS, mdns_probe, netif);
|
sys_timeout(MDNS_INITIAL_PROBE_DELAY_MS, mdns_probe_and_announce, netif);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -160,16 +160,32 @@ struct mdns_delayed_msg {
|
||||||
struct mdns_outmsg delayed_msg_unicast;
|
struct mdns_outmsg delayed_msg_unicast;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* MDNS states */
|
||||||
|
typedef enum {
|
||||||
|
/* MDNS module is off */
|
||||||
|
MDNS_STATE_OFF,
|
||||||
|
/* Waiting before probing can be started */
|
||||||
|
MDNS_STATE_PROBE_WAIT,
|
||||||
|
/* Probing the unique records */
|
||||||
|
MDNS_STATE_PROBING,
|
||||||
|
/* Waiting before announcing the probed unique records */
|
||||||
|
MDNS_STATE_ANNOUNCE_WAIT,
|
||||||
|
/* Announcing all records */
|
||||||
|
MDNS_STATE_ANNOUNCING,
|
||||||
|
/* Probing and announcing completed */
|
||||||
|
MDNS_STATE_COMPLETE
|
||||||
|
} acd_state_enum_t;
|
||||||
|
|
||||||
/** Description of a host/netif */
|
/** Description of a host/netif */
|
||||||
struct mdns_host {
|
struct mdns_host {
|
||||||
/** Hostname */
|
/** Hostname */
|
||||||
char name[MDNS_LABEL_MAXLEN + 1];
|
char name[MDNS_LABEL_MAXLEN + 1];
|
||||||
/** Pointer to services */
|
/** Pointer to services */
|
||||||
struct mdns_service *services[MDNS_MAX_SERVICES];
|
struct mdns_service *services[MDNS_MAX_SERVICES];
|
||||||
/** Number of probes sent for the current name */
|
/** Number of probes/announces sent for the current name */
|
||||||
u8_t probes_sent;
|
u8_t sent_num;
|
||||||
/** State in probing sequence */
|
/** State of the mdns responder */
|
||||||
u8_t probing_state;
|
acd_state_enum_t state;
|
||||||
#if LWIP_IPV4
|
#if LWIP_IPV4
|
||||||
/** delayed msg struct for IPv4 */
|
/** delayed msg struct for IPv4 */
|
||||||
struct mdns_delayed_msg ipv4;
|
struct mdns_delayed_msg ipv4;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user