diff --git a/src/apps/mdns/mdns.c b/src/apps/mdns/mdns.c index 84f267a6..f87ea921 100644 --- a/src/apps/mdns/mdns.c +++ b/src/apps/mdns/mdns.c @@ -2513,12 +2513,14 @@ mdns_resp_netif_active(struct netif *netif) * @param txt_fn Callback to get TXT data. Will be called each time a TXT reply is created to * allow dynamic replies. * @param txt_data Userdata pointer for txt_fn + * @param subTypes table contanins all subtypes of the service + * param subtypes_nbr the number of the subtypes linked to that service, it should be <=MDNS_MAX_SERVICES_SUBTYPES * @return service_id if the service was added to the netif, an err_t otherwise */ s8_t -mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, service_get_txt_fn_t txt_fn, void *txt_data) +mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, service_get_txt_fn_t txt_fn, void *txt_data, char **subTypes, u8_t subtypes_nbr ) { - u8_t slot; + u8_t slot,i; struct mdns_service *srv; struct mdns_host *mdns; @@ -2543,10 +2545,13 @@ mdns_resp_add_service(struct netif *netif, const char *name, const char *service MEMCPY(&srv->name, name, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(name))); MEMCPY(&srv->service, service, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(service))); + for(i=0;isubTypes[i], subTypes[i], LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(subTypes[i]))); srv->txt_fn = txt_fn; srv->txt_userdata = txt_data; srv->proto = (u16_t)proto; srv->port = port; + srv->subtypes_nbr = subtypes_nbr; mdns->services[slot] = srv; diff --git a/src/apps/mdns/mdns_domain.c b/src/apps/mdns/mdns_domain.c index 265b5e6a..1839ee2b 100644 --- a/src/apps/mdns/mdns_domain.c +++ b/src/apps/mdns/mdns_domain.c @@ -632,4 +632,30 @@ mdns_write_domain(struct mdns_outpacket *outpkt, struct mdns_domain *domain) return ERR_OK; } +/** + * Build domain name for a subtype service + * @param domain Where to write the domain name + * @param service The service struct, containing service name, type and protocol + * @param include_name Whether to include the service name in the domain + * @return ERR_OK if domain was written. If service name is included, + * \.\<_sub\>.\.\.local. will be written, otherwise \.\.local. + * An err_t is returned on error. + */ +err_t +mdns_build_subtype_service_domain(struct mdns_domain *domain, struct mdns_service *service, int subTypes_index) +{ + err_t res; + LWIP_UNUSED_ARG(res); + memset(domain, 0, sizeof(struct mdns_domain)); + res = mdns_domain_add_label(domain, service->subTypes[subTypes_index], strlen(service->subTypes[subTypes_index])); + LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, "_sub", 4); + LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, service->service, (u8_t)strlen(service->service)); + LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, dnssd_protos[service->proto], (u8_t)strlen(dnssd_protos[service->proto])); + LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); + return mdns_add_dotlocal(domain); +} + #endif /* LWIP_MDNS_RESPONDER */ diff --git a/src/apps/mdns/mdns_out.c b/src/apps/mdns/mdns_out.c index 5c6d26b7..b470667c 100644 --- a/src/apps/mdns/mdns_out.c +++ b/src/apps/mdns/mdns_out.c @@ -54,7 +54,7 @@ /* Function prototypes */ static void mdns_clear_outmsg(struct mdns_outmsg *outmsg); - +static err_t mdns_add_service_subtype_ptr_answer(struct mdns_outpacket *reply, struct mdns_outmsg *msg, struct mdns_service *service); /** * Call user supplied function to setup TXT data * @param service The service to build TXT record for @@ -660,6 +660,8 @@ mdns_create_outpacket(struct netif *netif, struct mdns_outmsg *msg, if (msg->serv_replies[i] & REPLY_SERVICE_NAME_PTR) { res = mdns_add_servicename_ptr_answer(outpkt, msg, service); + /*if a subtype is used, that following function write answer of the subtype service PTR RR to outpacket*/ + res = mdns_add_service_subtype_ptr_answer(outpkt, msg, service); if (res != ERR_OK) { return res; } @@ -1160,4 +1162,39 @@ mdns_send_request(struct mdns_request *req, struct netif *netif, const ip_addr_t } #endif +/** Write an all subtype services -> PTR RR to outpacket */ +static err_t +mdns_add_service_subtype_ptr_answer(struct mdns_outpacket *reply, struct mdns_outmsg *msg, + struct mdns_service *service) +{ + err_t res = ERR_OK; + u8_t subtyes_index; + u32_t ttl = MDNS_TTL_4500; + struct mdns_domain service_type, sub_service; + for(subtyes_index=0;subtyes_index < LWIP_MIN(service->subtypes_nbr,MDNS_MAX_SERVICES_SUBTYPES); subtyes_index++) + { + res =mdns_build_subtype_service_domain(&sub_service, service,subtyes_index); + res =mdns_build_service_domain(&service_type, service, 1); + /* When answering to a legacy querier, we need to repeat the question and + * limit the ttl to the short legacy ttl */ + if(msg->legacy_query) { + /* Repeating the question only needs to be done for the question asked + * (max one question), not for the additional records. */ + if(reply->questions < 1) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Add question for legacy query\n")); + res = mdns_add_question(reply, &sub_service, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, 0); + if (res != ERR_OK) { + return res; + } + reply->questions = 1; + } + /* ttl of legacy answer may not be greater then 10 seconds */ + ttl = MDNS_TTL_10; + } + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with service type PTR record\n")); + res =mdns_add_answer(reply, &sub_service, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, + 0, ttl, NULL, 0, &service_type); + } + return res; +} #endif /* LWIP_MDNS_RESPONDER */ diff --git a/src/include/lwip/apps/mdns.h b/src/include/lwip/apps/mdns.h index 33da4a3e..9480415d 100644 --- a/src/include/lwip/apps/mdns.h +++ b/src/include/lwip/apps/mdns.h @@ -112,7 +112,7 @@ err_t mdns_resp_remove_netif(struct netif *netif); err_t mdns_resp_rename_netif(struct netif *netif, const char *hostname); int mdns_resp_netif_active(struct netif *netif); -s8_t mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, service_get_txt_fn_t txt_fn, void *txt_userdata); +s8_t mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, service_get_txt_fn_t txt_fn, void *txt_data, char **subTypes, u8_t subtypes_nbr ); err_t mdns_resp_del_service(struct netif *netif, u8_t slot); err_t mdns_resp_rename_service(struct netif *netif, u8_t slot, const char *name); diff --git a/src/include/lwip/apps/mdns_domain.h b/src/include/lwip/apps/mdns_domain.h index 9fa804e6..140029b3 100644 --- a/src/include/lwip/apps/mdns_domain.h +++ b/src/include/lwip/apps/mdns_domain.h @@ -70,7 +70,7 @@ err_t mdns_build_request_domain(struct mdns_domain *domain, struct mdns_request #endif u16_t mdns_compress_domain(struct pbuf *pbuf, u16_t *offset, struct mdns_domain *domain); err_t mdns_write_domain(struct mdns_outpacket *outpkt, struct mdns_domain *domain); - +err_t mdns_build_subtype_service_domain(struct mdns_domain *domain, struct mdns_service *service, int subTypes_index); #endif /* LWIP_MDNS_RESPONDER */ #ifdef __cplusplus diff --git a/src/include/lwip/apps/mdns_opts.h b/src/include/lwip/apps/mdns_opts.h index 1eee3e38..03e5ff55 100644 --- a/src/include/lwip/apps/mdns_opts.h +++ b/src/include/lwip/apps/mdns_opts.h @@ -52,12 +52,14 @@ * transport. IGMP is needed for IPv4 multicast. */ #ifndef LWIP_MDNS_RESPONDER -#define LWIP_MDNS_RESPONDER 0 +#define LWIP_MDNS_RESPONDER 1 #endif /* LWIP_MDNS_RESPONDER */ /** The maximum number of services per netif */ #ifndef MDNS_MAX_SERVICES #define MDNS_MAX_SERVICES 1 +/** The maximum number of subtypes per service */ +#define MDNS_MAX_SERVICES_SUBTYPES 4 #endif /** The minimum delay between probes in ms. RFC 6762 require 250ms. diff --git a/src/include/lwip/apps/mdns_priv.h b/src/include/lwip/apps/mdns_priv.h index 5209ba00..1576531b 100644 --- a/src/include/lwip/apps/mdns_priv.h +++ b/src/include/lwip/apps/mdns_priv.h @@ -98,14 +98,18 @@ struct mdns_service { char name[MDNS_LABEL_MAXLEN + 1]; /** Type of service, like '_http' */ char service[MDNS_LABEL_MAXLEN + 1]; - /** Callback function and userdata - * to update txtdata buffer */ + /** SubType of service, like '_printer' */ + char subTypes[MDNS_MAX_SERVICES_SUBTYPES][MDNS_LABEL_MAXLEN + 1]; + /** Callback function and userdata/* + /* to update txtdata buffer */ service_get_txt_fn_t txt_fn; void *txt_userdata; /** Protocol, TCP or UDP */ u16_t proto; /** Port of the service */ u16_t port; + /** Number of the subtypes of a service */ + u16_t subtypes_nbr; }; /** mDNS output packet */