nodemcu_mdns.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919
  1. /**
  2. * lwip MDNS resolver file.
  3. *
  4. * Created on: Jul 29, 2010
  5. * Author: Daniel Toma
  6. *
  7. * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. The name of the author may not be used to endorse or promote
  18. * products derived from this software without specific prior
  19. * written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
  22. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  23. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  25. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  27. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  28. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  29. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  30. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. */
  33. /**
  34. * This file implements a MDNS host name and PUCK service registration.
  35. *-----------------------------------------------------------------------------
  36. * Includes
  37. *----------------------------------------------------------------------------*/
  38. #include "lwip/opt.h"
  39. #if LWIP_MDNS /* don't build if not configured for use in lwipopts.h */
  40. #include "lwip/mdns.h"
  41. #include "lwip/udp.h"
  42. #include "lwip/mem.h"
  43. #include "lwip/igmp.h"
  44. #include "osapi.h"
  45. #include "os_type.h"
  46. #include "user_interface.h"
  47. #include "c_string.h"
  48. #include "nodemcu_mdns.h"
  49. #if 0
  50. #define MDNS_DBG(...) os_printf(...)
  51. #else
  52. #define MDNS_DBG(...) do {} while (0)
  53. #endif
  54. #define MDNS_NAME_LENGTH 68 //68
  55. static const char* service_name_with_suffix = NULL;
  56. #define DNS_SD_SERVICE "_services._dns-sd._udp.local"
  57. #define PUCK_SERVICE_LENGTH 30
  58. #define PUCK_DATASHEET_SIZE 96
  59. #ifdef MEMLEAK_DEBUG
  60. static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
  61. #endif
  62. /** DNS server IP address */
  63. #ifndef DNS_MULTICAST_ADDRESS
  64. #define DNS_MULTICAST_ADDRESS ipaddr_addr("224.0.0.251") /* resolver1.opendns.com */
  65. #endif
  66. /** DNS server IP address */
  67. #ifndef MDNS_LOCAL
  68. #define MDNS_LOCAL "local" /* resolver1.opendns.com */
  69. #endif
  70. /** DNS server port address */
  71. #ifndef DNS_MDNS_PORT
  72. #define DNS_MDNS_PORT 5353
  73. #endif
  74. /** DNS maximum number of retries when asking for a name, before "timeout". */
  75. #ifndef DNS_MAX_RETRIES
  76. #define DNS_MAX_RETRIES 4
  77. #endif
  78. /** DNS resource record max. TTL (one week as default) */
  79. #ifndef DNS_MAX_TTL
  80. #define DNS_MAX_TTL 604800
  81. #endif
  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. /* DNS protocol states */
  95. #define DNS_STATE_UNUSED 0
  96. #define DNS_STATE_NEW 1
  97. #define DNS_STATE_ASKING 2
  98. #define DNS_STATE_DONE 3
  99. /* MDNS registration type */
  100. #define MDNS_HOSTNAME_REG 0
  101. #define MDNS_SERVICE_REG 1
  102. /* MDNS registration type */
  103. #define MDNS_REG_ANSWER 1
  104. #define MDNS_SD_ANSWER 2
  105. #define MDNS_SERVICE_REG_ANSWER 3
  106. /* MDNS registration time */
  107. #define MDNS_HOST_TIME 120
  108. #define MDNS_SERVICE_TIME 3600
  109. /** MDNS name length with "." at the beginning and end of name*/
  110. #ifndef MDNS_LENGTH_ADD
  111. #define MDNS_LENGTH_ADD 2
  112. #endif
  113. #ifdef MDNS_MAX_NAME_LENGTH
  114. #undef MDNS_MAX_NAME_LENGTH
  115. #endif
  116. #define MDNS_MAX_NAME_LENGTH (256)
  117. PACK_STRUCT_BEGIN
  118. /** DNS message header */
  119. struct mdns_hdr {
  120. PACK_STRUCT_FIELD(u16_t id);
  121. PACK_STRUCT_FIELD(u8_t flags1);
  122. PACK_STRUCT_FIELD(u8_t flags2);
  123. PACK_STRUCT_FIELD(u16_t numquestions);
  124. PACK_STRUCT_FIELD(u16_t numanswers);
  125. PACK_STRUCT_FIELD(u16_t numauthrr);
  126. PACK_STRUCT_FIELD(u16_t numextrarr);
  127. }PACK_STRUCT_STRUCT;
  128. PACK_STRUCT_END
  129. #define SIZEOF_DNS_HDR 12
  130. PACK_STRUCT_BEGIN
  131. /** MDNS query message structure */
  132. struct mdns_query {
  133. /* MDNS query record starts with either a domain name or a pointer
  134. to a name already present somewhere in the packet. */PACK_STRUCT_FIELD(u16_t type);
  135. PACK_STRUCT_FIELD(u16_t class);
  136. }PACK_STRUCT_STRUCT;
  137. PACK_STRUCT_END
  138. #define SIZEOF_DNS_QUERY 4
  139. PACK_STRUCT_BEGIN
  140. /** MDNS answer message structure */
  141. struct mdns_answer {
  142. /* MDNS answer 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);
  145. PACK_STRUCT_FIELD(u32_t ttl);
  146. PACK_STRUCT_FIELD(u16_t len);
  147. }PACK_STRUCT_STRUCT;
  148. PACK_STRUCT_END
  149. #define SIZEOF_DNS_ANSWER 10
  150. PACK_STRUCT_BEGIN
  151. /** MDNS answer message structure */
  152. struct mdns_auth {
  153. PACK_STRUCT_FIELD(u32_t src);
  154. }PACK_STRUCT_STRUCT;
  155. PACK_STRUCT_END
  156. #define SIZEOF_MDNS_AUTH 4
  157. PACK_STRUCT_BEGIN
  158. /** MDNS service registration message structure */
  159. struct mdns_service {
  160. PACK_STRUCT_FIELD(u16_t prior);
  161. PACK_STRUCT_FIELD(u16_t weight);
  162. PACK_STRUCT_FIELD(u16_t port);
  163. }PACK_STRUCT_STRUCT;
  164. PACK_STRUCT_END
  165. #define SIZEOF_MDNS_SERVICE 6
  166. static os_timer_t mdns_timer;
  167. /* forward declarations */
  168. static void mdns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p,
  169. struct ip_addr *addr, u16_t port);
  170. /*-----------------------------------------------------------------------------
  171. * Globales
  172. *----------------------------------------------------------------------------*/
  173. /* MDNS variables */
  174. //static char puck_datasheet[PUCK_DATASHEET_SIZE];
  175. static struct udp_pcb *mdns_pcb = NULL;
  176. static struct nodemcu_mdns_info * ms_info = NULL;
  177. static struct ip_addr multicast_addr;
  178. static uint8 register_flag = 0;
  179. static uint8 mdns_flag = 0;
  180. static u8_t *mdns_payload;
  181. /**
  182. * Compare the "dotted" name "query" with the encoded name "response"
  183. * to make sure an answer from the DNS server matches the current mdns_table
  184. * entry (otherwise, answers might arrive late for hostname not on the list
  185. * any more).
  186. *
  187. * @param query hostname (not encoded) from the mdns_table
  188. * @param response encoded hostname in the DNS response
  189. * @return 0: names equal; 1: names differ
  190. */
  191. static u8_t ICACHE_FLASH_ATTR
  192. mdns_compare_name(unsigned char *query, unsigned char *response) {
  193. unsigned char n;
  194. do {
  195. n = *response++;
  196. /** @see RFC 1035 - 4.1.4. Message compression */
  197. if ((n & 0xc0) == 0xc0) {
  198. /* Compressed name */
  199. break;
  200. } else {
  201. /* Not compressed name */
  202. while (n > 0) {
  203. if ((*query) != (*response)) {
  204. return 1;
  205. }
  206. ++response;
  207. ++query;
  208. --n;
  209. };
  210. ++query;
  211. }
  212. } while (*response != 0);
  213. return 0;
  214. }
  215. static int
  216. mdns_namelen(u8_t *p, unsigned int maxlen) {
  217. u8_t *orig = p;
  218. while (*p && *p <= 63) {
  219. if (p - orig > maxlen) {
  220. return -1;
  221. }
  222. p += *p + 1;
  223. }
  224. if (*p >= 0xc0) {
  225. p += 2; // advance over the two byte pointer
  226. } else {
  227. p++; // advance over the final 0
  228. }
  229. if (p - orig > maxlen) {
  230. return -1;
  231. }
  232. return p - orig;
  233. }
  234. static err_t send_packet(struct pbuf *p, struct ip_addr *dst_addr, u16_t dst_port, u8_t *addr_ptr) {
  235. err_t err;
  236. /* send dns packet */
  237. struct netif *sta_netif = (struct netif *)eagle_lwip_getif(0x00);
  238. struct netif *ap_netif = (struct netif *)eagle_lwip_getif(0x01);
  239. if (addr_ptr) {
  240. if (wifi_get_opmode() == 0x02) {
  241. if (!ap_netif) {
  242. return;
  243. }
  244. memcpy(addr_ptr, &ap_netif->ip_addr, sizeof(ap_netif->ip_addr));
  245. } else {
  246. if (!sta_netif) {
  247. return;
  248. }
  249. memcpy(addr_ptr, &sta_netif->ip_addr, sizeof(sta_netif->ip_addr));
  250. }
  251. }
  252. if (dst_addr) {
  253. err = udp_sendto(mdns_pcb, p, dst_addr, dst_port);
  254. } else {
  255. err = udp_sendto(mdns_pcb, p, &multicast_addr, DNS_MDNS_PORT);
  256. if(wifi_get_opmode() == 0x03 && wifi_get_broadcast_if() == 0x03 &&\
  257. sta_netif != NULL && ap_netif != NULL) {
  258. if(netif_is_up(sta_netif) && netif_is_up(ap_netif)) {
  259. netif_set_default(sta_netif);
  260. if (addr_ptr) {
  261. memcpy(addr_ptr, &ap_netif->ip_addr, sizeof(ap_netif->ip_addr));
  262. }
  263. err = udp_sendto(mdns_pcb, p, &multicast_addr, DNS_MDNS_PORT);
  264. netif_set_default(ap_netif);
  265. }
  266. }
  267. }
  268. /* free pbuf */
  269. pbuf_free(p);
  270. return err;
  271. }
  272. /**
  273. * Send a mDNS packet for the service type
  274. *
  275. * @param id transaction ID in the DNS query packet
  276. * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise
  277. */
  278. static err_t ICACHE_FLASH_ATTR
  279. mdns_send_service_type(u16_t id, struct ip_addr *dst_addr, u16_t dst_port) {
  280. err_t err;
  281. struct mdns_hdr *hdr;
  282. struct mdns_answer ans;
  283. struct mdns_auth auth;
  284. struct mdns_service serv;
  285. struct pbuf *p ,*p_sta;
  286. char *query, *nptr;
  287. const char *pHostname;
  288. struct netif * sta_netif = NULL;
  289. struct netif * ap_netif = NULL;
  290. char tmpBuf[PUCK_DATASHEET_SIZE + PUCK_SERVICE_LENGTH];
  291. u8_t n;
  292. u16_t length = 0;
  293. /* if here, we have either a new query or a retry on a previous query to process */
  294. p = pbuf_alloc(PBUF_TRANSPORT,
  295. SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM);
  296. if (p != NULL) {
  297. LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
  298. /* fill dns header */
  299. hdr = (struct mdns_hdr*) p->payload;
  300. os_memset(hdr, 0, SIZEOF_DNS_HDR);
  301. hdr->id = htons(id);
  302. hdr->flags1 = DNS_FLAG1_RESPONSE;
  303. pHostname = DNS_SD_SERVICE;
  304. hdr->numanswers = htons(1);
  305. query = (char*) hdr + SIZEOF_DNS_HDR;
  306. --pHostname;
  307. /* convert hostname into suitable query format. */
  308. do {
  309. ++pHostname;
  310. nptr = query;
  311. ++query;
  312. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  313. *query = *pHostname;
  314. ++query;
  315. ++n;
  316. }
  317. *nptr = n;
  318. } while (*pHostname != 0);
  319. *query++ = '\0';
  320. /* fill dns query */
  321. ans.type = htons(DNS_RRTYPE_PTR);
  322. ans.class = htons(DNS_RRCLASS_IN);
  323. ans.ttl = htonl(3600);
  324. ans.len = htons(os_strlen(service_name_with_suffix) + 1 +1 );
  325. length = 0;
  326. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  327. /* resize the query */
  328. query = query + SIZEOF_DNS_ANSWER;
  329. pHostname = service_name_with_suffix;
  330. --pHostname;
  331. /* convert hostname into suitable query format. */
  332. do {
  333. ++pHostname;
  334. nptr = query;
  335. ++query;
  336. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  337. *query = *pHostname;
  338. ++query;
  339. ++n;
  340. }
  341. *nptr = n;
  342. } while (*pHostname != 0);
  343. *query++ = '\0';
  344. /* resize pbuf to the exact dns query */
  345. pbuf_realloc(p, (query + length) - ((char*) (p->payload)));
  346. err = send_packet(p, dst_addr, dst_port, 0);
  347. } else {
  348. err = ERR_MEM;
  349. }
  350. return err;
  351. }
  352. /**
  353. * Send a mDNS service answer packet.
  354. *
  355. * @param name service name to query
  356. * @param id transaction ID in the DNS query packet
  357. * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise
  358. */
  359. static err_t ICACHE_FLASH_ATTR
  360. mdns_send_service(struct nodemcu_mdns_info *info, u16_t id, struct ip_addr *dst_addr, u16_t dst_port) {
  361. err_t err;
  362. struct mdns_hdr *hdr;
  363. struct mdns_answer ans;
  364. struct mdns_service serv;
  365. struct mdns_auth auth;
  366. struct pbuf *p ,*p_sta;
  367. char *query, *nptr;
  368. char *query_end;
  369. const char *pHostname;
  370. const char *name = info->host_name;
  371. u8_t n;
  372. u8_t i = 0;
  373. u16_t length = 0;
  374. u8_t addr1 = 12, addr2 = 12;
  375. struct netif * sta_netif = NULL;
  376. struct netif * ap_netif = NULL;
  377. char tmpBuf[PUCK_DATASHEET_SIZE + PUCK_SERVICE_LENGTH];
  378. u16_t dns_class = dst_addr ? DNS_RRCLASS_IN : DNS_RRCLASS_FLUSH_IN;
  379. /* if here, we have either a new query or a retry on a previous query to process */
  380. p = pbuf_alloc(PBUF_TRANSPORT,
  381. SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM);
  382. if (p != NULL) {
  383. LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
  384. /* fill dns header */
  385. hdr = (struct mdns_hdr*) p->payload;
  386. os_memset(hdr, 0, SIZEOF_DNS_HDR);
  387. hdr->id = htons(id);
  388. hdr->flags1 = DNS_FLAG1_RESPONSE;
  389. hdr->numanswers = htons(4);
  390. query = (char*) hdr + SIZEOF_DNS_HDR;
  391. query_end = (char *) p->payload + p->tot_len;
  392. c_strlcpy(tmpBuf, service_name_with_suffix, sizeof(tmpBuf));
  393. pHostname = tmpBuf;
  394. --pHostname;
  395. /* convert hostname into suitable query format. */
  396. do {
  397. ++pHostname;
  398. nptr = query;
  399. ++query;
  400. ++addr1;
  401. ++addr2;
  402. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  403. *query = *pHostname;
  404. ++query;
  405. ++addr1;
  406. ++addr2;
  407. ++n;
  408. }
  409. *nptr = n;
  410. } while (*pHostname != 0);
  411. *query++ = '\0';
  412. length = sizeof(MDNS_LOCAL);
  413. addr1 -= length;
  414. length = os_strlen(service_name_with_suffix) + 1;
  415. addr2 -= length;
  416. ans.type = htons(DNS_RRTYPE_PTR);
  417. ans.class = htons(DNS_RRCLASS_IN);
  418. ans.ttl = htonl(300);
  419. length = os_strlen(ms_info->host_desc) + MDNS_LENGTH_ADD + 1;
  420. ans.len = htons(length);
  421. length = 0;
  422. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  423. /* resize the query */
  424. query = query + SIZEOF_DNS_ANSWER;
  425. int name_offset = query - (const char *) hdr;
  426. pHostname = ms_info->host_desc;
  427. --pHostname;
  428. /* convert hostname into suitable query format. */
  429. do {
  430. ++pHostname;
  431. nptr = query;
  432. ++query;
  433. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  434. *query = *pHostname;
  435. ++query;
  436. ++n;
  437. }
  438. *nptr = n;
  439. } while (*pHostname != 0);
  440. *query++ = DNS_OFFSET_FLAG;
  441. *query++ = DNS_DEFAULT_OFFSET;
  442. *query++ = 0xc0 + (name_offset >> 8);
  443. *query++ = name_offset & 0xff;
  444. /* fill the answer */
  445. ans.type = htons(DNS_RRTYPE_TXT);
  446. ans.class = htons(dns_class);
  447. ans.ttl = htonl(300);
  448. // length = os_strlen(TXT_DATA) + MDNS_LENGTH_ADD + 1;
  449. const char *attributes[12];
  450. int attr_count = 0;
  451. for(i = 0; i < 10 && (info->txt_data[i] != NULL); i++) {
  452. length += os_strlen(info->txt_data[i]);
  453. length++;
  454. attributes[attr_count++] = info->txt_data[i];
  455. }
  456. //MDNS_DBG("Found %d user attributes\n", i);
  457. static const char *defaults[] = { "platform=nodemcu", NULL };
  458. for(i = 0; defaults[i] != NULL; i++) {
  459. // See if this is a duplicate
  460. int j;
  461. int len = strchr(defaults[i], '=') + 1 - defaults[i];
  462. for (j = 0; j < attr_count; j++) {
  463. if (strncmp(attributes[j], defaults[i], len) == 0) {
  464. break;
  465. }
  466. }
  467. if (j == attr_count) {
  468. length += os_strlen(defaults[i]);
  469. length++;
  470. attributes[attr_count++] = defaults[i];
  471. }
  472. }
  473. //MDNS_DBG("Found %d total attributes\n", attr_count);
  474. ans.len = htons(length);
  475. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  476. query = query + SIZEOF_DNS_ANSWER;
  477. // Check enough space in the packet
  478. const char *end_of_packet = query + length + 2 + SIZEOF_DNS_ANSWER + SIZEOF_MDNS_SERVICE +
  479. os_strlen(ms_info->host_name) + 7 + 1 + 2 + SIZEOF_DNS_ANSWER + SIZEOF_MDNS_AUTH;
  480. if (query_end <= end_of_packet) {
  481. MDNS_DBG("Too much data to send\n");
  482. pbuf_free(p);
  483. return ERR_MEM;
  484. }
  485. //MDNS_DBG("Query=%x, query_end=%x, end_ofpacket=%x, length=%x\n", query, query_end, end_of_packet, length);
  486. i = 0;
  487. while(attributes[i] != NULL && i < attr_count) {
  488. pHostname = attributes[i];
  489. --pHostname;
  490. /* convert hostname into suitable query format. */
  491. do {
  492. ++pHostname;
  493. nptr = query;
  494. ++query;
  495. for (n = 0; *pHostname != 0; ++pHostname) {
  496. *query = *pHostname;
  497. ++query;
  498. ++n;
  499. }
  500. *nptr = n;
  501. } while (*pHostname != 0);
  502. i++;
  503. }
  504. // *query++ = '\0';
  505. // Increment by length
  506. *query++ = 0xc0 + (name_offset >> 8);
  507. *query++ = name_offset & 0xff;
  508. // Increment by 2
  509. ans.type = htons(DNS_RRTYPE_SRV);
  510. ans.class = htons(dns_class);
  511. ans.ttl = htonl(300);
  512. c_strlcpy(tmpBuf,ms_info->host_name, sizeof(tmpBuf));
  513. c_strlcat(tmpBuf, ".", sizeof(tmpBuf));
  514. c_strlcat(tmpBuf, MDNS_LOCAL, sizeof(tmpBuf));
  515. length = os_strlen(tmpBuf) + MDNS_LENGTH_ADD;
  516. ans.len = htons(SIZEOF_MDNS_SERVICE + length);
  517. length = 0;
  518. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  519. /* resize the query */
  520. query = query + SIZEOF_DNS_ANSWER;
  521. serv.prior = htons(0);
  522. serv.weight = htons(0);
  523. serv.port = htons(ms_info->service_port);
  524. MEMCPY( query, &serv, SIZEOF_MDNS_SERVICE);
  525. /* resize the query */
  526. query = query + SIZEOF_MDNS_SERVICE;
  527. int hostname_offset = query - (const char *) hdr;
  528. pHostname = tmpBuf;
  529. --pHostname;
  530. do {
  531. ++pHostname;
  532. nptr = query;
  533. ++query;
  534. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  535. *query = *pHostname;
  536. ++query;
  537. ++n;
  538. }
  539. *nptr = n;
  540. } while (*pHostname != 0);
  541. *query++ = '\0';
  542. // increment by strlen(service_name) + 1 + 7 + sizeof_dns_answer + sizeof_mdns_service
  543. *query++ = 0xc0 + (hostname_offset >> 8);
  544. *query++ = hostname_offset & 0xff;
  545. ans.type = htons(DNS_RRTYPE_A);
  546. ans.class = htons(dns_class);
  547. ans.ttl = htonl(300);
  548. ans.len = htons(DNS_IP_ADDR_LEN);
  549. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  550. /* resize the query */
  551. query = query + SIZEOF_DNS_ANSWER;
  552. // increment by strlen(service_name) + 1 + 7 + sizeof_dns_answer
  553. /* fill the payload of the mDNS message */
  554. /* set the local IP address */
  555. auth.src = 0;
  556. MEMCPY( query, &auth, SIZEOF_MDNS_AUTH);
  557. u8_t *addr_ptr = query + ((char *) &auth.src - (char *) &auth);
  558. /* resize the query */
  559. query = query + SIZEOF_MDNS_AUTH;
  560. //MDNS_DBG("Final ptr=%x\n", query);
  561. // increment by sizeof_mdns_auth
  562. /* set the name of the authority field.
  563. * The same name as the Query using the offset address*/
  564. /* resize pbuf to the exact dns query */
  565. pbuf_realloc(p, (query) - ((char*) (p->payload)));
  566. err = send_packet(p, dst_addr, dst_port, addr_ptr);
  567. } else {
  568. MDNS_DBG("ERR_MEM \n");
  569. err = ERR_MEM;
  570. }
  571. return err;
  572. }
  573. /**
  574. * Receive input function for DNS response packets arriving for the dns UDP pcb.
  575. *
  576. * @params see udp.h
  577. */
  578. static void ICACHE_FLASH_ATTR
  579. mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr,
  580. u16_t port) {
  581. u16_t i;
  582. struct mdns_hdr *hdr;
  583. u8_t nquestions;
  584. LWIP_UNUSED_ARG(arg);
  585. LWIP_UNUSED_ARG(pcb);
  586. struct nodemcu_mdns_info *info = (struct nodemcu_mdns_info *)arg;
  587. /* is the dns message too big ? */
  588. if (p->tot_len > DNS_MSG_SIZE) {
  589. LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n"));
  590. /* free pbuf and return */
  591. goto memerr1;
  592. }
  593. /* is the dns message big enough ? */
  594. if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) {
  595. LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
  596. /* free pbuf and return */
  597. goto memerr1;
  598. }
  599. /* copy dns payload inside static buffer for processing */
  600. if (pbuf_copy_partial(p, mdns_payload, p->tot_len, 0) == p->tot_len) {
  601. /* The ID in the DNS header should be our entry into the name table. */
  602. hdr = (struct mdns_hdr*) mdns_payload;
  603. i = htons(hdr->id);
  604. nquestions = htons(hdr->numquestions);
  605. //nanswers = htons(hdr->numanswers);
  606. /* if we have a question send an answer if necessary */
  607. if (nquestions > 0) {
  608. struct mdns_query qry;
  609. int namelen = mdns_namelen((u8_t *) (hdr + 1), p->tot_len);
  610. memcpy(&qry, namelen + (u8_t *) (hdr + 1), sizeof(qry));
  611. u16_t qry_type = ntohs(qry.type);
  612. /* MDNS_DS_DOES_NAME_CHECK */
  613. /* Check if the name in the "question" part match with the name of the MDNS DS service. */
  614. if (mdns_compare_name((unsigned char *) DNS_SD_SERVICE,
  615. (unsigned char *) mdns_payload + SIZEOF_DNS_HDR) == 0) {
  616. if (qry_type == DNS_RRTYPE_PTR || qry_type == DNS_RRTYPE_ANY) {
  617. mdns_send_service_type(i, addr, port);
  618. }
  619. } else if (mdns_compare_name((unsigned char *) service_name_with_suffix,
  620. (unsigned char *) mdns_payload + SIZEOF_DNS_HDR) == 0) {
  621. if (qry_type == DNS_RRTYPE_PTR || qry_type == DNS_RRTYPE_ANY) {
  622. mdns_send_service(info, i, addr, port);
  623. }
  624. } else {
  625. char tmpBuf[PUCK_DATASHEET_SIZE + PUCK_SERVICE_LENGTH];
  626. c_strlcpy(tmpBuf,ms_info->host_name, sizeof(tmpBuf));
  627. c_strlcat(tmpBuf, ".", sizeof(tmpBuf));
  628. c_strlcat(tmpBuf, MDNS_LOCAL, sizeof(tmpBuf));
  629. if (mdns_compare_name((unsigned char *) tmpBuf,
  630. (unsigned char *) mdns_payload + SIZEOF_DNS_HDR) == 0) {
  631. if (qry_type == DNS_RRTYPE_A || qry_type == DNS_RRTYPE_ANY) {
  632. mdns_send_service(info, i, addr, port);
  633. }
  634. } else {
  635. c_strlcpy(tmpBuf,ms_info->host_desc, sizeof(tmpBuf));
  636. c_strlcat(tmpBuf, ".", sizeof(tmpBuf));
  637. c_strlcat(tmpBuf, service_name_with_suffix, sizeof(tmpBuf));
  638. if (mdns_compare_name((unsigned char *) tmpBuf,
  639. (unsigned char *) mdns_payload + SIZEOF_DNS_HDR) == 0) {
  640. if (qry_type == DNS_RRTYPE_TXT || qry_type == DNS_RRTYPE_SRV || qry_type == DNS_RRTYPE_ANY) {
  641. mdns_send_service(info, i, addr, port);
  642. }
  643. }
  644. }
  645. }
  646. }
  647. }
  648. memerr1:
  649. /* free pbuf */
  650. pbuf_free(p);
  651. return;
  652. }
  653. static void
  654. mdns_free_info(struct nodemcu_mdns_info *info) {
  655. os_free((void *) info);
  656. }
  657. /**
  658. * close the UDP pcb .
  659. */
  660. void ICACHE_FLASH_ATTR
  661. nodemcu_mdns_close(void)
  662. {
  663. os_timer_disarm(&mdns_timer);
  664. if (mdns_pcb != NULL) {
  665. udp_remove(mdns_pcb);
  666. }
  667. if (mdns_payload) {
  668. os_free(mdns_payload);
  669. }
  670. mdns_payload = NULL;
  671. mdns_pcb = NULL;
  672. mdns_free_info(ms_info);
  673. ms_info = NULL;
  674. }
  675. static void ICACHE_FLASH_ATTR
  676. mdns_set_servicename(const char *name) {
  677. char tmpBuf[128];
  678. os_sprintf(tmpBuf, "_%s._tcp.local", name);
  679. if (service_name_with_suffix) {
  680. os_free(service_name_with_suffix);
  681. }
  682. service_name_with_suffix = c_strdup(tmpBuf);
  683. }
  684. static u8_t reg_counter;
  685. static void
  686. mdns_reg_handler_restart(void) {
  687. reg_counter = 99;
  688. }
  689. static void ICACHE_FLASH_ATTR
  690. mdns_reg(struct nodemcu_mdns_info *info) {
  691. mdns_send_service(info,0,0,0);
  692. if (reg_counter++ > 10) {
  693. mdns_send_service_type(0,0,0);
  694. reg_counter = 0;
  695. }
  696. }
  697. static struct nodemcu_mdns_info *
  698. mdns_dup_info(const struct nodemcu_mdns_info *info) {
  699. struct nodemcu_mdns_info *result;
  700. // calculate length
  701. int len = sizeof(struct nodemcu_mdns_info);
  702. len += c_strlen(info->host_name) + 1;
  703. len += c_strlen(info->host_desc) + 1;
  704. len += c_strlen(info->service_name) + 1;
  705. int i;
  706. for (i = 0; i < sizeof(info->txt_data) / sizeof(info->txt_data[0]) && info->txt_data[i]; i++) {
  707. len += c_strlen(info->txt_data[i]) + 1;
  708. }
  709. #define COPY_OVER(dest, src, p) len = c_strlen(src) + 1; memcpy(p, src, len); dest = p; p += len
  710. result = (struct nodemcu_mdns_info *) os_zalloc(len);
  711. if (result) {
  712. char *p = (char *) (result + 1);
  713. result->service_port = info->service_port;
  714. COPY_OVER(result->host_name, info->host_name, p);
  715. COPY_OVER(result->host_desc, info->host_desc, p);
  716. COPY_OVER(result->service_name, info->service_name, p);
  717. for (i = 0; i < sizeof(info->txt_data) / sizeof(info->txt_data[0]) && info->txt_data[i]; i++) {
  718. COPY_OVER(result->txt_data[i], info->txt_data[i], p);
  719. }
  720. }
  721. #undef COPY_OVER
  722. return result;
  723. }
  724. /**
  725. * Initialize the resolver: set up the UDP pcb and configure the default server
  726. * (NEW IP).
  727. *
  728. * returns TRUE if it worked, FALSE if it failed.
  729. */
  730. bool ICACHE_FLASH_ATTR
  731. nodemcu_mdns_init(struct nodemcu_mdns_info *info) {
  732. /* initialize default DNS server address */
  733. multicast_addr.addr = DNS_MULTICAST_ADDRESS;
  734. struct ip_info ipconfig;
  735. mdns_free_info(ms_info);
  736. ms_info = mdns_dup_info(info); // Save the passed block. We need all the data forever
  737. if (!ms_info) {
  738. return FALSE;
  739. }
  740. if (mdns_payload) {
  741. os_free(mdns_payload);
  742. }
  743. mdns_payload = (u8_t *) os_malloc(DNS_MSG_SIZE);
  744. if (!mdns_payload) {
  745. MDNS_DBG("Alloc fail\n");
  746. return FALSE;
  747. }
  748. LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n"));
  749. mdns_set_servicename(ms_info->service_name);
  750. // get the host name as instrumentName_serialNumber for MDNS
  751. // set the name of the service, the same as host name
  752. MDNS_DBG("host_name = %s\n", ms_info->host_name);
  753. MDNS_DBG("server_name = %s\n", service_name_with_suffix);
  754. /* initialize mDNS */
  755. mdns_pcb = udp_new();
  756. if (!mdns_pcb) {
  757. return FALSE;
  758. }
  759. /* join to the multicast address 224.0.0.251 */
  760. if(wifi_get_opmode() & 0x01) {
  761. struct netif *sta_netif = (struct netif *)eagle_lwip_getif(0x00);
  762. if (sta_netif && sta_netif->ip_addr.addr && igmp_joingroup(&sta_netif->ip_addr, &multicast_addr) != ERR_OK) {
  763. MDNS_DBG("sta udp_join_multigrup failed!\n");
  764. return FALSE;
  765. };
  766. }
  767. if(wifi_get_opmode() & 0x02) {
  768. struct netif *ap_netif = (struct netif *)eagle_lwip_getif(0x01);
  769. if (ap_netif && ap_netif->ip_addr.addr && igmp_joingroup(&ap_netif->ip_addr, &multicast_addr) != ERR_OK) {
  770. MDNS_DBG("ap udp_join_multigrup failed!\n");
  771. return FALSE;
  772. };
  773. }
  774. register_flag = 1;
  775. /* join to any IP address at the port 5353 */
  776. if (udp_bind(mdns_pcb, IP_ADDR_ANY, DNS_MDNS_PORT) != ERR_OK) {
  777. MDNS_DBG("udp_bind failed!\n");
  778. return FALSE;
  779. };
  780. /*loopback function for the multicast(224.0.0.251) messages received at port 5353*/
  781. udp_recv(mdns_pcb, mdns_recv, ms_info);
  782. mdns_flag = 1;
  783. /*
  784. * Register the name of the instrument
  785. */
  786. //MDNS_DBG("About to start timer\n");
  787. os_timer_disarm(&mdns_timer);
  788. os_timer_setfn(&mdns_timer, (os_timer_func_t *)mdns_reg,ms_info);
  789. os_timer_arm(&mdns_timer, 1000 * 120, 1);
  790. /* kick off the first one right away */
  791. mdns_reg_handler_restart();
  792. mdns_reg(ms_info);
  793. return TRUE;
  794. }
  795. #endif /* LWIP_MDNS */