mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-10-24 12:24:29 +08:00
Commit ID: 2f8508c7 1. Fix possible crash when probing on particular interface with duplicated service instances due to naming conflicts on network. Issue: MDNS server initially sends probing packets to resolve naming confilicts with already registered service instances. In case of a conflict, instance name is altered and probing restarts. Original instance however wasnnot removed from the structure and upon service removal only one entry was removed and a dangling service might have been kept in the structure to bring about a crash. Resolution: Keep only one instance of a service in the probing structure 2. Enable pcbs before starting service thread to avoid updating pcb's internal variables from concurent tasks. Possible race condition: user task runs mdns_init, which enables pcbs while mdns-task already created could execute enable/disable of the same pcbs if an appropriate system event received 3. Fix possible deadlock on mdns deinit calling mdns_free(). Mnds_free() initiates stop and delete timer tasks, which after locking the mutex could lead to a dead lock in case timer task executed before deleting the task, as it would wait indefinitelly for unlocking the mutex. This condition is fixed by calling _mdns_stop_timer without locking the mutex, because there's no need to protect any data when stopping and deleting the timer task 4. Fix race condition in updating packet data from user task when failed to allocate or queue a new service. Issue: mdns_service_add API allocates and queues an action to be processed in mdns task context; when allocation or queueing fails, allocated structure needs to be freed. Function _mdns_free_service did not only fee all the structures, but also updates packet data. Resolution: Moved removal of packet data outside of _mdns_free_service function 5. Fix possible crash when packet scheduled to transmit contained service which might have been already removed. Packets scheduled to transmit are pushed to action queue and removed from tx_queue_head structure, which is searched for all remaining services and while service is removed, then service questions/asnwers are also removed from this structure. This update fixes possible crash when packet is pushed to action queue, and when service is removed, its answers are removed from tx_queue_head, but not from action queue. This could lead to a crash when the packet is poped from action queue containing questions/answers to already removed (freed) service 6. Use binary semaphore instead of mutex when searching. Mdns_search_once_t::lock is used to synchronize tasks (taken by one task and given by the other) so it should not be a mutex. Convert to semaphore, and rename to indicate its purpose 7. Fix memory leak in pbuf if tcpipadapter failed to get netif 8. Fix malfuctional query_txt. When running a query for a single txt, result entries were not created and attached to result structure. This issue was introduced when fixing memory leak in txt structure, which worked correctly for PTR queries, but caused trouble for TXT query 9. Fix possible crash when mdns_free called while action queue not empty 10. Fix memory leak when query for service receives multiple ptr entries for one instance 11. Fix crash after init if no memory for task. Mdns init first starts timer task, then starts service task. If service task failed to be created, timer task needs to be stopped too 12. Fixed crash on free undefined ptr after skipped strdup. Shortcircuit evaluation may cause skip of _mdns_strdup_check of any further question field, which after clear_rx_packet freed undefined memory 13. Fix networking running udp_sendif from lwip thread 14. Check all mallocs for failure and add default hook to log error with free heap. Solves crash about _mdns_result_txt_create when stress test 15. Fixed static memory leak 16. Resolve memory leak when txt record received multiple times 17. Skip sending search when finished, not properly locked timer task 18. Sending search packets also in probing and announcing state. Mdns queries did not work properly when send imeadiately after set_hostname, which cuased reinit of pcb and therefore restarted probing, so search packets were blocked until probing finished
1061 lines
32 KiB
C
1061 lines
32 KiB
C
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "esp_console.h"
|
|
#include "argtable3/argtable3.h"
|
|
#include "mdns.h"
|
|
|
|
static const char * if_str[] = {"STA", "AP", "ETH", "MAX"};
|
|
static const char * ip_protocol_str[] = {"V4", "V6", "MAX"};
|
|
|
|
static void mdns_print_results(mdns_result_t * results)
|
|
{
|
|
mdns_result_t * r = results;
|
|
mdns_ip_addr_t * a = NULL;
|
|
int i = 1, t;
|
|
while (r) {
|
|
printf("%d: Interface: %s, Type: %s\n", i++, if_str[r->tcpip_if], ip_protocol_str[r->ip_protocol]);
|
|
if (r->instance_name) {
|
|
printf(" PTR : %s\n", r->instance_name);
|
|
}
|
|
if (r->hostname) {
|
|
printf(" SRV : %s.local:%u\n", r->hostname, r->port);
|
|
}
|
|
if (r->txt_count) {
|
|
printf(" TXT : [%u] ", r->txt_count);
|
|
for (t=0; t<r->txt_count; t++) {
|
|
printf("%s=%s; ", r->txt[t].key, r->txt[t].value);
|
|
}
|
|
printf("\n");
|
|
}
|
|
a = r->addr;
|
|
while (a) {
|
|
if (a->addr.type == IPADDR_TYPE_V6) {
|
|
printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6));
|
|
} else {
|
|
printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4)));
|
|
}
|
|
a = a->next;
|
|
}
|
|
r = r->next;
|
|
}
|
|
}
|
|
|
|
static struct {
|
|
struct arg_str *hostname;
|
|
struct arg_int *timeout;
|
|
struct arg_end *end;
|
|
} mdns_query_a_args;
|
|
|
|
static int cmd_mdns_query_a(int argc, char** argv)
|
|
{
|
|
int nerrors = arg_parse(argc, argv, (void**) &mdns_query_a_args);
|
|
if (nerrors != 0) {
|
|
arg_print_errors(stderr, mdns_query_a_args.end, argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
const char * hostname = mdns_query_a_args.hostname->sval[0];
|
|
int timeout = mdns_query_a_args.timeout->ival[0];
|
|
|
|
if (!hostname || !hostname[0]) {
|
|
printf("ERROR: Hostname not supplied\n");
|
|
return 1;
|
|
}
|
|
|
|
if (timeout <= 0) {
|
|
timeout = 1000;
|
|
}
|
|
|
|
printf("Query A: %s.local, Timeout: %d\n", hostname, timeout);
|
|
|
|
struct ip4_addr addr;
|
|
addr.addr = 0;
|
|
|
|
esp_err_t err = mdns_query_a(hostname, timeout, &addr);
|
|
if (err) {
|
|
if (err == ESP_ERR_NOT_FOUND) {
|
|
printf("ERROR: Host was not found!\n");
|
|
return 0;
|
|
}
|
|
printf("ERROR: Query Failed\n");
|
|
return 1;
|
|
}
|
|
|
|
printf(IPSTR "\n", IP2STR(&addr));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void register_mdns_query_a()
|
|
{
|
|
mdns_query_a_args.hostname = arg_str1(NULL, NULL, "<hostname>", "Hostname that is searched for");
|
|
mdns_query_a_args.timeout = arg_int0("t", "timeout", "<timeout>", "Timeout for this query");
|
|
mdns_query_a_args.end = arg_end(2);
|
|
|
|
const esp_console_cmd_t cmd_init = {
|
|
.command = "mdns_query_a",
|
|
.help = "Query MDNS for IPv4",
|
|
.hint = NULL,
|
|
.func = &cmd_mdns_query_a,
|
|
.argtable = &mdns_query_a_args
|
|
};
|
|
|
|
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_init) );
|
|
}
|
|
|
|
static int cmd_mdns_query_aaaa(int argc, char** argv)
|
|
{
|
|
int nerrors = arg_parse(argc, argv, (void**) &mdns_query_a_args);
|
|
if (nerrors != 0) {
|
|
arg_print_errors(stderr, mdns_query_a_args.end, argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
const char * hostname = mdns_query_a_args.hostname->sval[0];
|
|
int timeout = mdns_query_a_args.timeout->ival[0];
|
|
|
|
if (!hostname || !hostname[0]) {
|
|
printf("ERROR: Hostname not supplied\n");
|
|
return 1;
|
|
}
|
|
|
|
if (timeout <= 0) {
|
|
timeout = 1000;
|
|
}
|
|
|
|
printf("Query AAAA: %s.local, Timeout: %d\n", hostname, timeout);
|
|
|
|
struct ip6_addr addr;
|
|
memset(addr.addr, 0, 16);
|
|
|
|
esp_err_t err = mdns_query_aaaa(hostname, timeout, &addr);
|
|
if (err) {
|
|
if (err == ESP_ERR_NOT_FOUND) {
|
|
printf("Host was not found!\n");
|
|
return 0;
|
|
}
|
|
printf("ERROR: Query Failed\n");
|
|
return 1;
|
|
}
|
|
|
|
printf(IPV6STR "\n", IPV62STR(addr));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void register_mdns_query_aaaa()
|
|
{
|
|
mdns_query_a_args.hostname = arg_str1(NULL, NULL, "<hostname>", "Hostname that is searched for");
|
|
mdns_query_a_args.timeout = arg_int0("t", "timeout", "<timeout>", "Timeout for this query");
|
|
mdns_query_a_args.end = arg_end(2);
|
|
|
|
const esp_console_cmd_t cmd_init = {
|
|
.command = "mdns_query_aaaa",
|
|
.help = "Query MDNS for IPv6",
|
|
.hint = NULL,
|
|
.func = &cmd_mdns_query_aaaa,
|
|
.argtable = &mdns_query_a_args
|
|
};
|
|
|
|
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_init) );
|
|
}
|
|
|
|
static struct {
|
|
struct arg_str *instance;
|
|
struct arg_str *service;
|
|
struct arg_str *proto;
|
|
struct arg_int *timeout;
|
|
struct arg_end *end;
|
|
} mdns_query_srv_args;
|
|
|
|
static int cmd_mdns_query_srv(int argc, char** argv)
|
|
{
|
|
int nerrors = arg_parse(argc, argv, (void**) &mdns_query_srv_args);
|
|
if (nerrors != 0) {
|
|
arg_print_errors(stderr, mdns_query_srv_args.end, argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
const char * instance = mdns_query_srv_args.instance->sval[0];
|
|
const char * service = mdns_query_srv_args.service->sval[0];
|
|
const char * proto = mdns_query_srv_args.proto->sval[0];
|
|
int timeout = mdns_query_srv_args.timeout->ival[0];
|
|
|
|
if (timeout <= 0) {
|
|
timeout = 1000;
|
|
}
|
|
|
|
printf("Query SRV: %s.%s.%s.local, Timeout: %d\n", instance, service, proto, timeout);
|
|
|
|
mdns_result_t * results = NULL;
|
|
esp_err_t err = mdns_query_srv(instance, service, proto, timeout, &results);
|
|
if (err) {
|
|
printf("ERROR: Query Failed\n");
|
|
return 1;
|
|
}
|
|
if (!results) {
|
|
printf("No results found!\n");
|
|
return 0;
|
|
}
|
|
mdns_print_results(results);
|
|
mdns_query_results_free(results);
|
|
return 0;
|
|
}
|
|
|
|
static void register_mdns_query_srv()
|
|
{
|
|
mdns_query_srv_args.instance = arg_str1(NULL, NULL, "<instance>", "Instance to search for");
|
|
mdns_query_srv_args.service = arg_str1(NULL, NULL, "<service>", "Service to search for (ex. _http, _smb, etc.)");
|
|
mdns_query_srv_args.proto = arg_str1(NULL, NULL, "<proto>", "Protocol to search for (_tcp, _udp, etc.)");
|
|
mdns_query_srv_args.timeout = arg_int0("t", "timeout", "<timeout>", "Timeout for this query");
|
|
mdns_query_srv_args.end = arg_end(2);
|
|
|
|
const esp_console_cmd_t cmd_init = {
|
|
.command = "mdns_query_srv",
|
|
.help = "Query MDNS for Service SRV",
|
|
.hint = NULL,
|
|
.func = &cmd_mdns_query_srv,
|
|
.argtable = &mdns_query_srv_args
|
|
};
|
|
|
|
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_init) );
|
|
}
|
|
|
|
static struct {
|
|
struct arg_str *instance;
|
|
struct arg_str *service;
|
|
struct arg_str *proto;
|
|
struct arg_int *timeout;
|
|
struct arg_end *end;
|
|
} mdns_query_txt_args;
|
|
|
|
static int cmd_mdns_query_txt(int argc, char** argv)
|
|
{
|
|
int nerrors = arg_parse(argc, argv, (void**) &mdns_query_txt_args);
|
|
if (nerrors != 0) {
|
|
arg_print_errors(stderr, mdns_query_txt_args.end, argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
const char * instance = mdns_query_txt_args.instance->sval[0];
|
|
const char * service = mdns_query_txt_args.service->sval[0];
|
|
const char * proto = mdns_query_txt_args.proto->sval[0];
|
|
int timeout = mdns_query_txt_args.timeout->ival[0];
|
|
|
|
printf("Query TXT: %s.%s.%s.local, Timeout: %d\n", instance, service, proto, timeout);
|
|
|
|
if (timeout <= 0) {
|
|
timeout = 5000;
|
|
}
|
|
|
|
mdns_result_t * results = NULL;
|
|
esp_err_t err = mdns_query_txt(instance, service, proto, timeout, &results);
|
|
if (err) {
|
|
printf("ERROR: Query Failed\n");
|
|
return 1;
|
|
}
|
|
if (!results) {
|
|
printf("No results found!\n");
|
|
return 0;
|
|
}
|
|
|
|
mdns_print_results(results);
|
|
mdns_query_results_free(results);
|
|
return 0;
|
|
}
|
|
|
|
static void register_mdns_query_txt()
|
|
{
|
|
mdns_query_txt_args.instance = arg_str1(NULL, NULL, "<instance>", "Instance to search for");
|
|
mdns_query_txt_args.service = arg_str1(NULL, NULL, "<service>", "Service to search for (ex. _http, _smb, etc.)");
|
|
mdns_query_txt_args.proto = arg_str1(NULL, NULL, "<proto>", "Protocol to search for (_tcp, _udp, etc.)");
|
|
mdns_query_txt_args.timeout = arg_int0("t", "timeout", "<timeout>", "Timeout for this query");
|
|
mdns_query_txt_args.end = arg_end(2);
|
|
|
|
const esp_console_cmd_t cmd_init = {
|
|
.command = "mdns_query_txt",
|
|
.help = "Query MDNS for Service TXT",
|
|
.hint = NULL,
|
|
.func = &cmd_mdns_query_txt,
|
|
.argtable = &mdns_query_txt_args
|
|
};
|
|
|
|
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_init) );
|
|
}
|
|
|
|
static struct {
|
|
struct arg_str *service;
|
|
struct arg_str *proto;
|
|
struct arg_int *timeout;
|
|
struct arg_int *max_results;
|
|
struct arg_end *end;
|
|
} mdns_query_ptr_args;
|
|
|
|
static int cmd_mdns_query_ptr(int argc, char** argv)
|
|
{
|
|
int nerrors = arg_parse(argc, argv, (void**) &mdns_query_ptr_args);
|
|
if (nerrors != 0) {
|
|
arg_print_errors(stderr, mdns_query_ptr_args.end, argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
const char * service = mdns_query_ptr_args.service->sval[0];
|
|
const char * proto = mdns_query_ptr_args.proto->sval[0];
|
|
int timeout = mdns_query_ptr_args.timeout->ival[0];
|
|
int max_results = mdns_query_ptr_args.max_results->ival[0];
|
|
|
|
if (timeout <= 0) {
|
|
timeout = 5000;
|
|
}
|
|
|
|
if (max_results <= 0 || max_results > 255) {
|
|
max_results = 255;
|
|
}
|
|
|
|
printf("Query PTR: %s.%s.local, Timeout: %d, Max Results: %d\n", service, proto, timeout, max_results);
|
|
|
|
mdns_result_t * results = NULL;
|
|
esp_err_t err = mdns_query_ptr(service, proto, timeout, max_results, &results);
|
|
if (err) {
|
|
printf("ERROR: Query Failed\n");
|
|
return 1;
|
|
}
|
|
if (!results) {
|
|
printf("No results found!\n");
|
|
return 0;
|
|
}
|
|
|
|
mdns_print_results(results);
|
|
mdns_query_results_free(results);
|
|
return 0;
|
|
}
|
|
|
|
static void register_mdns_query_ptr()
|
|
{
|
|
mdns_query_ptr_args.service = arg_str1(NULL, NULL, "<service>", "Service to search for (ex. _http, _smb, etc.)");
|
|
mdns_query_ptr_args.proto = arg_str1(NULL, NULL, "<proto>", "Protocol to search for (_tcp, _udp, etc.)");
|
|
mdns_query_ptr_args.timeout = arg_int0("t", "timeout", "<timeout>", "Timeout for this query");
|
|
mdns_query_ptr_args.max_results = arg_int0("m", "max_results", "<max_results>", "Maximum results returned");
|
|
mdns_query_ptr_args.end = arg_end(2);
|
|
|
|
const esp_console_cmd_t cmd_init = {
|
|
.command = "mdns_query_ptr",
|
|
.help = "Query MDNS for Service",
|
|
.hint = NULL,
|
|
.func = &cmd_mdns_query_ptr,
|
|
.argtable = &mdns_query_ptr_args
|
|
};
|
|
|
|
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_init) );
|
|
}
|
|
|
|
static struct {
|
|
struct arg_str *hostname;
|
|
struct arg_int *timeout;
|
|
struct arg_int *max_results;
|
|
struct arg_end *end;
|
|
} mdns_query_ip_args;
|
|
|
|
static int cmd_mdns_query_ip(int argc, char** argv)
|
|
{
|
|
int nerrors = arg_parse(argc, argv, (void**) &mdns_query_ip_args);
|
|
if (nerrors != 0) {
|
|
arg_print_errors(stderr, mdns_query_ip_args.end, argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
const char * hostname = mdns_query_ip_args.hostname->sval[0];
|
|
int timeout = mdns_query_ip_args.timeout->ival[0];
|
|
int max_results = mdns_query_ip_args.max_results->ival[0];
|
|
|
|
if (!hostname || !hostname[0]) {
|
|
printf("ERROR: Hostname not supplied\n");
|
|
return 1;
|
|
}
|
|
|
|
if (timeout <= 0) {
|
|
timeout = 1000;
|
|
}
|
|
|
|
if (max_results < 0 || max_results > 255) {
|
|
max_results = 255;
|
|
}
|
|
|
|
printf("Query IP: %s.local, Timeout: %d, Max Results: %d\n", hostname, timeout, max_results);
|
|
|
|
mdns_result_t * results = NULL;
|
|
esp_err_t err = mdns_query(hostname, NULL, NULL, MDNS_TYPE_ANY, timeout, max_results, &results);
|
|
if (err) {
|
|
printf("ERROR: Query Failed\n");
|
|
return 1;
|
|
}
|
|
if (!results) {
|
|
printf("No results found!\n");
|
|
return 0;
|
|
}
|
|
mdns_print_results(results);
|
|
mdns_query_results_free(results);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void register_mdns_query_ip()
|
|
{
|
|
mdns_query_ip_args.hostname = arg_str1(NULL, NULL, "<hostname>", "Hostname that is searched for");
|
|
mdns_query_ip_args.timeout = arg_int0("t", "timeout", "<timeout>", "Timeout for this query");
|
|
mdns_query_ip_args.max_results = arg_int0("m", "max_results", "<max_results>", "Maximum results returned");
|
|
mdns_query_ip_args.end = arg_end(2);
|
|
|
|
const esp_console_cmd_t cmd_init = {
|
|
.command = "mdns_query_ip",
|
|
.help = "Query MDNS for IP",
|
|
.hint = NULL,
|
|
.func = &cmd_mdns_query_ip,
|
|
.argtable = &mdns_query_ip_args
|
|
};
|
|
|
|
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_init) );
|
|
}
|
|
|
|
static struct {
|
|
struct arg_str *instance;
|
|
struct arg_str *service;
|
|
struct arg_str *proto;
|
|
struct arg_int *timeout;
|
|
struct arg_int *max_results;
|
|
struct arg_end *end;
|
|
} mdns_query_svc_args;
|
|
|
|
static int cmd_mdns_query_svc(int argc, char** argv)
|
|
{
|
|
int nerrors = arg_parse(argc, argv, (void**) &mdns_query_svc_args);
|
|
if (nerrors != 0) {
|
|
arg_print_errors(stderr, mdns_query_svc_args.end, argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
const char * instance = mdns_query_svc_args.instance->sval[0];
|
|
const char * service = mdns_query_svc_args.service->sval[0];
|
|
const char * proto = mdns_query_svc_args.proto->sval[0];
|
|
int timeout = mdns_query_svc_args.timeout->ival[0];
|
|
int max_results = mdns_query_svc_args.max_results->ival[0];
|
|
|
|
if (timeout <= 0) {
|
|
timeout = 5000;
|
|
}
|
|
|
|
if (max_results < 0 || max_results > 255) {
|
|
max_results = 255;
|
|
}
|
|
|
|
printf("Query SVC: %s.%s.%s.local, Timeout: %d, Max Results: %d\n", instance, service, proto, timeout, max_results);
|
|
|
|
mdns_result_t * results = NULL;
|
|
esp_err_t err = mdns_query(instance, service, proto, MDNS_TYPE_ANY, timeout, max_results, &results);
|
|
if (err) {
|
|
printf("ERROR: Query Failed\n");
|
|
return 1;
|
|
}
|
|
if (!results) {
|
|
printf("No results found!\n");
|
|
return 0;
|
|
}
|
|
|
|
mdns_print_results(results);
|
|
mdns_query_results_free(results);
|
|
return 0;
|
|
}
|
|
|
|
static void register_mdns_query_svc()
|
|
{
|
|
mdns_query_svc_args.instance = arg_str1(NULL, NULL, "<instance>", "Instance to search for");
|
|
mdns_query_svc_args.service = arg_str1(NULL, NULL, "<service>", "Service to search for (ex. _http, _smb, etc.)");
|
|
mdns_query_svc_args.proto = arg_str1(NULL, NULL, "<proto>", "Protocol to search for (_tcp, _udp, etc.)");
|
|
mdns_query_svc_args.timeout = arg_int0("t", "timeout", "<timeout>", "Timeout for this query");
|
|
mdns_query_svc_args.max_results = arg_int0("m", "max_results", "<max_results>", "Maximum results returned");
|
|
mdns_query_svc_args.end = arg_end(2);
|
|
|
|
const esp_console_cmd_t cmd_init = {
|
|
.command = "mdns_query_svc",
|
|
.help = "Query MDNS for Service TXT & SRV",
|
|
.hint = NULL,
|
|
.func = &cmd_mdns_query_svc,
|
|
.argtable = &mdns_query_svc_args
|
|
};
|
|
|
|
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_init) );
|
|
}
|
|
|
|
static struct {
|
|
struct arg_str *hostname;
|
|
struct arg_str *instance;
|
|
struct arg_end *end;
|
|
} mdns_init_args;
|
|
|
|
static int cmd_mdns_init(int argc, char** argv)
|
|
{
|
|
int nerrors = arg_parse(argc, argv, (void**) &mdns_init_args);
|
|
if (nerrors != 0) {
|
|
arg_print_errors(stderr, mdns_init_args.end, argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
ESP_ERROR_CHECK( mdns_init() );
|
|
|
|
if (mdns_init_args.hostname->sval[0]) {
|
|
ESP_ERROR_CHECK( mdns_hostname_set(mdns_init_args.hostname->sval[0]) );
|
|
printf("MDNS: Hostname: %s\n", mdns_init_args.hostname->sval[0]);
|
|
}
|
|
|
|
if (mdns_init_args.instance->sval[0]) {
|
|
ESP_ERROR_CHECK( mdns_instance_name_set(mdns_init_args.instance->sval[0]) );
|
|
printf("MDNS: Instance: %s\n", mdns_init_args.instance->sval[0]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void register_mdns_init()
|
|
{
|
|
mdns_init_args.hostname = arg_str0("h", "hostname", "<hostname>", "Hostname that the server will advertise");
|
|
mdns_init_args.instance = arg_str0("i", "instance", "<instance>", "Default instance name for services");
|
|
mdns_init_args.end = arg_end(2);
|
|
|
|
const esp_console_cmd_t cmd_init = {
|
|
.command = "mdns_init",
|
|
.help = "Start MDNS Server",
|
|
.hint = NULL,
|
|
.func = &cmd_mdns_init,
|
|
.argtable = &mdns_init_args
|
|
};
|
|
|
|
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_init) );
|
|
}
|
|
|
|
static int cmd_mdns_free(int argc, char** argv)
|
|
{
|
|
mdns_free();
|
|
return 0;
|
|
}
|
|
|
|
static void register_mdns_free()
|
|
{
|
|
const esp_console_cmd_t cmd_free = {
|
|
.command = "mdns_free",
|
|
.help = "Stop MDNS Server",
|
|
.hint = NULL,
|
|
.func = &cmd_mdns_free,
|
|
.argtable = NULL
|
|
};
|
|
|
|
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_free) );
|
|
}
|
|
|
|
static struct {
|
|
struct arg_str *hostname;
|
|
struct arg_end *end;
|
|
} mdns_set_hostname_args;
|
|
|
|
static int cmd_mdns_set_hostname(int argc, char** argv)
|
|
{
|
|
int nerrors = arg_parse(argc, argv, (void**) &mdns_set_hostname_args);
|
|
if (nerrors != 0) {
|
|
arg_print_errors(stderr, mdns_set_hostname_args.end, argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
if (mdns_set_hostname_args.hostname->sval[0] == NULL) {
|
|
printf("ERROR: Bad arguments!\n");
|
|
return 1;
|
|
}
|
|
|
|
ESP_ERROR_CHECK( mdns_hostname_set(mdns_set_hostname_args.hostname->sval[0]) );
|
|
return 0;
|
|
}
|
|
|
|
static void register_mdns_set_hostname()
|
|
{
|
|
mdns_set_hostname_args.hostname = arg_str1(NULL, NULL, "<hostname>", "Hostname that the server will advertise");
|
|
mdns_set_hostname_args.end = arg_end(2);
|
|
|
|
const esp_console_cmd_t cmd_set_hostname = {
|
|
.command = "mdns_set_hostname",
|
|
.help = "Set MDNS Server hostname",
|
|
.hint = NULL,
|
|
.func = &cmd_mdns_set_hostname,
|
|
.argtable = &mdns_set_hostname_args
|
|
};
|
|
|
|
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_set_hostname) );
|
|
}
|
|
|
|
static struct {
|
|
struct arg_str *instance;
|
|
struct arg_end *end;
|
|
} mdns_set_instance_args;
|
|
|
|
static int cmd_mdns_set_instance(int argc, char** argv)
|
|
{
|
|
int nerrors = arg_parse(argc, argv, (void**) &mdns_set_instance_args);
|
|
if (nerrors != 0) {
|
|
arg_print_errors(stderr, mdns_set_instance_args.end, argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
if (mdns_set_instance_args.instance->sval[0] == NULL) {
|
|
printf("ERROR: Bad arguments!\n");
|
|
return 1;
|
|
}
|
|
|
|
ESP_ERROR_CHECK( mdns_instance_name_set(mdns_set_instance_args.instance->sval[0]) );
|
|
return 0;
|
|
}
|
|
|
|
static void register_mdns_set_instance()
|
|
{
|
|
mdns_set_instance_args.instance = arg_str1(NULL, NULL, "<instance>", "Default instance name for services");
|
|
mdns_set_instance_args.end = arg_end(2);
|
|
|
|
const esp_console_cmd_t cmd_set_instance = {
|
|
.command = "mdns_set_instance",
|
|
.help = "Set MDNS Server Istance Name",
|
|
.hint = NULL,
|
|
.func = &cmd_mdns_set_instance,
|
|
.argtable = &mdns_set_instance_args
|
|
};
|
|
|
|
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_set_instance) );
|
|
}
|
|
|
|
static mdns_txt_item_t * _convert_items(const char **values, int count)
|
|
{
|
|
int i=0,e;
|
|
const char * value = NULL;
|
|
mdns_txt_item_t * items = (mdns_txt_item_t*) malloc(sizeof(mdns_txt_item_t) * count);
|
|
if (!items) {
|
|
printf("ERROR: No Memory!\n");
|
|
goto fail;
|
|
|
|
}
|
|
memset(items, 0, sizeof(mdns_txt_item_t) * count);
|
|
|
|
for (i=0; i<count; i++) {
|
|
value = values[i];
|
|
char * esign = strchr(value, '=');
|
|
if (!esign) {
|
|
printf("ERROR: Equal sign not found in '%s'!\n", value);
|
|
goto fail;
|
|
}
|
|
int var_len = esign - value;
|
|
int val_len = strlen(value) - var_len - 1;
|
|
char * var = (char*)malloc(var_len+1);
|
|
if (var == NULL) {
|
|
printf("ERROR: No Memory!\n");
|
|
goto fail;
|
|
}
|
|
char * val = (char*)malloc(val_len+1);
|
|
if (val == NULL) {
|
|
printf("ERROR: No Memory!\n");
|
|
free(var);
|
|
goto fail;
|
|
}
|
|
memcpy(var, value, var_len);
|
|
var[var_len] = 0;
|
|
memcpy(val, esign+1, val_len);
|
|
val[val_len] = 0;
|
|
|
|
items[i].key = var;
|
|
items[i].value = val;
|
|
}
|
|
|
|
return items;
|
|
|
|
fail:
|
|
for (e=0;e<i;e++) {
|
|
free((char *)items[e].key);
|
|
free((char *)items[e].value);
|
|
}
|
|
free(items);
|
|
return NULL;
|
|
}
|
|
|
|
static struct {
|
|
struct arg_str *service;
|
|
struct arg_str *proto;
|
|
struct arg_int *port;
|
|
struct arg_str *instance;
|
|
struct arg_str *txt;
|
|
struct arg_end *end;
|
|
} mdns_add_args;
|
|
|
|
static int cmd_mdns_service_add(int argc, char** argv)
|
|
{
|
|
int nerrors = arg_parse(argc, argv, (void**) &mdns_add_args);
|
|
if (nerrors != 0) {
|
|
arg_print_errors(stderr, mdns_add_args.end, argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
if (!mdns_add_args.service->sval[0] || !mdns_add_args.proto->sval[0] || !mdns_add_args.port->ival[0]) {
|
|
printf("ERROR: Bad arguments!\n");
|
|
return 1;
|
|
}
|
|
const char * instance = NULL;
|
|
if (mdns_add_args.instance->sval[0] && mdns_add_args.instance->sval[0][0]) {
|
|
instance = mdns_add_args.instance->sval[0];
|
|
printf("MDNS: Service Instance: %s\n", instance);
|
|
}
|
|
mdns_txt_item_t * items = NULL;
|
|
if (mdns_add_args.txt->count) {
|
|
items = _convert_items(mdns_add_args.txt->sval, mdns_add_args.txt->count);
|
|
if (!items) {
|
|
printf("ERROR: No Memory!\n");
|
|
return 1;
|
|
|
|
}
|
|
}
|
|
|
|
ESP_ERROR_CHECK( mdns_service_add(instance, mdns_add_args.service->sval[0], mdns_add_args.proto->sval[0], mdns_add_args.port->ival[0], items, mdns_add_args.txt->count) );
|
|
free(items);
|
|
return 0;
|
|
}
|
|
|
|
static void register_mdns_service_add()
|
|
{
|
|
mdns_add_args.service = arg_str1(NULL, NULL, "<service>", "MDNS Service");
|
|
mdns_add_args.proto = arg_str1(NULL, NULL, "<proto>", "IP Protocol");
|
|
mdns_add_args.port = arg_int1(NULL, NULL, "<port>", "Service Port");
|
|
mdns_add_args.instance = arg_str0("i", "instance", "<instance>", "Instance name");
|
|
mdns_add_args.txt = arg_strn(NULL, NULL, "item", 0, 30, "TXT Items (name=value)");
|
|
mdns_add_args.end = arg_end(2);
|
|
|
|
const esp_console_cmd_t cmd_add = {
|
|
.command = "mdns_service_add",
|
|
.help = "Add service to MDNS",
|
|
.hint = NULL,
|
|
.func = &cmd_mdns_service_add,
|
|
.argtable = &mdns_add_args
|
|
};
|
|
|
|
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_add) );
|
|
}
|
|
|
|
static struct {
|
|
struct arg_str *service;
|
|
struct arg_str *proto;
|
|
struct arg_end *end;
|
|
} mdns_remove_args;
|
|
|
|
static int cmd_mdns_service_remove(int argc, char** argv)
|
|
{
|
|
int nerrors = arg_parse(argc, argv, (void**) &mdns_remove_args);
|
|
if (nerrors != 0) {
|
|
arg_print_errors(stderr, mdns_remove_args.end, argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
if (!mdns_remove_args.service->sval[0] || !mdns_remove_args.proto->sval[0]) {
|
|
printf("ERROR: Bad arguments!\n");
|
|
return 1;
|
|
}
|
|
|
|
ESP_ERROR_CHECK( mdns_service_remove(mdns_remove_args.service->sval[0], mdns_remove_args.proto->sval[0]) );
|
|
return 0;
|
|
}
|
|
|
|
static void register_mdns_service_remove()
|
|
{
|
|
mdns_remove_args.service = arg_str1(NULL, NULL, "<service>", "MDNS Service");
|
|
mdns_remove_args.proto = arg_str1(NULL, NULL, "<proto>", "IP Protocol");
|
|
mdns_remove_args.end = arg_end(2);
|
|
|
|
const esp_console_cmd_t cmd_remove = {
|
|
.command = "mdns_service_remove",
|
|
.help = "Remove service from MDNS",
|
|
.hint = NULL,
|
|
.func = &cmd_mdns_service_remove,
|
|
.argtable = &mdns_remove_args
|
|
};
|
|
|
|
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_remove) );
|
|
}
|
|
|
|
static struct {
|
|
struct arg_str *service;
|
|
struct arg_str *proto;
|
|
struct arg_str *instance;
|
|
struct arg_end *end;
|
|
} mdns_service_instance_set_args;
|
|
|
|
static int cmd_mdns_service_instance_set(int argc, char** argv)
|
|
{
|
|
int nerrors = arg_parse(argc, argv, (void**) &mdns_service_instance_set_args);
|
|
if (nerrors != 0) {
|
|
arg_print_errors(stderr, mdns_service_instance_set_args.end, argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
if (!mdns_service_instance_set_args.service->sval[0] || !mdns_service_instance_set_args.proto->sval[0] || !mdns_service_instance_set_args.instance->sval[0]) {
|
|
printf("ERROR: Bad arguments!\n");
|
|
return 1;
|
|
}
|
|
|
|
ESP_ERROR_CHECK( mdns_service_instance_name_set(mdns_service_instance_set_args.service->sval[0], mdns_service_instance_set_args.proto->sval[0], mdns_service_instance_set_args.instance->sval[0]) );
|
|
return 0;
|
|
}
|
|
|
|
static void register_mdns_service_instance_set()
|
|
{
|
|
mdns_service_instance_set_args.service = arg_str1(NULL, NULL, "<service>", "MDNS Service");
|
|
mdns_service_instance_set_args.proto = arg_str1(NULL, NULL, "<proto>", "IP Protocol");
|
|
mdns_service_instance_set_args.instance = arg_str1(NULL, NULL, "<instance>", "Instance name");
|
|
mdns_service_instance_set_args.end = arg_end(2);
|
|
|
|
const esp_console_cmd_t cmd_add = {
|
|
.command = "mdns_service_instance_set",
|
|
.help = "Set MDNS Service Instance Name",
|
|
.hint = NULL,
|
|
.func = &cmd_mdns_service_instance_set,
|
|
.argtable = &mdns_service_instance_set_args
|
|
};
|
|
|
|
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_add) );
|
|
}
|
|
|
|
static struct {
|
|
struct arg_str *service;
|
|
struct arg_str *proto;
|
|
struct arg_int *port;
|
|
struct arg_end *end;
|
|
} mdns_service_port_set_args;
|
|
|
|
static int cmd_mdns_service_port_set(int argc, char** argv) {
|
|
int nerrors = arg_parse(argc, argv, (void**) &mdns_service_port_set_args);
|
|
if (nerrors != 0) {
|
|
arg_print_errors(stderr, mdns_service_port_set_args.end, argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
if (!mdns_service_port_set_args.service->sval[0] || !mdns_service_port_set_args.proto->sval[0] || !mdns_service_port_set_args.port->ival[0]) {
|
|
printf("ERROR: Bad arguments!\n");
|
|
return 1;
|
|
}
|
|
|
|
ESP_ERROR_CHECK( mdns_service_port_set(mdns_service_port_set_args.service->sval[0], mdns_service_port_set_args.proto->sval[0], mdns_service_port_set_args.port->ival[0]) );
|
|
return 0;
|
|
}
|
|
|
|
static void register_mdns_service_port_set()
|
|
{
|
|
mdns_service_port_set_args.service = arg_str1(NULL, NULL, "<service>", "MDNS Service");
|
|
mdns_service_port_set_args.proto = arg_str1(NULL, NULL, "<proto>", "IP Protocol");
|
|
mdns_service_port_set_args.port = arg_int1(NULL, NULL, "<port>", "Service Port");
|
|
mdns_service_port_set_args.end = arg_end(2);
|
|
|
|
const esp_console_cmd_t cmd_add = {
|
|
.command = "mdns_service_port_set",
|
|
.help = "Set MDNS Service port",
|
|
.hint = NULL,
|
|
.func = &cmd_mdns_service_port_set,
|
|
.argtable = &mdns_service_port_set_args
|
|
};
|
|
|
|
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_add) );
|
|
}
|
|
|
|
static struct {
|
|
struct arg_str *service;
|
|
struct arg_str *proto;
|
|
struct arg_str *txt;
|
|
struct arg_end *end;
|
|
} mdns_txt_replace_args;
|
|
|
|
static int cmd_mdns_service_txt_replace(int argc, char** argv)
|
|
{
|
|
mdns_txt_item_t * items = NULL;
|
|
int nerrors = arg_parse(argc, argv, (void**) &mdns_txt_replace_args);
|
|
if (nerrors != 0) {
|
|
arg_print_errors(stderr, mdns_txt_replace_args.end, argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
if (!mdns_txt_replace_args.service->sval[0] || !mdns_txt_replace_args.proto->sval[0]) {
|
|
printf("ERROR: Bad arguments!\n");
|
|
return 1;
|
|
}
|
|
|
|
if (mdns_txt_replace_args.txt->count) {
|
|
items = _convert_items(mdns_txt_replace_args.txt->sval, mdns_txt_replace_args.txt->count);
|
|
if (!items) {
|
|
printf("ERROR: No Memory!\n");
|
|
return 1;
|
|
|
|
}
|
|
}
|
|
ESP_ERROR_CHECK( mdns_service_txt_set(mdns_txt_replace_args.service->sval[0], mdns_txt_replace_args.proto->sval[0], items, mdns_txt_replace_args.txt->count) );
|
|
free(items);
|
|
return 0;
|
|
}
|
|
|
|
static void register_mdns_service_txt_replace()
|
|
{
|
|
mdns_txt_replace_args.service = arg_str1(NULL, NULL, "<service>", "MDNS Service");
|
|
mdns_txt_replace_args.proto = arg_str1(NULL, NULL, "<proto>", "IP Protocol");
|
|
mdns_txt_replace_args.txt = arg_strn(NULL, NULL, "item", 0, 30, "TXT Items (name=value)");
|
|
mdns_txt_replace_args.end = arg_end(2);
|
|
|
|
const esp_console_cmd_t cmd_txt_set = {
|
|
.command = "mdns_service_txt_replace",
|
|
.help = "Replace MDNS service TXT items",
|
|
.hint = NULL,
|
|
.func = &cmd_mdns_service_txt_replace,
|
|
.argtable = &mdns_txt_replace_args
|
|
};
|
|
|
|
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_txt_set) );
|
|
}
|
|
|
|
static struct {
|
|
struct arg_str *service;
|
|
struct arg_str *proto;
|
|
struct arg_str *var;
|
|
struct arg_str *value;
|
|
struct arg_end *end;
|
|
} mdns_txt_set_args;
|
|
|
|
static int cmd_mdns_service_txt_set(int argc, char** argv)
|
|
{
|
|
int nerrors = arg_parse(argc, argv, (void**) &mdns_txt_set_args);
|
|
if (nerrors != 0) {
|
|
arg_print_errors(stderr, mdns_txt_set_args.end, argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
if (!mdns_txt_set_args.service->sval[0] || !mdns_txt_set_args.proto->sval[0] || !mdns_txt_set_args.var->sval[0]) {
|
|
printf("ERROR: Bad arguments!\n");
|
|
return 1;
|
|
}
|
|
|
|
ESP_ERROR_CHECK( mdns_service_txt_item_set(mdns_txt_set_args.service->sval[0], mdns_txt_set_args.proto->sval[0], mdns_txt_set_args.var->sval[0], mdns_txt_set_args.value->sval[0]) );
|
|
return 0;
|
|
}
|
|
|
|
static void register_mdns_service_txt_set()
|
|
{
|
|
mdns_txt_set_args.service = arg_str1(NULL, NULL, "<service>", "MDNS Service");
|
|
mdns_txt_set_args.proto = arg_str1(NULL, NULL, "<proto>", "IP Protocol");
|
|
mdns_txt_set_args.var = arg_str1(NULL, NULL, "<var>", "Item Name");
|
|
mdns_txt_set_args.value = arg_str1(NULL, NULL, "<value>", "Item Value");
|
|
mdns_txt_set_args.end = arg_end(2);
|
|
|
|
const esp_console_cmd_t cmd_txt_set = {
|
|
.command = "mdns_service_txt_set",
|
|
.help = "Add/Set MDNS service TXT item",
|
|
.hint = NULL,
|
|
.func = &cmd_mdns_service_txt_set,
|
|
.argtable = &mdns_txt_set_args
|
|
};
|
|
|
|
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_txt_set) );
|
|
}
|
|
|
|
static struct {
|
|
struct arg_str *service;
|
|
struct arg_str *proto;
|
|
struct arg_str *var;
|
|
struct arg_end *end;
|
|
} mdns_txt_remove_args;
|
|
|
|
static int cmd_mdns_service_txt_remove(int argc, char** argv)
|
|
{
|
|
int nerrors = arg_parse(argc, argv, (void**) &mdns_txt_remove_args);
|
|
if (nerrors != 0) {
|
|
arg_print_errors(stderr, mdns_txt_remove_args.end, argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
if (!mdns_txt_remove_args.service->sval[0] || !mdns_txt_remove_args.proto->sval[0] || !mdns_txt_remove_args.var->sval[0]) {
|
|
printf("ERROR: Bad arguments!\n");
|
|
return 1;
|
|
}
|
|
|
|
ESP_ERROR_CHECK( mdns_service_txt_item_remove(mdns_txt_remove_args.service->sval[0], mdns_txt_remove_args.proto->sval[0], mdns_txt_remove_args.var->sval[0]) );
|
|
return 0;
|
|
}
|
|
|
|
static void register_mdns_service_txt_remove()
|
|
{
|
|
mdns_txt_remove_args.service = arg_str1(NULL, NULL, "<service>", "MDNS Service");
|
|
mdns_txt_remove_args.proto = arg_str1(NULL, NULL, "<proto>", "IP Protocol");
|
|
mdns_txt_remove_args.var = arg_str1(NULL, NULL, "<var>", "Item Name");
|
|
mdns_txt_remove_args.end = arg_end(2);
|
|
|
|
const esp_console_cmd_t cmd_txt_remove = {
|
|
.command = "mdns_service_txt_remove",
|
|
.help = "Remove MDNS service TXT item",
|
|
.hint = NULL,
|
|
.func = &cmd_mdns_service_txt_remove,
|
|
.argtable = &mdns_txt_remove_args
|
|
};
|
|
|
|
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_txt_remove) );
|
|
}
|
|
|
|
static int cmd_mdns_service_remove_all(int argc, char** argv)
|
|
{
|
|
mdns_service_remove_all();
|
|
return 0;
|
|
}
|
|
|
|
static void register_mdns_service_remove_all()
|
|
{
|
|
const esp_console_cmd_t cmd_free = {
|
|
.command = "mdns_service_remove_all",
|
|
.help = "Remove all MDNS services",
|
|
.hint = NULL,
|
|
.func = &cmd_mdns_service_remove_all,
|
|
.argtable = NULL
|
|
};
|
|
|
|
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_free) );
|
|
}
|
|
|
|
void mdns_console_register()
|
|
{
|
|
register_mdns_init();
|
|
register_mdns_free();
|
|
register_mdns_set_hostname();
|
|
register_mdns_set_instance();
|
|
register_mdns_service_add();
|
|
register_mdns_service_remove();
|
|
register_mdns_service_instance_set();
|
|
register_mdns_service_port_set();
|
|
register_mdns_service_txt_replace();
|
|
register_mdns_service_txt_set();
|
|
register_mdns_service_txt_remove();
|
|
register_mdns_service_remove_all();
|
|
|
|
register_mdns_query_a();
|
|
register_mdns_query_aaaa();
|
|
register_mdns_query_txt();
|
|
register_mdns_query_srv();
|
|
register_mdns_query_ptr();
|
|
|
|
register_mdns_query_ip();
|
|
register_mdns_query_svc();
|
|
}
|
|
|