1 // Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 #ifndef MDNS_PRIVATE_H_ 15 #define MDNS_PRIVATE_H_ 16 17 #include "sdkconfig.h" 18 #include "mdns.h" 19 #include "esp_task.h" 20 #include "esp_timer.h" 21 22 //#define MDNS_ENABLE_DEBUG 23 24 #ifdef MDNS_ENABLE_DEBUG 25 #define _mdns_dbg_printf(...) printf(__VA_ARGS__) 26 #endif 27 28 /** mDNS strict mode: Set this to 1 for the mDNS library to strictly follow the RFC6762: 29 * Strict features: 30 * - to do not set original questions in response packets per RFC6762, sec 6 31 * 32 * The actual configuration is 0, i.e. non-strict mode, since some implementations, 33 * such as lwIP mdns resolver (used by standard POSIX API like getaddrinfo, gethostbyname) 34 * could not correctly resolve advertised names. 35 */ 36 #ifndef CONFIG_MDNS_STRICT_MODE 37 #define MDNS_STRICT_MODE 0 38 #else 39 #define MDNS_STRICT_MODE 1 40 #endif 41 42 #if !MDNS_STRICT_MODE 43 /* mDNS responders sometimes repeat queries in responses 44 * but according to RFC6762, sec 6: Responses MUST NOT contain 45 * any item in question field */ 46 #define MDNS_REPEAT_QUERY_IN_RESPONSE 1 47 #endif 48 /** The maximum number of services */ 49 #define MDNS_MAX_SERVICES CONFIG_MDNS_MAX_SERVICES 50 51 #define MDNS_ANSWER_PTR_TTL 4500 52 #define MDNS_ANSWER_TXT_TTL 4500 53 #define MDNS_ANSWER_SRV_TTL 120 54 #define MDNS_ANSWER_A_TTL 120 55 #define MDNS_ANSWER_AAAA_TTL 120 56 57 #define MDNS_FLAGS_AUTHORITATIVE 0x8400 58 #define MDNS_FLAGS_DISTRIBUTED 0x0200 59 60 #define MDNS_NAME_REF 0xC000 61 62 //custom type! only used by this implementation 63 //to help manage service discovery handling 64 #define MDNS_TYPE_SDPTR 0x0032 65 66 #define MDNS_CLASS_IN 0x0001 67 #define MDNS_CLASS_ANY 0x00FF 68 #define MDNS_CLASS_IN_FLUSH_CACHE 0x8001 69 70 #define MDNS_ANSWER_ALL 0x3F 71 #define MDNS_ANSWER_PTR 0x08 72 #define MDNS_ANSWER_TXT 0x04 73 #define MDNS_ANSWER_SRV 0x02 74 #define MDNS_ANSWER_A 0x01 75 #define MDNS_ANSWER_AAAA 0x10 76 #define MDNS_ANSWER_NSEC 0x20 77 #define MDNS_ANSWER_SDPTR 0x80 78 #define MDNS_ANSWER_AAAA_SIZE 16 79 80 #define MDNS_SERVICE_PORT 5353 // UDP port that the server runs on 81 #define MDNS_SERVICE_STACK_DEPTH CONFIG_MDNS_TASK_STACK_SIZE 82 #define MDNS_TASK_PRIORITY CONFIG_MDNS_TASK_PRIORITY 83 #if (MDNS_TASK_PRIORITY > ESP_TASK_PRIO_MAX) 84 #error "mDNS task priority is higher than ESP_TASK_PRIO_MAX" 85 #elif (MDNS_TASK_PRIORITY > ESP_TASKD_EVENT_PRIO) 86 #warning "mDNS task priority is higher than ESP_TASKD_EVENT_PRIO, mDNS library might not work correctly" 87 #endif 88 #define MDNS_TASK_AFFINITY CONFIG_MDNS_TASK_AFFINITY 89 #define MDNS_SERVICE_ADD_TIMEOUT_MS CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS 90 91 #define MDNS_PACKET_QUEUE_LEN 16 // Maximum packets that can be queued for parsing 92 #define MDNS_ACTION_QUEUE_LEN 16 // Maximum actions pending to the server 93 #define MDNS_TXT_MAX_LEN 1024 // Maximum string length of text data in TXT record 94 #define MDNS_NAME_MAX_LEN 64 // Maximum string length of hostname, instance, service and proto 95 #define MDNS_NAME_BUF_LEN (MDNS_NAME_MAX_LEN+1) // Maximum char buffer size to hold hostname, instance, service or proto 96 #define MDNS_MAX_PACKET_SIZE 1460 // Maximum size of mDNS outgoing packet 97 98 #define MDNS_HEAD_LEN 12 99 #define MDNS_HEAD_ID_OFFSET 0 100 #define MDNS_HEAD_FLAGS_OFFSET 2 101 #define MDNS_HEAD_QUESTIONS_OFFSET 4 102 #define MDNS_HEAD_ANSWERS_OFFSET 6 103 #define MDNS_HEAD_SERVERS_OFFSET 8 104 #define MDNS_HEAD_ADDITIONAL_OFFSET 10 105 106 #define MDNS_TYPE_OFFSET 0 107 #define MDNS_CLASS_OFFSET 2 108 #define MDNS_TTL_OFFSET 4 109 #define MDNS_LEN_OFFSET 8 110 #define MDNS_DATA_OFFSET 10 111 112 #define MDNS_SRV_PRIORITY_OFFSET 0 113 #define MDNS_SRV_WEIGHT_OFFSET 2 114 #define MDNS_SRV_PORT_OFFSET 4 115 #define MDNS_SRV_FQDN_OFFSET 6 116 117 #define MDNS_TIMER_PERIOD_US (CONFIG_MDNS_TIMER_PERIOD_MS*1000) 118 119 #define MDNS_SERVICE_LOCK() xSemaphoreTake(_mdns_service_semaphore, portMAX_DELAY) 120 #define MDNS_SERVICE_UNLOCK() xSemaphoreGive(_mdns_service_semaphore) 121 122 #define queueToEnd(type, queue, item) \ 123 if (!queue) { \ 124 queue = item; \ 125 } else { \ 126 type * _q = queue; \ 127 while (_q->next) { _q = _q->next; } \ 128 _q->next = item; \ 129 } 130 131 #define queueDetach(type, queue, item) \ 132 if (queue) { \ 133 if (queue == item) { \ 134 queue = queue->next; \ 135 } else { \ 136 type * _q = queue; \ 137 while (_q->next && _q->next != item) { \ 138 _q = _q->next; \ 139 } \ 140 if (_q->next == item) { \ 141 _q->next = item->next; \ 142 item->next = NULL; \ 143 } \ 144 } \ 145 } 146 147 #define queueFree(type, queue) while (queue) { type * _q = queue; queue = queue->next; free(_q); } 148 149 #define PCB_STATE_IS_PROBING(s) (s->state > PCB_OFF && s->state < PCB_ANNOUNCE_1) 150 #define PCB_STATE_IS_ANNOUNCING(s) (s->state > PCB_PROBE_3 && s->state < PCB_RUNNING) 151 #define PCB_STATE_IS_RUNNING(s) (s->state == PCB_RUNNING) 152 153 #ifndef HOOK_MALLOC_FAILED 154 #define HOOK_MALLOC_FAILED ESP_LOGE(TAG, "Cannot allocate memory (line: %d, free heap: %d bytes)", __LINE__, esp_get_free_heap_size()); 155 #endif 156 157 typedef enum { 158 PCB_OFF, PCB_DUP, PCB_INIT, 159 PCB_PROBE_1, PCB_PROBE_2, PCB_PROBE_3, 160 PCB_ANNOUNCE_1, PCB_ANNOUNCE_2, PCB_ANNOUNCE_3, 161 PCB_RUNNING 162 } mdns_pcb_state_t; 163 164 typedef enum { 165 MDNS_ANSWER, MDNS_NS, MDNS_EXTRA 166 } mdns_parsed_record_type_t; 167 168 typedef enum { 169 ACTION_SYSTEM_EVENT, 170 ACTION_HOSTNAME_SET, 171 ACTION_INSTANCE_SET, 172 ACTION_SERVICE_ADD, 173 ACTION_SERVICE_DEL, 174 ACTION_SERVICE_INSTANCE_SET, 175 ACTION_SERVICE_PORT_SET, 176 ACTION_SERVICE_TXT_REPLACE, 177 ACTION_SERVICE_TXT_SET, 178 ACTION_SERVICE_TXT_DEL, 179 ACTION_SERVICES_CLEAR, 180 ACTION_SEARCH_ADD, 181 ACTION_SEARCH_SEND, 182 ACTION_SEARCH_END, 183 ACTION_TX_HANDLE, 184 ACTION_RX_HANDLE, 185 ACTION_TASK_STOP, 186 ACTION_DELEGATE_HOSTNAME_ADD, 187 ACTION_DELEGATE_HOSTNAME_REMOVE, 188 ACTION_MAX 189 } mdns_action_type_t; 190 191 192 typedef struct { 193 uint16_t id; 194 union { 195 struct { 196 uint16_t qr :1; 197 uint16_t opCode :4; 198 uint16_t aa :1; 199 uint16_t tc :1; 200 uint16_t rd :1; 201 uint16_t ra :1; 202 uint16_t z :1; 203 uint16_t ad :1; 204 uint16_t cd :1; 205 uint16_t rCode :4;//response/error code 206 }; 207 uint16_t value; 208 } flags; 209 uint16_t questions; //QDCOUNT 210 uint16_t answers; //ANCOUNT 211 uint16_t servers; //NSCOUNT 212 uint16_t additional;//ARCOUNT 213 } mdns_header_t; 214 215 typedef struct { 216 char host[MDNS_NAME_BUF_LEN]; // hostname for A/AAAA records, instance name for SRV records 217 char service[MDNS_NAME_BUF_LEN]; 218 char proto[MDNS_NAME_BUF_LEN]; 219 char domain[MDNS_NAME_BUF_LEN]; 220 uint8_t parts; 221 uint8_t sub; 222 bool invalid; 223 } mdns_name_t; 224 225 typedef struct mdns_parsed_question_s { 226 struct mdns_parsed_question_s * next; 227 uint16_t type; 228 bool unicast; 229 char * host; 230 char * service; 231 char * proto; 232 char * domain; 233 } mdns_parsed_question_t; 234 235 typedef struct mdns_parsed_record_s { 236 struct mdns_parsed_record_s * next; 237 mdns_parsed_record_type_t record_type; 238 uint16_t type; 239 uint16_t clas; 240 uint8_t flush; 241 uint32_t ttl; 242 char * host; 243 char * service; 244 char * proto; 245 char * domain; 246 uint16_t data_len; 247 uint8_t *data; 248 } mdns_parsed_record_t; 249 250 typedef struct { 251 mdns_if_t tcpip_if; 252 mdns_ip_protocol_t ip_protocol; 253 esp_ip_addr_t src; 254 uint16_t src_port; 255 uint8_t multicast; 256 uint8_t authoritative; 257 uint8_t probe; 258 uint8_t discovery; 259 uint8_t distributed; 260 mdns_parsed_question_t * questions; 261 mdns_parsed_record_t * records; 262 uint16_t id; 263 } mdns_parsed_packet_t; 264 265 typedef struct { 266 mdns_if_t tcpip_if; 267 mdns_ip_protocol_t ip_protocol; 268 struct pbuf *pb; 269 esp_ip_addr_t src; 270 esp_ip_addr_t dest; 271 uint16_t src_port; 272 uint8_t multicast; 273 } mdns_rx_packet_t; 274 275 typedef struct mdns_txt_linked_item_s { 276 const char * key; /*!< item key name */ 277 char * value; /*!< item value string */ 278 uint8_t value_len; /*!< item value length */ 279 struct mdns_txt_linked_item_s * next; /*!< next result, or NULL for the last result in the list */ 280 } mdns_txt_linked_item_t; 281 282 typedef struct { 283 const char * instance; 284 const char * service; 285 const char * proto; 286 const char * hostname; 287 uint16_t priority; 288 uint16_t weight; 289 uint16_t port; 290 mdns_txt_linked_item_t * txt; 291 } mdns_service_t; 292 293 typedef struct mdns_srv_item_s { 294 struct mdns_srv_item_s * next; 295 mdns_service_t * service; 296 } mdns_srv_item_t; 297 298 typedef struct mdns_out_question_s { 299 struct mdns_out_question_s * next; 300 uint16_t type; 301 bool unicast; 302 const char * host; 303 const char * service; 304 const char * proto; 305 const char * domain; 306 bool own_dynamic_memory; 307 } mdns_out_question_t; 308 309 typedef struct mdns_host_item_t { 310 const char * hostname; 311 mdns_ip_addr_t *address_list; 312 struct mdns_host_item_t *next; 313 } mdns_host_item_t; 314 315 typedef struct mdns_out_answer_s { 316 struct mdns_out_answer_s * next; 317 uint16_t type; 318 uint8_t bye; 319 uint8_t flush; 320 mdns_service_t * service; 321 mdns_host_item_t* host; 322 const char * custom_instance; 323 const char * custom_service; 324 const char * custom_proto; 325 } mdns_out_answer_t; 326 327 typedef struct mdns_tx_packet_s { 328 struct mdns_tx_packet_s * next; 329 uint32_t send_at; 330 mdns_if_t tcpip_if; 331 mdns_ip_protocol_t ip_protocol; 332 esp_ip_addr_t dst; 333 uint16_t port; 334 uint16_t flags; 335 uint8_t distributed; 336 mdns_out_question_t * questions; 337 mdns_out_answer_t * answers; 338 mdns_out_answer_t * servers; 339 mdns_out_answer_t * additional; 340 bool queued; 341 uint16_t id; 342 } mdns_tx_packet_t; 343 344 typedef struct { 345 mdns_pcb_state_t state; 346 struct udp_pcb * pcb; 347 mdns_srv_item_t ** probe_services; 348 uint8_t probe_services_len; 349 uint8_t probe_ip; 350 uint8_t probe_running; 351 uint16_t failed_probes; 352 } mdns_pcb_t; 353 354 typedef enum { 355 SEARCH_OFF, 356 SEARCH_INIT, 357 SEARCH_RUNNING, 358 SEARCH_MAX 359 } mdns_search_once_state_t; 360 361 typedef struct mdns_search_once_s { 362 struct mdns_search_once_s * next; 363 364 mdns_search_once_state_t state; 365 uint32_t started_at; 366 uint32_t sent_at; 367 uint32_t timeout; 368 mdns_query_notify_t notifier; 369 SemaphoreHandle_t done_semaphore; 370 uint16_t type; 371 uint8_t max_results; 372 uint8_t num_results; 373 char * instance; 374 char * service; 375 char * proto; 376 mdns_result_t * result; 377 } mdns_search_once_t; 378 379 typedef struct mdns_server_s { 380 struct { 381 mdns_pcb_t pcbs[MDNS_IP_PROTOCOL_MAX]; 382 } interfaces[MDNS_IF_MAX]; 383 const char * hostname; 384 const char * instance; 385 mdns_srv_item_t * services; 386 SemaphoreHandle_t lock; 387 QueueHandle_t action_queue; 388 mdns_tx_packet_t * tx_queue_head; 389 mdns_search_once_t * search_once; 390 esp_timer_handle_t timer_handle; 391 } mdns_server_t; 392 393 typedef struct { 394 mdns_action_type_t type; 395 union { 396 struct { 397 char * hostname; 398 xTaskHandle calling_task; 399 } hostname_set; 400 char * instance; 401 struct { 402 esp_event_base_t event_base; 403 int32_t event_id; 404 esp_netif_t* interface; 405 } sys_event; 406 struct { 407 mdns_srv_item_t * service; 408 } srv_add; 409 struct { 410 mdns_srv_item_t * service; 411 } srv_del; 412 struct { 413 mdns_srv_item_t * service; 414 char * instance; 415 } srv_instance; 416 struct { 417 mdns_srv_item_t * service; 418 uint16_t port; 419 } srv_port; 420 struct { 421 mdns_srv_item_t * service; 422 mdns_txt_linked_item_t * txt; 423 } srv_txt_replace; 424 struct { 425 mdns_srv_item_t * service; 426 char * key; 427 char * value; 428 uint8_t value_len; 429 } srv_txt_set; 430 struct { 431 mdns_srv_item_t * service; 432 char * key; 433 } srv_txt_del; 434 struct { 435 mdns_search_once_t * search; 436 } search_add; 437 struct { 438 mdns_tx_packet_t * packet; 439 } tx_handle; 440 struct { 441 mdns_rx_packet_t * packet; 442 } rx_handle; 443 struct { 444 const char * hostname; 445 mdns_ip_addr_t *address_list; 446 } delegate_hostname; 447 } data; 448 } mdns_action_t; 449 450 /* 451 * @brief Convert mnds if to esp-netif handle 452 * 453 * @param tcpip_if mdns supported interface as internal enum 454 * 455 * @return 456 * - ptr to esp-netif on success 457 * - NULL if no available netif for current interface index 458 */ 459 esp_netif_t *_mdns_get_esp_netif(mdns_if_t tcpip_if); 460 461 462 #endif /* MDNS_PRIVATE_H_ */ 463