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