Compare commits
2 Commits
79f330859e
...
3d5c99570f
| Author | SHA1 | Date | |
|---|---|---|---|
| 3d5c99570f | |||
| c01c655c5f |
@@ -92,9 +92,9 @@ If this call returns successfully, the following queries will be answered:
|
||||
LWIP_ERROR("mdns add service txt failed\n", (res == ERR_OK), return);
|
||||
}
|
||||
|
||||
Since a hostname struct is used for TXT storage each single item can be max
|
||||
63 bytes long, and the total max length (including length bytes for each
|
||||
item) is 255 bytes.
|
||||
Each item is encoded as a length byte followed by the data, so each single
|
||||
item can be max 255 bytes long, and the total max length (including length
|
||||
bytes for each item) is defined by MDNS_TXT_RDATA_SIZE (default 255).
|
||||
|
||||
If your device runs a webserver on port 80, an example call might be:
|
||||
|
||||
|
||||
@@ -1272,7 +1272,7 @@ mdns_parse_pkt_known_answers(struct netif *netif, struct mdns_packet *pkt,
|
||||
} else if (match & REPLY_SERVICE_TXT) {
|
||||
mdns_prepare_txtdata(service);
|
||||
if (service->txtdata.length == ans.rd_length &&
|
||||
pbuf_memcmp(pkt->pbuf, ans.rd_offset, service->txtdata.name, ans.rd_length) == 0) {
|
||||
pbuf_memcmp(pkt->pbuf, ans.rd_offset, service->txtdata.rdata, ans.rd_length) == 0) {
|
||||
LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: TXT\n"));
|
||||
reply->serv_replies[i] &= ~REPLY_SERVICE_TXT;
|
||||
}
|
||||
@@ -2050,7 +2050,7 @@ mdns_handle_response(struct mdns_packet *pkt, struct netif *netif)
|
||||
} else if (ans.info.type == DNS_RRTYPE_TXT) {
|
||||
mdns_prepare_txtdata(service);
|
||||
if (service->txtdata.length == ans.rd_length &&
|
||||
pbuf_memcmp(pkt->pbuf, ans.rd_offset, service->txtdata.name, ans.rd_length) == 0) {
|
||||
pbuf_memcmp(pkt->pbuf, ans.rd_offset, service->txtdata.rdata, ans.rd_length) == 0) {
|
||||
LWIP_DEBUGF(MDNS_DEBUG, ("mDNS: response equals our own TXT record -> no conflict\n"));
|
||||
conflict = 0;
|
||||
}
|
||||
@@ -2613,10 +2613,29 @@ mdns_resp_rename_service(struct netif *netif, u8_t slot, const char *name)
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/* Adds an RFC 1035 character-string to TXT RDATA. */
|
||||
static err_t
|
||||
mdns_txt_add_charstr(struct mdns_txtdata *txtdata, const char *value, u8_t len)
|
||||
{
|
||||
if (1 + len + txtdata->length > MDNS_TXT_RDATA_SIZE) {
|
||||
LWIP_DEBUGF(MDNS_DEBUG, ("mdns_txt_add_charstr: adding string would exceed buffer (1+%d+%d > %d). Consider increasing MDNS_TXT_RDATA_SIZE.\n",
|
||||
len, txtdata->length, MDNS_TXT_RDATA_SIZE));
|
||||
return ERR_MEM;
|
||||
}
|
||||
txtdata->rdata[txtdata->length] = len;
|
||||
txtdata->length++;
|
||||
if (len) {
|
||||
MEMCPY(&txtdata->rdata[txtdata->length], value, len);
|
||||
txtdata->length += len;
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup mdns
|
||||
* Call this function from inside the service_get_txt_fn_t callback to add text data.
|
||||
* Buffer for TXT data is 256 bytes, and each field is prefixed with a length byte.
|
||||
* Buffer for TXT data is MDNS_TXT_RDATA_SIZE (default 256) bytes, and each
|
||||
* field is prefixed with a length byte.
|
||||
* @param service The service provided to the get_txt callback
|
||||
* @param txt String to add to the TXT field.
|
||||
* @param txt_len Length of string
|
||||
@@ -2629,7 +2648,7 @@ mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_
|
||||
LWIP_ASSERT("mdns_resp_add_service_txtitem: service != NULL", service);
|
||||
|
||||
/* Use a mdns_domain struct to store txt chunks since it is the same encoding */
|
||||
return mdns_domain_add_label(&service->txtdata, txt, txt_len);
|
||||
return mdns_txt_add_charstr(&service->txtdata, txt, txt_len);
|
||||
}
|
||||
|
||||
#if LWIP_MDNS_SEARCH
|
||||
|
||||
@@ -62,7 +62,7 @@ static void mdns_clear_outmsg(struct mdns_outmsg *outmsg);
|
||||
void
|
||||
mdns_prepare_txtdata(struct mdns_service *service)
|
||||
{
|
||||
memset(&service->txtdata, 0, sizeof(struct mdns_domain));
|
||||
memset(&service->txtdata, 0, sizeof(struct mdns_txtdata));
|
||||
if (service->txt_fn) {
|
||||
service->txt_fn(service, service->txt_userdata);
|
||||
}
|
||||
@@ -508,7 +508,7 @@ mdns_add_txt_answer(struct mdns_outpacket *reply, struct mdns_outmsg *msg,
|
||||
}
|
||||
LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with TXT record\n"));
|
||||
return mdns_add_answer(reply, &service_instance, DNS_RRTYPE_TXT, DNS_RRCLASS_IN,
|
||||
msg->cache_flush, ttl, (u8_t *) &service->txtdata.name,
|
||||
msg->cache_flush, ttl, service->txtdata.rdata,
|
||||
service->txtdata.length, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -88,6 +88,12 @@
|
||||
#define MDNS_OUTPUT_PACKET_SIZE ((MDNS_MAX_SERVICES == 1) ? 512 : 1450)
|
||||
#endif
|
||||
|
||||
/** The maximum size of TXT RDATA allocated for each service.
|
||||
*/
|
||||
#ifndef MDNS_TXT_RDATA_SIZE
|
||||
# define MDNS_TXT_RDATA_SIZE 256
|
||||
#endif
|
||||
|
||||
/** MDNS_RESP_USENETIF_EXTCALLBACK==1: register an ext_callback on the netif
|
||||
* to automatically restart probing/announcing on status or address change.
|
||||
*/
|
||||
|
||||
@@ -90,10 +90,16 @@ struct mdns_request {
|
||||
};
|
||||
#endif
|
||||
|
||||
/** TXT record data */
|
||||
struct mdns_txtdata {
|
||||
u8_t rdata[MDNS_TXT_RDATA_SIZE];
|
||||
u16_t length;
|
||||
};
|
||||
|
||||
/** Description of a service */
|
||||
struct mdns_service {
|
||||
/** TXT record to answer with */
|
||||
struct mdns_domain txtdata;
|
||||
struct mdns_txtdata txtdata;
|
||||
/** Name of service, like 'myweb' */
|
||||
char name[MDNS_LABEL_MAXLEN + 1];
|
||||
/** Type of service, like '_http' */
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/apps/mdns.h"
|
||||
#include "lwip/apps/mdns_domain.h"
|
||||
#include "lwip/apps/mdns_out.h"
|
||||
#include "lwip/apps/mdns_priv.h"
|
||||
|
||||
START_TEST(readname_basic)
|
||||
@@ -876,6 +877,155 @@ START_TEST(compress_long_match)
|
||||
}
|
||||
END_TEST
|
||||
|
||||
#define TXT_STRING_1 "path=/"
|
||||
#define TXT_LENGTH_1 6
|
||||
#define TXT_LENSTR_1 "\006"
|
||||
|
||||
#define TXT_STRING_2 ""
|
||||
#define TXT_LENGTH_2 0
|
||||
#define TXT_LENSTR_2 "\000"
|
||||
|
||||
#define TXT_STRING_3 "This sentence is sixty-three bytes long, including punctuation."
|
||||
#define TXT_LENGTH_3 63
|
||||
#define TXT_LENSTR_3 "\077"
|
||||
|
||||
#define TXT_STRING_4 "This tests whether mdns_resp_add_service_txtitem can properly handle strings longer than 63 characters."
|
||||
#define TXT_LENGTH_4 103
|
||||
#define TXT_LENSTR_4 "\147"
|
||||
|
||||
START_TEST(txt_short_item)
|
||||
{
|
||||
const char *expected_txtdata = TXT_LENSTR_1 TXT_STRING_1;
|
||||
const size_t expected_txtdata_length = 1 + TXT_LENGTH_1;
|
||||
|
||||
struct mdns_service service;
|
||||
err_t res;
|
||||
memset(&service, 0, sizeof(struct mdns_service));
|
||||
|
||||
mdns_prepare_txtdata(&service);
|
||||
res = mdns_resp_add_service_txtitem(&service, TXT_STRING_1, TXT_LENGTH_1);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
fail_unless(service.txtdata.length == expected_txtdata_length);
|
||||
fail_if(memcmp(service.txtdata.rdata, expected_txtdata, expected_txtdata_length));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(txt_empty_item)
|
||||
{
|
||||
const char *expected_txtdata = TXT_LENSTR_2 TXT_STRING_2;
|
||||
const size_t expected_txtdata_length = 1 + TXT_LENGTH_2;
|
||||
|
||||
struct mdns_service service;
|
||||
err_t res;
|
||||
memset(&service, 0, sizeof(struct mdns_service));
|
||||
|
||||
mdns_prepare_txtdata(&service);
|
||||
res = mdns_resp_add_service_txtitem(&service, TXT_STRING_2, TXT_LENGTH_2);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
fail_unless(service.txtdata.length == expected_txtdata_length);
|
||||
fail_if(memcmp(service.txtdata.rdata, expected_txtdata, expected_txtdata_length));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(txt_long_item)
|
||||
{
|
||||
const char *expected_txtdata = TXT_LENSTR_4 TXT_STRING_4;
|
||||
const size_t expected_txtdata_length = 1 + TXT_LENGTH_4;
|
||||
|
||||
struct mdns_service service;
|
||||
err_t res;
|
||||
memset(&service, 0, sizeof(struct mdns_service));
|
||||
|
||||
mdns_prepare_txtdata(&service);
|
||||
res = mdns_resp_add_service_txtitem(&service, TXT_STRING_4, TXT_LENGTH_4);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
fail_unless(service.txtdata.length == expected_txtdata_length);
|
||||
fail_if(memcmp(service.txtdata.rdata, expected_txtdata, expected_txtdata_length));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(txt_multiple_items)
|
||||
{
|
||||
const char *expected_txtdata = (
|
||||
TXT_LENSTR_1
|
||||
TXT_STRING_1
|
||||
TXT_LENSTR_2
|
||||
TXT_STRING_2
|
||||
TXT_LENSTR_3
|
||||
TXT_STRING_3
|
||||
TXT_LENSTR_4
|
||||
TXT_STRING_4
|
||||
);
|
||||
const size_t expected_txtdata_length = (
|
||||
1 + TXT_LENGTH_1
|
||||
+ 1 + TXT_LENGTH_2
|
||||
+ 1 + TXT_LENGTH_3
|
||||
+ 1 + TXT_LENGTH_4
|
||||
);
|
||||
|
||||
struct mdns_service service;
|
||||
err_t res;
|
||||
memset(&service, 0, sizeof(struct mdns_service));
|
||||
|
||||
mdns_prepare_txtdata(&service);
|
||||
|
||||
res = mdns_resp_add_service_txtitem(&service, TXT_STRING_1, TXT_LENGTH_1);
|
||||
fail_unless(res == ERR_OK); /* TXT_STRING_1 */
|
||||
|
||||
res = mdns_resp_add_service_txtitem(&service, TXT_STRING_2, TXT_LENGTH_2);
|
||||
fail_unless(res == ERR_OK); /* TXT_STRING_1 */
|
||||
|
||||
res = mdns_resp_add_service_txtitem(&service, TXT_STRING_3, TXT_LENGTH_3);
|
||||
fail_unless(res == ERR_OK); /* TXT_STRING_3 */
|
||||
|
||||
res = mdns_resp_add_service_txtitem(&service, TXT_STRING_4, TXT_LENGTH_4);
|
||||
fail_unless(res == ERR_OK); /* TXT_STRING_4 */
|
||||
|
||||
fail_unless(service.txtdata.length == expected_txtdata_length);
|
||||
fail_if(memcmp(service.txtdata.rdata, expected_txtdata, expected_txtdata_length));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(txt_buffer_full)
|
||||
{
|
||||
const char *expected_txtdata = (
|
||||
TXT_LENSTR_3 TXT_STRING_3
|
||||
TXT_LENSTR_3 TXT_STRING_3
|
||||
TXT_LENSTR_3 TXT_STRING_3
|
||||
TXT_LENSTR_3 TXT_STRING_3
|
||||
);
|
||||
const size_t expected_txtdata_length = 256;
|
||||
|
||||
struct mdns_service service;
|
||||
err_t res;
|
||||
int i;
|
||||
memset(&service, 0, sizeof(struct mdns_service));
|
||||
|
||||
mdns_prepare_txtdata(&service);
|
||||
|
||||
/* add a 64-byte string 4 times = 256 bytes */
|
||||
for (i = 0; i < 4; i++) {
|
||||
res = mdns_resp_add_service_txtitem(&service, TXT_STRING_3, TXT_LENGTH_3);
|
||||
ck_assert_msg(res == ERR_OK,
|
||||
"adding text item failed with error %d (i=%d, txtdata.length=%d)",
|
||||
res, i, service.txtdata.length);
|
||||
}
|
||||
|
||||
/* Try to add a few more strings while the buffer is full. This should fail. */
|
||||
res = mdns_resp_add_service_txtitem(&service, "", 0);
|
||||
fail_unless(res != ERR_OK); /* empty string */
|
||||
|
||||
res = mdns_resp_add_service_txtitem(&service, "path=/", 6);
|
||||
fail_unless(res != ERR_OK); /* short string */
|
||||
|
||||
fail_unless(service.txtdata.length == expected_txtdata_length);
|
||||
fail_if(memcmp(service.txtdata.rdata, expected_txtdata, expected_txtdata_length));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite* mdns_suite(void)
|
||||
{
|
||||
testfunc tests[] = {
|
||||
@@ -911,6 +1061,12 @@ Suite* mdns_suite(void)
|
||||
TESTFUNC(compress_2nd_label_short),
|
||||
TESTFUNC(compress_jump_to_jump),
|
||||
TESTFUNC(compress_long_match),
|
||||
|
||||
TESTFUNC(txt_short_item),
|
||||
TESTFUNC(txt_empty_item),
|
||||
TESTFUNC(txt_long_item),
|
||||
TESTFUNC(txt_multiple_items),
|
||||
TESTFUNC(txt_buffer_full),
|
||||
};
|
||||
return create_suite("MDNS", tests, sizeof(tests)/sizeof(testfunc), NULL, NULL);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user