MeterLogger
mdns.c
Go to the documentation of this file.
1 /**
2  * lwip MDNS resolver file.
3  *
4  * Created on: Jul 29, 2010
5  * Author: Daniel Toma
6  *
7 
8  * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  * 3. The name of the author may not be used to endorse or promote
19  * products derived from this software without specific prior
20  * written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
23  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
26  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
28  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 /**
36 
37  * This file implements a MDNS host name and PUCK service registration.
38 
39  *-----------------------------------------------------------------------------
40  * Includes
41  *----------------------------------------------------------------------------*/
42 #include "lwip/opt.h"
43 #if LWIP_MDNS /* don't build if not configured for use in lwipopts.h */
44 #include "lwip/mdns.h"
45 #include "lwip/puck_def.h"
46 #include "lwip/udp.h"
47 #include "lwip/mem.h"
48 #include "lwip/igmp.h"
49 #include "osapi.h"
50 #include "os_type.h"
51 #include "user_interface.h"
52 
53 #ifdef MEMLEAK_DEBUG
54 static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
55 #endif
56 
57 /** DNS server IP address */
58 #ifndef DNS_MULTICAST_ADDRESS
59 #define DNS_MULTICAST_ADDRESS ipaddr_addr("224.0.0.251") /* resolver1.opendns.com */
60 #endif
61 
62 /** DNS server IP address */
63 #ifndef MDNS_LOCAL
64 #define MDNS_LOCAL "local" /* resolver1.opendns.com */
65 #endif
66 
67 /** DNS server port address */
68 #ifndef DNS_MDNS_PORT
69 #define DNS_MDNS_PORT 5353
70 #endif
71 
72 /** DNS maximum number of retries when asking for a name, before "timeout". */
73 #ifndef DNS_MAX_RETRIES
74 #define DNS_MAX_RETRIES 4
75 #endif
76 
77 /** DNS resource record max. TTL (one week as default) */
78 #ifndef DNS_MAX_TTL
79 #define DNS_MAX_TTL 604800
80 #endif
81 
82 /* DNS protocol flags */
83 #define DNS_FLAG1_RESPONSE 0x84
84 #define DNS_FLAG1_OPCODE_STATUS 0x10
85 #define DNS_FLAG1_OPCODE_INVERSE 0x08
86 #define DNS_FLAG1_OPCODE_STANDARD 0x00
87 #define DNS_FLAG1_AUTHORATIVE 0x04
88 #define DNS_FLAG1_TRUNC 0x02
89 #define DNS_FLAG1_RD 0x01
90 #define DNS_FLAG2_RA 0x80
91 #define DNS_FLAG2_ERR_MASK 0x0f
92 #define DNS_FLAG2_ERR_NONE 0x00
93 #define DNS_FLAG2_ERR_NAME 0x03
94 
95 /* DNS protocol states */
96 #define DNS_STATE_UNUSED 0
97 #define DNS_STATE_NEW 1
98 #define DNS_STATE_ASKING 2
99 #define DNS_STATE_DONE 3
100 
101 /* MDNS registration type */
102 #define MDNS_HOSTNAME_REG 0
103 #define MDNS_SERVICE_REG 1
104 
105 /* MDNS registration type */
106 #define MDNS_REG_ANSWER 1
107 #define MDNS_SD_ANSWER 2
108 #define MDNS_SERVICE_REG_ANSWER 3
109 
110 /* MDNS registration time */
111 #define MDNS_HOST_TIME 120
112 #define MDNS_SERVICE_TIME 3600
113 
114 /** MDNS name length with "." at the beginning and end of name*/
115 #ifndef MDNS_LENGTH_ADD
116 #define MDNS_LENGTH_ADD 2
117 #endif
118 
119 #ifdef MDNS_MAX_NAME_LENGTH
120 #undef MDNS_MAX_NAME_LENGTH
121 #endif
122 #define MDNS_MAX_NAME_LENGTH (256)
123 
125 /** DNS message header */
126 struct mdns_hdr {
128  PACK_STRUCT_FIELD(u8_t flags1);
129  PACK_STRUCT_FIELD(u8_t flags2);
130  PACK_STRUCT_FIELD(u16_t numquestions);
131  PACK_STRUCT_FIELD(u16_t numanswers);
132  PACK_STRUCT_FIELD(u16_t numauthrr);
133  PACK_STRUCT_FIELD(u16_t numextrarr);
136 
137 #define SIZEOF_DNS_HDR 12
138 
140 /** MDNS query message structure */
141 struct mdns_query {
142  /* MDNS query record starts with either a domain name or a pointer
143  to a name already present somewhere in the packet. */PACK_STRUCT_FIELD(u16_t type);
144  PACK_STRUCT_FIELD(u16_t class);
147 
148 #define SIZEOF_DNS_QUERY 4
149 
151 /** MDNS answer message structure */
152 struct mdns_answer {
153  /* MDNS answer record starts with either a domain name or a pointer
154  to a name already present somewhere in the packet. */PACK_STRUCT_FIELD(u16_t type);
155  PACK_STRUCT_FIELD(u16_t class);
160 #define SIZEOF_DNS_ANSWER 10
161 
163 /** MDNS answer message structure */
164 struct mdns_auth {
168 
169 #define SIZEOF_MDNS_AUTH 4
171 /** MDNS service registration message structure */
172 struct mdns_service {
173  PACK_STRUCT_FIELD(u16_t prior);
174  PACK_STRUCT_FIELD(u16_t weight);
175  PACK_STRUCT_FIELD(u16_t port);
178 
179 #define SIZEOF_MDNS_SERVICE 6
180 
181 uint16 PUCK_PORT ;
182 os_timer_t mdns_timer;
183 /* forward declarations */
184 static void mdns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p,
185  struct ip_addr *addr, u16_t port);
186 
187 /*-----------------------------------------------------------------------------
188  * Globales
189  *----------------------------------------------------------------------------*/
190 
191 /* MDNS variables */
192 static char host_name[MDNS_NAME_LENGTH];
193 static char service_name[MDNS_NAME_LENGTH];
194 static char server_name[MDNS_NAME_LENGTH];
195 //static char puck_datasheet[PUCK_DATASHEET_SIZE];
196 static struct udp_pcb *mdns_pcb = NULL;
197 static struct mdns_info * ms_info = NULL;
198 static struct ip_addr multicast_addr;
199 static struct ip_addr host_addr;
200 static uint8 register_flag = 0;
201 static uint8 mdns_flag = 0;
202 //#if (DNS_USES_STATIC_BUF == 1)
203 static u8_t mdns_payload[DNS_MSG_SIZE];
204 //#endif /* (MDNS_USES_STATIC_BUF == 1) */
205 /*
206  * Function to set the UDP pcb used to send the mDNS packages
207  */
209 getPcb(struct udp_pcb *pcb) {
210  mdns_pcb = pcb;
211 }
212 
213 #if DNS_DOES_NAME_CHECK
214 /**
215  * Compare the "dotted" name "query" with the encoded name "response"
216  * to make sure an answer from the DNS server matches the current mdns_table
217  * entry (otherwise, answers might arrive late for hostname not on the list
218  * any more).
219  *
220  * @param query hostname (not encoded) from the mdns_table
221  * @param response encoded hostname in the DNS response
222  * @return 0: names equal; 1: names differ
223  */
224 static u8_t ICACHE_FLASH_ATTR
225 mdns_compare_name(unsigned char *query, unsigned char *response) {
226  unsigned char n;
227 
228  do {
229  n = *response++;
230  /** @see RFC 1035 - 4.1.4. Message compression */
231  if ((n & 0xc0) == 0xc0) {
232  /* Compressed name */
233  break;
234  } else {
235  /* Not compressed name */
236  while (n > 0) {
237  if ((*query) != (*response)) {
238  return 1;
239  }
240  ++response;
241  ++query;
242  --n;
243  };
244  ++query;
245  }
246  } while (*response != 0);
247 
248  return 0;
249 }
250 #endif /* DNS_DOES_NAME_CHECK */
251 /**
252  * Send a mDNS answer packet.
253  *
254  * @param type of answer hostname and service registration or service
255  * @param name to query
256  * @param id transaction ID in the DNS query packet
257  * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise
258  */
260 mdns_answer(u16_t type, const char* name, u8_t id) {
261  err_t err;
262  struct mdns_hdr *hdr;
263  struct mdns_answer ans;
264  struct mdns_auth auth;
265  struct mdns_service serv;
266  struct pbuf *p ,*p_sta;
267  char *query, *nptr;
268  const char *pHostname;
269  struct netif * sta_netif = NULL;
270  struct netif * ap_netif = NULL;
271  static char tmpBuf[PUCK_DATASHEET_SIZE + PUCK_SERVICE_LENGTH];
272  u8_t n;
273  u16_t length = 0;
274  /* if here, we have either a new query or a retry on a previous query to process */
276  SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM);
277  if (p != NULL) {
278  LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
279  /* fill dns header */
280  hdr = (struct mdns_hdr*) p->payload;
281  os_memset(hdr, 0, SIZEOF_DNS_HDR);
282  hdr->id = htons(id);
283  hdr->flags1 = DNS_FLAG1_RESPONSE;
284 
285  if (type == MDNS_SD_ANSWER) {
286  pHostname = DNS_SD_SERVICE;
287  hdr->numanswers = htons(1);
288  } else if (type == MDNS_SERVICE_REG_ANSWER) {
289  pHostname = PUCK_SERVICE;
290  hdr->numanswers = htons(type);
291  } else {
292  pHostname = name;
293  hdr->numanswers = htons(type);
294  }
295  query = (char*) hdr + SIZEOF_DNS_HDR;
296  --pHostname;
297  /* convert hostname into suitable query format. */
298  do {
299  ++pHostname;
300  nptr = query;
301  ++query;
302  for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
303  *query = *pHostname;
304  ++query;
305  ++n;
306  }
307  *nptr = n;
308  } while (*pHostname != 0);
309  *query++ = '\0';
310  /* fill dns query */
311 
312  if (type == MDNS_REG_ANSWER) {
313 
314  ans.type = htons(DNS_RRTYPE_A);
315  ans.class = htons(DNS_RRCLASS_IN);
316  ans.ttl = htonl(MDNS_SERVICE_TIME);
317  ans.len = htons(DNS_IP_ADDR_LEN);
318  length = DNS_IP_ADDR_LEN;
319 
320  MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
321 
322  /* resize the query */
323  query = query + SIZEOF_DNS_ANSWER;
324 
325  /* set the local IP address */
326  auth.src = host_addr.addr;
327  MEMCPY( query, &auth, SIZEOF_MDNS_AUTH);
328  }
329  if (type == MDNS_SD_ANSWER) {
330 
331  ans.type = htons(DNS_RRTYPE_PTR);
332  ans.class = htons(DNS_RRCLASS_IN);
333  ans.ttl = htonl(300);
334  ans.len = htons(os_strlen(PUCK_SERVICE) + 1 +1 );
335  length = 0;
336 
337  MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
338 
339  /* resize the query */
340  query = query + SIZEOF_DNS_ANSWER;
341  pHostname = PUCK_SERVICE;
342  --pHostname;
343 
344  /* convert hostname into suitable query format. */
345  do {
346  ++pHostname;
347  nptr = query;
348  ++query;
349  for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
350  *query = *pHostname;
351  ++query;
352  ++n;
353  }
354  *nptr = n;
355  } while (*pHostname != 0);
356  *query++ = '\0';
357  }
358 
359  if (type == MDNS_SERVICE_REG_ANSWER) {
360 
361  ans.type = htons(DNS_RRTYPE_PTR);
362  ans.class = htons(DNS_RRCLASS_IN);
363  ans.ttl = htonl(MDNS_SERVICE_TIME);
364  os_strcpy(tmpBuf, name);
365  os_strcat(tmpBuf, ".");
366  os_strcat(tmpBuf, PUCK_SERVICE);
367 
368  length = os_strlen(tmpBuf) + MDNS_LENGTH_ADD;
369  ans.len = htons(length);
370  length = 0;
371 
372  MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
373 
374  /* resize the query */
375  query = query + SIZEOF_DNS_ANSWER;
376 
377  pHostname = tmpBuf;
378  --pHostname;
379 
380  /* convert hostname into suitable query format. */
381  do {
382  ++pHostname;
383  nptr = query;
384  ++query;
385  for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
386  *query = *pHostname;
387  ++query;
388  ++n;
389  }
390  *nptr = n;
391  } while (*pHostname != 0);
392  *query++ = '\0';
393 
394  /* Service query*/
395  pHostname = name;
396  --pHostname;
397 
398  /* convert hostname into suitable query format. */
399  do {
400  ++pHostname;
401  nptr = query;
402  ++query;
403  for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
404  *query = *pHostname;
405  ++query;
406  ++n;
407  }
408  *nptr = n;
409  } while (*pHostname != 0);
410 
411  /* Add to the service name the service local
412  * pointing to the beginning of the mDNS message*/
413  *query++ = DNS_OFFSET_FLAG;
414  *query++ = DNS_DEFAULT_OFFSET;
415 
416  /* fill the query */
417 
418  ans.type = htons(DNS_RRTYPE_SRV);
419  ans.class = htons(DNS_RRCLASS_FLUSH_IN);
420  ans.ttl = htonl(MDNS_SERVICE_TIME);
421  os_strcpy(tmpBuf, host_name);
422  os_strcat(tmpBuf, ".");
423  os_strcat(tmpBuf, MDNS_LOCAL);
424  length = os_strlen(tmpBuf) + MDNS_LENGTH_ADD;
425  ans.len = htons(SIZEOF_MDNS_SERVICE + length);
426  length = 0;
427  MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
428 
429  /* resize the query */
430  query = query + SIZEOF_DNS_ANSWER;
431  /* fill the service properties */
432 
433  serv.prior = htons(0);
434  serv.weight = htons(0);
435  serv.port = htons(PUCK_PORT);
436  MEMCPY( query, &serv, SIZEOF_MDNS_SERVICE);
437  /* resize the query */
438  query = query + SIZEOF_MDNS_SERVICE;
439 
440  pHostname = tmpBuf;
441  --pHostname;
442 
443  /* convert hostname into suitable query format. */
444  do {
445  ++pHostname;
446  nptr = query;
447  ++query;
448  for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
449  *query = *pHostname;
450  ++query;
451  ++n;
452  }
453  *nptr = n;
454  } while (*pHostname != 0);
455  *query++ = '\0';
456 
457  /* TXT answer */
458  pHostname = name;
459  --pHostname;
460 
461  /* convert hostname into suitable query format. */
462  do {
463  ++pHostname;
464  nptr = query;
465  ++query;
466  for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
467  *query = *pHostname;
468  ++query;
469  ++n;
470  }
471  *nptr = n;
472  } while (*pHostname != 0);
473 
474  /* Add to the service name the service local
475  * pointing to the beginning of the mDNS message*/
476  *query++ = DNS_OFFSET_FLAG;
477  *query++ = DNS_DEFAULT_OFFSET;
478 
479  /* fill the answer */
480  ans.type = htons(DNS_RRTYPE_TXT);
481  ans.class = htons(DNS_RRCLASS_IN);
482  ans.ttl = htonl(MDNS_SERVICE_TIME);
483  length = sizeof(SERVICE_DESCRIPTION);
484  ans.len = htons(length);
485  length = 0;
486  MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
487 
488  /* resize the query */
489  query = query + SIZEOF_DNS_ANSWER;
490 
491  pHostname = SERVICE_DESCRIPTION;
492  --pHostname;
493 
494  /* convert hostname into suitable query format. */
495  do {
496  ++pHostname;
497  nptr = query;
498  ++query;
499  for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
500  *query = *pHostname;
501  ++query;
502  ++n;
503  }
504  *nptr = n;
505  } while (*pHostname != 0);
506  *query++ = '\0';
507  }
508  /* resize pbuf to the exact dns query */
509  pbuf_realloc(p, (query + length) - ((char*) (p->payload)));
510 
511  /* send dns packet */
512  /*add by tzx for AP + STA MDNS begin------*/
513  sta_netif = (struct netif *)eagle_lwip_getif(0x00);
514  ap_netif = (struct netif *)eagle_lwip_getif(0x01);
515  if(wifi_get_opmode() == 0x03 && wifi_get_broadcast_if() == 0x03 &&\
516  sta_netif != NULL && ap_netif != NULL) {
517  if(netif_is_up(sta_netif) && netif_is_up(ap_netif)) {
518 
519  p_sta = pbuf_alloc(PBUF_TRANSPORT,
520  SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM);
521  if (pbuf_copy (p_sta,p) != ERR_OK) {
522  os_printf("mdns_answer copying to new pbuf failed\n");
523  return -1;
524  }
525  netif_set_default(sta_netif);
526  err = udp_sendto(mdns_pcb, p_sta, &multicast_addr, DNS_MDNS_PORT);
527  pbuf_free(p_sta);
528  netif_set_default(ap_netif);
529  }
530  }
531  /*add by tzx for AP + STA MDNS end------*/
532  err = udp_sendto(mdns_pcb, p, &multicast_addr, DNS_MDNS_PORT);
533  /* free pbuf */
534  pbuf_free(p);
535  } else {
536  err = ERR_MEM;
537  }
538 
539  return err;
540 }
541 
542 /**
543  * Send a mDNS service answer packet.
544  *
545  * @param name service name to query
546  * @param id transaction ID in the DNS query packet
547  * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise
548  */
550 mdns_send_service(struct mdns_info *info, u8_t id) {
551  err_t err;
552  struct mdns_hdr *hdr;
553  struct mdns_answer ans;
554  struct mdns_service serv;
555  struct mdns_auth auth;
556  struct pbuf *p ,*p_sta;
557  char *query, *nptr;
558  const char *pHostname;
559  char *device_info;
560  const char *name = info->host_name;
561  u8_t n;
562  u8_t i = 0;
563  u16_t length = 0;
564  u8_t addr1 = 12, addr2 = 12;
565  struct netif * sta_netif = NULL;
566  struct netif * ap_netif = NULL;
567  static char tmpBuf[PUCK_DATASHEET_SIZE + PUCK_SERVICE_LENGTH];
568  /* if here, we have either a new query or a retry on a previous query to process */
570  SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM);
571  if (p != NULL) {
572  LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
573  /* fill dns header */
574  hdr = (struct mdns_hdr*) p->payload;
575  os_memset(hdr, 0, SIZEOF_DNS_HDR);
576  hdr->id = htons(id);
577  hdr->flags1 = DNS_FLAG1_RESPONSE;
578  hdr->numanswers = htons(4);
579  query = (char*) hdr + SIZEOF_DNS_HDR;
580  os_strcpy(tmpBuf, PUCK_SERVICE);
581 
582  pHostname = tmpBuf;
583  --pHostname;
584 
585  /* convert hostname into suitable query format. */
586  do {
587  ++pHostname;
588  nptr = query;
589  ++query;
590  ++addr1;
591  ++addr2;
592  for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
593  *query = *pHostname;
594  ++query;
595  ++addr1;
596  ++addr2;
597  ++n;
598  }
599  *nptr = n;
600  } while (*pHostname != 0);
601  *query++ = '\0';
602  length = sizeof(MDNS_LOCAL);
603  addr1 -= length;
604  length = os_strlen(PUCK_SERVICE) + 1;
605  addr2 -= length;
606 
607  ans.type = htons(DNS_RRTYPE_PTR);
608  ans.class = htons(DNS_RRCLASS_IN);
609  ans.ttl = htonl(300);
610  os_strcpy(tmpBuf, name);
611  length = os_strlen(tmpBuf) + MDNS_LENGTH_ADD + 1;
612  ans.len = htons(length);
613  length = 0;
614 
615  MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
616  /* resize the query */
617  query = query + SIZEOF_DNS_ANSWER;
618 
619  pHostname = tmpBuf;
620  --pHostname;
621  /* convert hostname into suitable query format. */
622  do {
623  ++pHostname;
624  nptr = query;
625  ++query;
626  for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
627  *query = *pHostname;
628  ++query;
629  ++n;
630  }
631  *nptr = n;
632  } while (*pHostname != 0);
633  *query++ = DNS_OFFSET_FLAG;
634  *query++ = DNS_DEFAULT_OFFSET;
635  pHostname = name;
636  --pHostname;
637  /* convert hostname into suitable query format. */
638  do {
639  ++pHostname;
640  nptr = query;
641  ++query;
642  for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
643  *query = *pHostname;
644  ++query;
645  ++n;
646  }
647  *nptr = n;
648  } while (*pHostname != 0);
649  //*query++ = '\0';
650  *query++ = DNS_OFFSET_FLAG;
651  *query++ = DNS_DEFAULT_OFFSET;
652 
653  /* fill the answer */
654  ans.type = htons(DNS_RRTYPE_TXT);
655  ans.class = htons(DNS_RRCLASS_FLUSH_IN);
656  ans.ttl = htonl(300);
657 // length = os_strlen(TXT_DATA) + MDNS_LENGTH_ADD + 1;
658  device_info = (char *)os_zalloc(50);
659  ets_sprintf(device_info,"vendor = %s","Espressif");
660  for(i = 0; i < 10 &&(info->txt_data[i] != NULL);i++) {
661  length += os_strlen(info->txt_data[i]);
662  length++;
663  }
664  length += os_strlen(device_info)+ 1 ;
665  ans.len = htons(length);
666  length = 0;
667  MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
668  query = query + SIZEOF_DNS_ANSWER;
669  pHostname = device_info;
670  --pHostname;
671  /* convert hostname into suitable query format. */
672  do {
673  ++pHostname;
674  nptr = query;
675  ++query;
676  for (n = 0; *pHostname != 0; ++pHostname) {
677  *query = *pHostname;
678  ++query;
679  ++n;
680  }
681  *nptr = n;
682  } while (*pHostname != 0);
683  i = 0;
684  while(info->txt_data[i] != NULL && i < 10) {
685  pHostname = info->txt_data[i];
686  --pHostname;
687  /* convert hostname into suitable query format. */
688  do {
689  ++pHostname;
690  nptr = query;
691  ++query;
692  for (n = 0; *pHostname != 0; ++pHostname) {
693  *query = *pHostname;
694  ++query;
695  ++n;
696  }
697  *nptr = n;
698  } while (*pHostname != 0);
699  i++;
700  }
701 // *query++ = '\0';
702  os_free(device_info);
703  os_strcpy(tmpBuf, name);
704  pHostname = tmpBuf;
705  --pHostname;
706  do {
707  ++pHostname;
708  nptr = query;
709  ++query;
710  for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
711  *query = *pHostname;
712  ++query;
713  ++n;
714  }
715  *nptr = n;
716  } while (*pHostname != 0);
717 
718  *query++ = DNS_OFFSET_FLAG;
719  *query++ = DNS_DEFAULT_OFFSET;
720 
721  ans.type = htons(DNS_RRTYPE_SRV);
722  ans.class = htons(DNS_RRCLASS_FLUSH_IN);
723  ans.ttl = htonl(300);
724  os_strcpy(tmpBuf,service_name);
725  os_strcat(tmpBuf, ".");
726  os_strcat(tmpBuf, MDNS_LOCAL);
727  length = os_strlen(tmpBuf) + MDNS_LENGTH_ADD;
728  ans.len = htons(SIZEOF_MDNS_SERVICE + length);
729  length = 0;
730  MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
731 
732  /* resize the query */
733  query = query + SIZEOF_DNS_ANSWER;
734 
735  serv.prior = htons(0);
736  serv.weight = htons(0);
737  serv.port = htons(PUCK_PORT);
738  MEMCPY( query, &serv, SIZEOF_MDNS_SERVICE);
739  /* resize the query */
740  query = query + SIZEOF_MDNS_SERVICE;
741 
742  pHostname = tmpBuf;
743  --pHostname;
744  do {
745  ++pHostname;
746  nptr = query;
747  ++query;
748  for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
749  *query = *pHostname;
750  ++query;
751  ++n;
752  }
753  *nptr = n;
754  } while (*pHostname != 0);
755  *query++ = '\0';
756  /* set the name of the authority field.
757  * The same name as the Query using the offset address*/
758  os_strcpy(tmpBuf,service_name);
759  os_strcat(tmpBuf, ".");
760  os_strcat(tmpBuf, MDNS_LOCAL);
761  pHostname = tmpBuf;
762  --pHostname;
763  do {
764  ++pHostname;
765  nptr = query;
766  ++query;
767  for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
768  *query = *pHostname;
769  ++query;
770  ++n;
771  }
772  *nptr = n;
773  } while (*pHostname != 0);
774  *query++ = '\0';
775  /* set the name of the authority field.
776  * The same name as the Query using the offset address*/
777  //*query++ = DNS_OFFSET_FLAG;
778  //*query++ = DNS_DEFAULT_OFFSET;
779  ans.type = htons(DNS_RRTYPE_A);
780  ans.class = htons(DNS_RRCLASS_FLUSH_IN);
781  ans.ttl = htonl(300);
782  ans.len = htons(DNS_IP_ADDR_LEN);
783 
784  MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
785 
786  /* resize the query */
787  query = query + SIZEOF_DNS_ANSWER;
788 
789  /* fill the payload of the mDNS message */
790  /* set the local IP address */
791  auth.src = host_addr.addr; //ipAddr;
792  MEMCPY( query, &auth, SIZEOF_MDNS_AUTH);
793  /* resize the query */
794  query = query + SIZEOF_MDNS_AUTH;
795 
796  /* set the name of the authority field.
797  * The same name as the Query using the offset address*/
798 
799  /* resize pbuf to the exact dns query */
800  pbuf_realloc(p, (query) - ((char*) (p->payload)));
801  /* send dns packet */
802  sta_netif = (struct netif *)eagle_lwip_getif(0x00);
803  ap_netif = (struct netif *)eagle_lwip_getif(0x01);
804  if(wifi_get_opmode() == 0x03 && wifi_get_broadcast_if() == 0x03 &&\
805  sta_netif != NULL && ap_netif != NULL) {
806  if(netif_is_up(sta_netif) && netif_is_up(ap_netif)) {
807 
808  p_sta = pbuf_alloc(PBUF_TRANSPORT,
809  SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM);
810  if (pbuf_copy (p_sta,p) != ERR_OK) {
811  os_printf("mdns_send_service copying to new pbuf failed\n");
812  return -1;
813  }
814  netif_set_default(sta_netif);
815  err = udp_sendto(mdns_pcb, p_sta, &multicast_addr, DNS_MDNS_PORT);
816  pbuf_free(p_sta);
817  netif_set_default(ap_netif);
818  }
819  }
820  err = udp_sendto(mdns_pcb, p, &multicast_addr, DNS_MDNS_PORT);
821 
822  /* free pbuf */
823  pbuf_free(p);
824  } else {
825  os_printf("ERR_MEM \n");
826  err = ERR_MEM;
827  }
828 
829  return err;
830 }
831 
832 /**
833  * Receive input function for DNS response packets arriving for the dns UDP pcb.
834  *
835  * @params see udp.h
836  */
837 static void ICACHE_FLASH_ATTR
838 mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr,
839  u16_t port) {
840  u8_t i;
841  struct mdns_hdr *hdr;
842  u8_t nquestions;
843  LWIP_UNUSED_ARG(arg);
844  LWIP_UNUSED_ARG(pcb);
845  LWIP_UNUSED_ARG(addr);
846  LWIP_UNUSED_ARG(port);
847  struct mdns_info *info = (struct mdns_info *)arg;
848  /* is the dns message too big ? */
849  if (p->tot_len > DNS_MSG_SIZE) {
850  LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n"));
851  /* free pbuf and return */
852  goto memerr1;
853  }
854 
855  /* is the dns message big enough ? */
856  if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) {
857  LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
858  /* free pbuf and return */
859  goto memerr1;
860  }
861  /* copy dns payload inside static buffer for processing */
862  if (pbuf_copy_partial(p, mdns_payload, p->tot_len, 0) == p->tot_len) {
863  /* The ID in the DNS header should be our entry into the name table. */
864  hdr = (struct mdns_hdr*) mdns_payload;
865 
866  i = htons(hdr->id);
867  if (i < DNS_TABLE_SIZE) {
868 
869  nquestions = htons(hdr->numquestions);
870  //nanswers = htons(hdr->numanswers);
871  /* if we have a question send an answer if necessary */
872  if (nquestions > 0) {
873  /* MDNS_DS_DOES_NAME_CHECK */
874  /* Check if the name in the "question" part match with the name of the MDNS DS service. */
875  if (mdns_compare_name((unsigned char *) DNS_SD_SERVICE,
876  (unsigned char *) mdns_payload + SIZEOF_DNS_HDR) == 0) {
877  /* respond with the puck service*/
878  mdns_answer(MDNS_SD_ANSWER, PUCK_SERVICE, 0);
879  } else if (mdns_compare_name((unsigned char *) PUCK_SERVICE,
880  (unsigned char *) mdns_payload + SIZEOF_DNS_HDR) == 0) {
881  /* respond with the puck service*/
882  mdns_send_service(info, 0);
883  } else
884  goto memerr2;
885  }
886  }
887  }
888  goto memerr2;
889  memerr2:
890  os_memset(mdns_payload , 0 ,DNS_MSG_SIZE);
891  memerr1:
892  /* free pbuf */
893  pbuf_free(p);
894  return;
895 }
896 
897 /**
898  * close the UDP pcb .
899  */
901 mdns_close(void)
902 {
903  if (mdns_pcb != NULL && ms_info != NULL)
904  udp_remove(mdns_pcb);
905  os_free(ms_info);
906  mdns_pcb = NULL;
907  ms_info = NULL;
908 
909 }
910 
912 mdns_set_name(const char *name)
913 {
914  //strcpy(host_name, name);
915  os_strcpy(service_name, name);
916 }
917 
919 mdns_enable(void)
920 {
921  if(mdns_flag == 0) {
922  udp_recv(mdns_pcb, mdns_recv, NULL);
923  }
924 }
925 
927 mdns_disable(void)
928 {
929  if (mdns_flag == 1) {
930  udp_recv(mdns_pcb, NULL, NULL);
931  }
932 }
933 
934 /**
935  * close the UDP pcb .
936  */
937 char* ICACHE_FLASH_ATTR
938 mdns_get_hostname(void) {
939  //strcpy(host_name, name);
940  char *name = host_name;
941  if (host_name[0] != 0 ) {
942  return name;
943  } else {
944  return ("Espressif");
945  }
946 }
947 
949 mdns_set_hostname(char *name) {
950  if (name == NULL) {
951  os_strncpy(host_name, "Espressif", os_strlen("Espressif")+3);
952  return;
953  }
954  if (os_strlen(name) + 3 <= MDNS_NAME_LENGTH ){
955  os_strncpy(host_name, name, os_strlen(name) );
956 // os_memset(host_name + os_strlen(host_name) ,0x00,3);
957  } else {
958  os_strncpy(host_name, name, MDNS_NAME_LENGTH);
959  }
960 }
961 
963 mdns_set_servername(const char *name) {
964  if (name == NULL) {
965  PUCK_SERVICE = "_Espressif._tcp._local";
966  }else {
967  os_sprintf(server_name ,"_%s._tcp.local",name);
968  PUCK_SERVICE = server_name;
969  }
970 }
971 
972 char* ICACHE_FLASH_ATTR
973 mdns_get_servername(void) {
974  char *name = PUCK_SERVICE;
975  if (name == NULL) {
976  PUCK_SERVICE = "_Espressif._tcp._local";
977  }
978  return name;
979 }
980 
982 mdns_server_unregister(void) {
983  struct ip_addr ap_host_addr;
984  struct ip_info ipconfig;
985  if(register_flag == 1){
986  if (igmp_leavegroup(&host_addr, &multicast_addr) != ERR_OK) {
987  os_printf("sta udp_leave_multigrup failed!\n");
988  return;
989  };
990  if(wifi_get_opmode() == 0x03 || wifi_get_opmode() == 0x02) {
991  wifi_get_ip_info(SOFTAP_IF, &ipconfig);
992  ap_host_addr.addr = ipconfig.ip.addr;
993  if (igmp_leavegroup(&ap_host_addr, &multicast_addr) != ERR_OK) {
994  os_printf("ap udp_join_multigrup failed!\n");
995  return;
996  };
997  }
998  register_flag = 0;
999  }
1000 }
1001 
1002 void ICACHE_FLASH_ATTR
1003 mdns_server_register(void) {
1004 
1005  if (register_flag == 1) {
1006  os_printf("mdns server is already registered !\n");
1007  return;
1008  } else if (igmp_joingroup(&host_addr, &multicast_addr) != ERR_OK) {
1009  os_printf("udp_join_multigrup failed!\n");
1010  return;
1011  };
1012  register_flag = 1;
1013 }
1014 
1015 void ICACHE_FLASH_ATTR
1016 mdns_reg(struct mdns_info *info) {
1017 
1018  static uint8 i = 0;
1019  if (i <= 3) {
1020  mdns_send_service(info,0);
1021  i++;
1022  } else {
1023  os_timer_disarm(&mdns_timer);
1024  }
1025 }
1026 
1027 /**
1028  * Initialize the resolver: set up the UDP pcb and configure the default server
1029  * (NEW IP).
1030  */
1031 void ICACHE_FLASH_ATTR
1032 mdns_init(struct mdns_info *info) {
1033  /* initialize default DNS server address */
1034  multicast_addr.addr = DNS_MULTICAST_ADDRESS;
1035  struct ip_addr ap_host_addr;
1036  struct ip_info ipconfig;
1037  ms_info = (struct mdns_info *)os_zalloc(sizeof(struct mdns_info));
1038  if (ms_info != NULL) {
1039  os_memcpy(ms_info,info,sizeof(struct mdns_info));
1040  } else {
1041  os_printf("ms_info alloc failed\n");
1042  return;
1043  }
1044  if (ms_info->ipAddr == 0) {
1045  os_printf("mdns ip error!\n ");
1046  return;
1047  }
1048  host_addr.addr = ms_info->ipAddr ;
1049  LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n"));
1050  //get the datasheet from PUCK
1051  mdns_set_hostname(ms_info->host_name);
1052  mdns_set_servername(ms_info->server_name);
1053  mdns_set_name(ms_info->host_name);
1054 
1055  // get the host name as instrumentName_serialNumber for MDNS
1056  // set the name of the service, the same as host name
1057  os_printf("host_name = %s\n", host_name);
1058  os_printf("server_name = %s\n", PUCK_SERVICE);
1059  if (ms_info->server_port == 0)
1060  {
1061  PUCK_PORT = 80;
1062  } else {
1063  PUCK_PORT = ms_info->server_port;
1064  }
1065 
1066  /* initialize mDNS */
1067  mdns_pcb = udp_new();
1068 
1069  if (mdns_pcb != NULL) {
1070  /* join to the multicast address 224.0.0.251 */
1071  if(wifi_get_opmode() == 0x03 || wifi_get_opmode() == 0x01) {
1072  if (igmp_joingroup(&host_addr, &multicast_addr) != ERR_OK) {
1073  os_printf("sta udp_join_multigrup failed!\n");
1074  return;
1075  };
1076  }
1077  if(wifi_get_opmode() == 0x03 || wifi_get_opmode() == 0x02) {
1078  wifi_get_ip_info(SOFTAP_IF, &ipconfig);
1079  ap_host_addr.addr = ipconfig.ip.addr;
1080  if (igmp_joingroup(&ap_host_addr, &multicast_addr) != ERR_OK) {
1081  os_printf("ap udp_join_multigrup failed!\n");
1082  return;
1083  };
1084  }
1085  register_flag = 1;
1086  /* join to any IP address at the port 5353 */
1087  if (udp_bind(mdns_pcb, IP_ADDR_ANY, DNS_MDNS_PORT) != ERR_OK) {
1088  os_printf("udp_bind failed!\n");
1089  return;
1090  };
1091 
1092  /*loopback function for the multicast(224.0.0.251) messages received at port 5353*/
1093 // mdns_enable();
1094  udp_recv(mdns_pcb, mdns_recv, ms_info);
1095  mdns_flag = 1;
1096  /*
1097  * Register the name of the instrument
1098  */
1099 
1100  os_timer_disarm(&mdns_timer);
1101  os_timer_setfn(&mdns_timer, (os_timer_func_t *)mdns_reg,ms_info);
1102  os_timer_arm(&mdns_timer, 1000, 1);
1103  }
1104 }
1105 
1106 #endif /* LWIP_MDNS */
#define os_sprintf
Definition: osapi.h:54
#define DNS_TABLE_SIZE
Definition: opt.h:803
#define DNS_MSG_SIZE
Definition: opt.h:823
u16_t tot_len
Definition: pbuf.h:90
#define SOFTAP_IF
#define os_timer_t
Definition: os_type.h:34
struct pbuf * next
Definition: pbuf.h:78
err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from) ICACHE_FLASH_ATTR
Definition: pbuf.c:930
#define os_timer_disarm
Definition: osapi.h:51
#define PUCK_SERVICE_LENGTH
Definition: puck_def.h:23
#define os_strcat
Definition: osapi.h:39
#define NULL
Definition: def.h:47
en61107_response_t response
#define htons(x)
Definition: def.h:81
const ip_addr_t ip_addr_any ICACHE_RODATA_ATTR
Definition: ip_addr.c:44
unsigned short uint16
Definition: c_types.h:50
#define ICACHE_FLASH_ATTR
Definition: c_types.h:99
bool wifi_get_ip_info(uint8 if_index, struct ip_info *info)
#define os_timer_func_t
Definition: os_type.h:35
Definition: pbuf.h:58
#define DNS_DEBUG
Definition: opt.h:2044
struct netif * eagle_lwip_getif(uint8 index)
#define os_printf
Definition: osapi.h:62
uint8 wifi_get_opmode(void)
#define os_timer_setfn
Definition: osapi.h:52
char * host_name
Definition: espconn.h:185
#define os_zalloc(s)
Definition: mem.h:44
#define os_memcpy
Definition: osapi.h:36
#define os_strlen
Definition: osapi.h:43
unsigned long u32_t
Definition: cc.h:56
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:94
#define os_memset
Definition: osapi.h:38
#define os_strncpy
Definition: osapi.h:45
void netif_set_default(struct netif *netif) ICACHE_FLASH_ATTR
Definition: netif.c:431
uint8 wifi_get_broadcast_if(void)
#define ERR_OK
Definition: err.h:52
Definition: pbuf.h:76
unsigned char uint8
Definition: c_types.h:45
#define PACK_STRUCT_STRUCT
Definition: cc.h:72
s8_t err_t
Definition: err.h:47
Definition: netif.h:139
#define IP_ADDR_ANY
Definition: ip_addr.h:92
#define os_free(s)
Definition: mem.h:40
u8_t pbuf_free(struct pbuf *p) ICACHE_FLASH_ATTR
Definition: pbuf.c:685
char * txt_data[10]
Definition: espconn.h:189
#define PACK_STRUCT_BEGIN
Definition: cc.h:73
#define os_timer_arm(a, b, c)
Definition: osapi.h:50
#define PACK_STRUCT_END
Definition: cc.h:74
unsigned char u8_t
Definition: cc.h:52
#define MEMCPY(dst, src, len)
Definition: opt.h:84
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:65
#define os_strcpy
Definition: osapi.h:42
void * payload
Definition: pbuf.h:81
u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset) ICACHE_FLASH_ATTR
Definition: pbuf.c:996
#define netif_is_up(netif)
Definition: netif.h:286
#define MDNS_NAME_LENGTH
Definition: puck_def.h:17
#define SERVICE_DESCRIPTION
Definition: puck_def.h:22
void pbuf_realloc(struct pbuf *p, u16_t size) ICACHE_FLASH_ATTR
Definition: pbuf.c:492
#define DNS_SD_SERVICE
Definition: puck_def.h:21
#define PUCK_DATASHEET_SIZE
Definition: puck_def.h:33
#define ERR_MEM
Definition: err.h:53
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:73
char * PUCK_SERVICE
Definition: puck_def.h:19
#define htonl(x)
Definition: def.h:83
struct pbuf * pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type) ICACHE_FLASH_ATTR
Definition: pbuf.c:234
unsigned short u16_t
Definition: cc.h:54
#define PACK_STRUCT_FIELD(x)
Definition: cc.h:71