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