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