nodemcu_mdns.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145
  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 <string.h>
  48. #include "nodemcu_mdns.h"
  49. #if 0
  50. #define MDNS_DBG(...) dbg_printf(...)
  51. #else
  52. #define MDNS_DBG(...) do {} while (0)
  53. #endif
  54. #define min(a,b) ((a) < (b) ? (a) : (b))
  55. #define MDNS_NAME_LENGTH 68 //68
  56. #define DNS_RRTYPE_NSEC 47
  57. static const char* service_name_with_suffix = NULL;
  58. #define DNS_SD_SERVICE "_services._dns-sd._udp.local"
  59. #define PUCK_SERVICE_LENGTH 30
  60. #define PUCK_DATASHEET_SIZE 96
  61. #ifdef MEMLEAK_DEBUG
  62. static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
  63. #endif
  64. /** DNS server IP address */
  65. #ifndef DNS_MULTICAST_ADDRESS
  66. #define DNS_MULTICAST_ADDRESS ipaddr_addr("224.0.0.251") /* resolver1.opendns.com */
  67. #endif
  68. /** DNS server IP address */
  69. #ifndef MDNS_LOCAL
  70. #define MDNS_LOCAL "local" /* resolver1.opendns.com */
  71. #endif
  72. /** DNS server port address */
  73. #ifndef DNS_MDNS_PORT
  74. #define DNS_MDNS_PORT 5353
  75. #endif
  76. /** DNS maximum number of retries when asking for a name, before "timeout". */
  77. #ifndef DNS_MAX_RETRIES
  78. #define DNS_MAX_RETRIES 4
  79. #endif
  80. /** DNS resource record max. TTL (one week as default) */
  81. #ifndef DNS_MAX_TTL
  82. #define DNS_MAX_TTL 604800
  83. #endif
  84. /* DNS protocol flags */
  85. #define DNS_FLAG1_RESPONSE 0x84
  86. #define DNS_FLAG1_OPCODE_STATUS 0x10
  87. #define DNS_FLAG1_OPCODE_INVERSE 0x08
  88. #define DNS_FLAG1_OPCODE_STANDARD 0x00
  89. #define DNS_FLAG1_AUTHORATIVE 0x04
  90. #define DNS_FLAG1_TRUNC 0x02
  91. #define DNS_FLAG1_RD 0x01
  92. #define DNS_FLAG2_RA 0x80
  93. #define DNS_FLAG2_ERR_MASK 0x0f
  94. #define DNS_FLAG2_ERR_NONE 0x00
  95. #define DNS_FLAG2_ERR_NAME 0x03
  96. /* DNS protocol states */
  97. #define DNS_STATE_UNUSED 0
  98. #define DNS_STATE_NEW 1
  99. #define DNS_STATE_ASKING 2
  100. #define DNS_STATE_DONE 3
  101. /* MDNS registration type */
  102. #define MDNS_HOSTNAME_REG 0
  103. #define MDNS_SERVICE_REG 1
  104. /* MDNS registration type */
  105. #define MDNS_REG_ANSWER 1
  106. #define MDNS_SD_ANSWER 2
  107. #define MDNS_SERVICE_REG_ANSWER 3
  108. /* MDNS registration time */
  109. #define MDNS_HOST_TIME 120
  110. #define MDNS_SERVICE_TIME 3600
  111. /** MDNS name length with "." at the beginning and end of name*/
  112. #ifndef MDNS_LENGTH_ADD
  113. #define MDNS_LENGTH_ADD 2
  114. #endif
  115. #ifdef MDNS_MAX_NAME_LENGTH
  116. #undef MDNS_MAX_NAME_LENGTH
  117. #endif
  118. #define MDNS_MAX_NAME_LENGTH (256)
  119. PACK_STRUCT_BEGIN
  120. /** DNS message header */
  121. struct mdns_hdr {
  122. PACK_STRUCT_FIELD(u16_t id);
  123. PACK_STRUCT_FIELD(u8_t flags1);
  124. PACK_STRUCT_FIELD(u8_t flags2);
  125. PACK_STRUCT_FIELD(u16_t numquestions);
  126. PACK_STRUCT_FIELD(u16_t numanswers);
  127. PACK_STRUCT_FIELD(u16_t numauthrr);
  128. PACK_STRUCT_FIELD(u16_t numextrarr);
  129. }PACK_STRUCT_STRUCT;
  130. PACK_STRUCT_END
  131. #define SIZEOF_DNS_HDR 12
  132. PACK_STRUCT_BEGIN
  133. /** MDNS query message structure */
  134. struct mdns_query {
  135. /* MDNS query record starts with either a domain name or a pointer
  136. to a name already present somewhere in the packet. */PACK_STRUCT_FIELD(u16_t type);
  137. PACK_STRUCT_FIELD(u16_t class);
  138. }PACK_STRUCT_STRUCT;
  139. PACK_STRUCT_END
  140. #define SIZEOF_DNS_QUERY 4
  141. PACK_STRUCT_BEGIN
  142. /** MDNS answer message structure */
  143. struct mdns_answer {
  144. /* MDNS answer record starts with either a domain name or a pointer
  145. to a name already present somewhere in the packet. */PACK_STRUCT_FIELD(u16_t type);
  146. PACK_STRUCT_FIELD(u16_t class);
  147. PACK_STRUCT_FIELD(u32_t ttl);
  148. PACK_STRUCT_FIELD(u16_t len);
  149. }PACK_STRUCT_STRUCT;
  150. PACK_STRUCT_END
  151. #define SIZEOF_DNS_ANSWER 10
  152. PACK_STRUCT_BEGIN
  153. /** MDNS answer message structure */
  154. struct mdns_a_rr {
  155. PACK_STRUCT_FIELD(u32_t src);
  156. }PACK_STRUCT_STRUCT;
  157. PACK_STRUCT_END
  158. #define SIZEOF_MDNS_A_RR 4
  159. PACK_STRUCT_BEGIN
  160. /** MDNS service registration message structure */
  161. struct mdns_service {
  162. PACK_STRUCT_FIELD(u16_t prior);
  163. PACK_STRUCT_FIELD(u16_t weight);
  164. PACK_STRUCT_FIELD(u16_t port);
  165. }PACK_STRUCT_STRUCT;
  166. PACK_STRUCT_END
  167. #define SIZEOF_MDNS_SERVICE 6
  168. static os_timer_t mdns_timer;
  169. /* forward declarations */
  170. static void mdns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p,
  171. struct ip_addr *addr, u16_t port);
  172. /*-----------------------------------------------------------------------------
  173. * Globales
  174. *----------------------------------------------------------------------------*/
  175. /* MDNS variables */
  176. //static char puck_datasheet[PUCK_DATASHEET_SIZE];
  177. static struct udp_pcb *mdns_pcb = NULL;
  178. static struct nodemcu_mdns_info * ms_info = NULL;
  179. static struct ip_addr multicast_addr;
  180. static uint8 register_flag = 0;
  181. static uint8 mdns_flag = 0;
  182. static u8_t *mdns_payload;
  183. /**
  184. * Compare the "dotted" name "query" with the encoded name "response"
  185. * to make sure an answer from the DNS server matches the current mdns_table
  186. * entry (otherwise, answers might arrive late for hostname not on the list
  187. * any more).
  188. *
  189. * @param query hostname (not encoded) from the mdns_table
  190. * @param response encoded hostname in the DNS response
  191. * @return 0: names equal; 1: names differ
  192. */
  193. static u8_t ICACHE_FLASH_ATTR
  194. mdns_compare_name(unsigned char *query, unsigned char *response, unsigned char *pktbase) {
  195. unsigned char n;
  196. do {
  197. n = *response++;
  198. /** @see RFC 1035 - 4.1.4. Message compression */
  199. if ((n & 0xc0) == 0xc0) {
  200. n = ((n << 8) + *response) & 0x3fff;
  201. if (n < response - pktbase) {
  202. response = pktbase + n;
  203. } else {
  204. return 1;
  205. }
  206. } else {
  207. /* Not compressed name */
  208. while (n > 0) {
  209. char q = *query;
  210. if (q >= 'A' && q <= 'Z') {
  211. q = q + 'a' - 'A';
  212. }
  213. char r = *response;
  214. if (r >= 'A' && r <= 'Z') {
  215. r = r + 'a' - 'A';
  216. }
  217. if (q != r) {
  218. return 1;
  219. }
  220. ++response;
  221. ++query;
  222. --n;
  223. };
  224. ++query;
  225. }
  226. } while (*response != 0);
  227. return 0;
  228. }
  229. static int
  230. mdns_namelen(u8_t *p, unsigned int maxlen) {
  231. u8_t *orig = p;
  232. while (*p && *p <= 63) {
  233. if (p - orig > maxlen) {
  234. return -1;
  235. }
  236. p += *p + 1;
  237. }
  238. if (*p >= 0xc0) {
  239. p += 2; // advance over the two byte pointer
  240. } else {
  241. p++; // advance over the final 0
  242. }
  243. if (p - orig > maxlen) {
  244. return -1;
  245. }
  246. return p - orig;
  247. }
  248. /* Copy an unencoded name into an encoded name */
  249. static unsigned char *copy_and_encode_name(unsigned char *ptr, const char *name) {
  250. while (*name) {
  251. const char *p = name;
  252. while (*p != '.' && *p) {
  253. p++;
  254. }
  255. *ptr++ = p - name;
  256. memcpy(ptr, name, p - name);
  257. ptr += p - name;
  258. if (!*p) {
  259. break;
  260. }
  261. name = p + 1;
  262. }
  263. *ptr++ = 0;
  264. return ptr;
  265. }
  266. static err_t send_packet(struct pbuf *p, struct ip_addr *dst_addr, u16_t dst_port, u8_t *addr_ptr) {
  267. err_t err;
  268. /* send dns packet */
  269. struct netif *sta_netif = (struct netif *)eagle_lwip_getif(0x00);
  270. struct netif *ap_netif = (struct netif *)eagle_lwip_getif(0x01);
  271. if (addr_ptr) {
  272. if (wifi_get_opmode() == 0x02) {
  273. if (!ap_netif) {
  274. return;
  275. }
  276. memcpy(addr_ptr, &ap_netif->ip_addr, sizeof(ap_netif->ip_addr));
  277. } else {
  278. if (!sta_netif) {
  279. return;
  280. }
  281. memcpy(addr_ptr, &sta_netif->ip_addr, sizeof(sta_netif->ip_addr));
  282. }
  283. }
  284. if (dst_addr) {
  285. err = udp_sendto(mdns_pcb, p, dst_addr, dst_port);
  286. } else {
  287. err = udp_sendto(mdns_pcb, p, &multicast_addr, DNS_MDNS_PORT);
  288. if(wifi_get_opmode() == 0x03 && wifi_get_broadcast_if() == 0x03 &&\
  289. sta_netif != NULL && ap_netif != NULL) {
  290. if(netif_is_up(sta_netif) && netif_is_up(ap_netif)) {
  291. netif_set_default(sta_netif);
  292. if (addr_ptr) {
  293. memcpy(addr_ptr, &ap_netif->ip_addr, sizeof(ap_netif->ip_addr));
  294. }
  295. err = udp_sendto(mdns_pcb, p, &multicast_addr, DNS_MDNS_PORT);
  296. netif_set_default(ap_netif);
  297. }
  298. }
  299. }
  300. /* free pbuf */
  301. pbuf_free(p);
  302. return err;
  303. }
  304. /**
  305. * Send a mDNS packet for the service type
  306. *
  307. * @param id transaction ID in the DNS query packet
  308. * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise
  309. */
  310. static err_t ICACHE_FLASH_ATTR
  311. mdns_send_service_type(u16_t id, struct ip_addr *dst_addr, u16_t dst_port) {
  312. err_t err;
  313. struct mdns_hdr *hdr;
  314. struct mdns_answer ans;
  315. struct mdns_a_rr a_rr;
  316. struct mdns_service serv;
  317. struct pbuf *p ,*p_sta;
  318. char *query, *nptr;
  319. const char *pHostname;
  320. struct netif * sta_netif = NULL;
  321. struct netif * ap_netif = NULL;
  322. int max_ttl = dst_addr ? 10 : 7200;
  323. char tmpBuf[PUCK_DATASHEET_SIZE + PUCK_SERVICE_LENGTH];
  324. u8_t n;
  325. u16_t length = 0;
  326. /* if here, we have either a new query or a retry on a previous query to process */
  327. p = pbuf_alloc(PBUF_TRANSPORT,
  328. SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM);
  329. if (p != NULL) {
  330. LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
  331. /* fill dns header */
  332. hdr = (struct mdns_hdr*) p->payload;
  333. os_memset(hdr, 0, SIZEOF_DNS_HDR);
  334. hdr->id = htons(id);
  335. hdr->flags1 = DNS_FLAG1_RESPONSE;
  336. pHostname = DNS_SD_SERVICE;
  337. hdr->numanswers = htons(1);
  338. query = (char*) hdr + SIZEOF_DNS_HDR;
  339. --pHostname;
  340. /* convert hostname into suitable query format. */
  341. do {
  342. ++pHostname;
  343. nptr = query;
  344. ++query;
  345. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  346. *query = *pHostname;
  347. ++query;
  348. ++n;
  349. }
  350. *nptr = n;
  351. } while (*pHostname != 0);
  352. *query++ = '\0';
  353. /* fill dns query */
  354. ans.type = htons(DNS_RRTYPE_PTR);
  355. ans.class = htons(DNS_RRCLASS_IN);
  356. ans.ttl = htonl(min(max_ttl, 3600));
  357. ans.len = htons(os_strlen(service_name_with_suffix) + 1 +1 );
  358. length = 0;
  359. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  360. /* resize the query */
  361. query = query + SIZEOF_DNS_ANSWER;
  362. pHostname = service_name_with_suffix;
  363. --pHostname;
  364. /* convert hostname into suitable query format. */
  365. do {
  366. ++pHostname;
  367. nptr = query;
  368. ++query;
  369. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  370. *query = *pHostname;
  371. ++query;
  372. ++n;
  373. }
  374. *nptr = n;
  375. } while (*pHostname != 0);
  376. *query++ = '\0';
  377. /* resize pbuf to the exact dns query */
  378. pbuf_realloc(p, (query + length) - ((char*) (p->payload)));
  379. err = send_packet(p, dst_addr, dst_port, 0);
  380. } else {
  381. err = ERR_MEM;
  382. }
  383. return err;
  384. }
  385. /**
  386. * Send a mDNS service answer packet.
  387. *
  388. * @param name service name to query
  389. * @param id transaction ID in the DNS query packet
  390. * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise
  391. */
  392. static err_t ICACHE_FLASH_ATTR
  393. mdns_send_service(struct nodemcu_mdns_info *info, u16_t id, struct ip_addr *dst_addr, u16_t dst_port) {
  394. err_t err;
  395. struct mdns_hdr *hdr;
  396. struct mdns_answer ans;
  397. struct mdns_service serv;
  398. struct mdns_a_rr a_rr;
  399. struct pbuf *p ,*p_sta;
  400. char *query, *nptr;
  401. char *query_end;
  402. const char *pHostname;
  403. const char *name = info->host_name;
  404. int max_ttl = dst_addr ? 10 : 7200;
  405. u8_t n;
  406. u8_t i = 0;
  407. u16_t length = 0;
  408. u8_t addr1 = 12, addr2 = 12;
  409. struct netif * sta_netif = NULL;
  410. struct netif * ap_netif = NULL;
  411. char tmpBuf[PUCK_DATASHEET_SIZE + PUCK_SERVICE_LENGTH];
  412. u16_t dns_class = dst_addr ? DNS_RRCLASS_IN : DNS_RRCLASS_FLUSH_IN;
  413. /* if here, we have either a new query or a retry on a previous query to process */
  414. p = pbuf_alloc(PBUF_TRANSPORT,
  415. SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM);
  416. if (p != NULL) {
  417. LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
  418. /* fill dns header */
  419. hdr = (struct mdns_hdr*) p->payload;
  420. os_memset(hdr, 0, SIZEOF_DNS_HDR);
  421. hdr->id = htons(id);
  422. hdr->flags1 = DNS_FLAG1_RESPONSE;
  423. hdr->numanswers = htons(4);
  424. hdr->numextrarr = htons(1);
  425. query = (char*) hdr + SIZEOF_DNS_HDR;
  426. query_end = (char *) p->payload + p->tot_len;
  427. strlcpy(tmpBuf, service_name_with_suffix, sizeof(tmpBuf));
  428. pHostname = tmpBuf;
  429. --pHostname;
  430. /* convert hostname into suitable query format. */
  431. do {
  432. ++pHostname;
  433. nptr = query;
  434. ++query;
  435. ++addr1;
  436. ++addr2;
  437. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  438. *query = *pHostname;
  439. ++query;
  440. ++addr1;
  441. ++addr2;
  442. ++n;
  443. }
  444. *nptr = n;
  445. } while (*pHostname != 0);
  446. *query++ = '\0';
  447. length = sizeof(MDNS_LOCAL);
  448. addr1 -= length;
  449. length = os_strlen(service_name_with_suffix) + 1;
  450. addr2 -= length;
  451. ans.type = htons(DNS_RRTYPE_PTR);
  452. ans.class = htons(DNS_RRCLASS_IN);
  453. ans.ttl = htonl(min(max_ttl, 300));
  454. length = os_strlen(ms_info->host_desc) + MDNS_LENGTH_ADD + 1;
  455. ans.len = htons(length);
  456. length = 0;
  457. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  458. /* resize the query */
  459. query = query + SIZEOF_DNS_ANSWER;
  460. int name_offset = query - (const char *) hdr;
  461. pHostname = ms_info->host_desc;
  462. --pHostname;
  463. /* convert hostname into suitable query format. */
  464. do {
  465. ++pHostname;
  466. nptr = query;
  467. ++query;
  468. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  469. *query = *pHostname;
  470. ++query;
  471. ++n;
  472. }
  473. *nptr = n;
  474. } while (*pHostname != 0);
  475. *query++ = DNS_OFFSET_FLAG;
  476. *query++ = DNS_DEFAULT_OFFSET;
  477. *query++ = 0xc0 + (name_offset >> 8);
  478. *query++ = name_offset & 0xff;
  479. /* fill the answer */
  480. ans.type = htons(DNS_RRTYPE_TXT);
  481. ans.class = htons(dns_class);
  482. ans.ttl = htonl(min(max_ttl, 300));
  483. // length = os_strlen(TXT_DATA) + MDNS_LENGTH_ADD + 1;
  484. const char *attributes[12];
  485. int attr_count = 0;
  486. for(i = 0; i < 10 && (info->txt_data[i] != NULL); i++) {
  487. length += os_strlen(info->txt_data[i]);
  488. length++;
  489. attributes[attr_count++] = info->txt_data[i];
  490. }
  491. //MDNS_DBG("Found %d user attributes\n", i);
  492. static const char *defaults[] = { "platform=nodemcu", NULL };
  493. for(i = 0; defaults[i] != NULL; i++) {
  494. // See if this is a duplicate
  495. int j;
  496. int len = strchr(defaults[i], '=') + 1 - defaults[i];
  497. for (j = 0; j < attr_count; j++) {
  498. if (strncmp(attributes[j], defaults[i], len) == 0) {
  499. break;
  500. }
  501. }
  502. if (j == attr_count) {
  503. length += os_strlen(defaults[i]);
  504. length++;
  505. attributes[attr_count++] = defaults[i];
  506. }
  507. }
  508. //MDNS_DBG("Found %d total attributes\n", attr_count);
  509. ans.len = htons(length);
  510. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  511. query = query + SIZEOF_DNS_ANSWER;
  512. // Check enough space in the packet
  513. const char *end_of_packet = query + length + 2 + SIZEOF_DNS_ANSWER + SIZEOF_MDNS_SERVICE +
  514. os_strlen(ms_info->host_name) + 7 + 1 + 2 + SIZEOF_DNS_ANSWER + SIZEOF_MDNS_A_RR +
  515. 2 + SIZEOF_DNS_ANSWER + 5;
  516. if (query_end <= end_of_packet) {
  517. MDNS_DBG("Too much data to send\n");
  518. pbuf_free(p);
  519. return ERR_MEM;
  520. }
  521. //MDNS_DBG("Query=%x, query_end=%x, end_ofpacket=%x, length=%x\n", query, query_end, end_of_packet, length);
  522. i = 0;
  523. while(attributes[i] != NULL && i < attr_count) {
  524. pHostname = attributes[i];
  525. --pHostname;
  526. /* convert hostname into suitable query format. */
  527. do {
  528. ++pHostname;
  529. nptr = query;
  530. ++query;
  531. for (n = 0; *pHostname != 0; ++pHostname) {
  532. *query = *pHostname;
  533. ++query;
  534. ++n;
  535. }
  536. *nptr = n;
  537. } while (*pHostname != 0);
  538. i++;
  539. }
  540. // *query++ = '\0';
  541. // Increment by length
  542. *query++ = 0xc0 + (name_offset >> 8);
  543. *query++ = name_offset & 0xff;
  544. // Increment by 2
  545. ans.type = htons(DNS_RRTYPE_SRV);
  546. ans.class = htons(dns_class);
  547. ans.ttl = htonl(min(max_ttl, 300));
  548. strlcpy(tmpBuf,ms_info->host_name, sizeof(tmpBuf));
  549. strlcat(tmpBuf, ".", sizeof(tmpBuf));
  550. strlcat(tmpBuf, MDNS_LOCAL, sizeof(tmpBuf));
  551. length = os_strlen(tmpBuf) + MDNS_LENGTH_ADD;
  552. ans.len = htons(SIZEOF_MDNS_SERVICE + length);
  553. length = 0;
  554. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  555. /* resize the query */
  556. query = query + SIZEOF_DNS_ANSWER;
  557. serv.prior = htons(0);
  558. serv.weight = htons(0);
  559. serv.port = htons(ms_info->service_port);
  560. MEMCPY( query, &serv, SIZEOF_MDNS_SERVICE);
  561. /* resize the query */
  562. query = query + SIZEOF_MDNS_SERVICE;
  563. int hostname_offset = query - (const char *) hdr;
  564. pHostname = tmpBuf;
  565. --pHostname;
  566. do {
  567. ++pHostname;
  568. nptr = query;
  569. ++query;
  570. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  571. *query = *pHostname;
  572. ++query;
  573. ++n;
  574. }
  575. *nptr = n;
  576. } while (*pHostname != 0);
  577. *query++ = '\0';
  578. // increment by strlen(service_name) + 1 + 7 + sizeof_dns_answer + sizeof_mdns_service
  579. *query++ = 0xc0 + (hostname_offset >> 8);
  580. *query++ = hostname_offset & 0xff;
  581. ans.type = htons(DNS_RRTYPE_A);
  582. ans.class = htons(dns_class);
  583. ans.ttl = htonl(min(max_ttl, 300));
  584. ans.len = htons(DNS_IP_ADDR_LEN);
  585. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  586. /* resize the query */
  587. query = query + SIZEOF_DNS_ANSWER;
  588. // increment by strlen(service_name) + 1 + 7 + sizeof_dns_answer
  589. /* fill the payload of the mDNS message */
  590. /* set the local IP address */
  591. a_rr.src = 0;
  592. MEMCPY( query, &a_rr, SIZEOF_MDNS_A_RR);
  593. u8_t *addr_ptr = query + ((char *) &a_rr.src - (char *) &a_rr);
  594. /* resize the query */
  595. query = query + SIZEOF_MDNS_A_RR;
  596. // Append the NSEC record that says we only have an A record
  597. *query++ = 0xc0 + (hostname_offset >> 8);
  598. *query++ = hostname_offset & 0xff;
  599. ans.type = htons(DNS_RRTYPE_NSEC);
  600. ans.class = htons(dns_class);
  601. ans.ttl = htonl(min(max_ttl, 300));
  602. ans.len = htons(5);
  603. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  604. query = query + SIZEOF_DNS_ANSWER;
  605. *query++ = 0xc0 + (hostname_offset >> 8);
  606. *query++ = hostname_offset & 0xff;
  607. *query++ = 0;
  608. *query++ = 1;
  609. *query++ = 0x40;
  610. //MDNS_DBG("Final ptr=%x\n", query);
  611. // increment by sizeof_mdns_a_rr
  612. /* set the name of the authority field.
  613. * The same name as the Query using the offset address*/
  614. /* resize pbuf to the exact dns query */
  615. pbuf_realloc(p, (query) - ((char*) (p->payload)));
  616. err = send_packet(p, dst_addr, dst_port, addr_ptr);
  617. if (!dst_addr) {
  618. // this is being sent multicast...
  619. // so reset the timer
  620. os_timer_disarm(&mdns_timer);
  621. os_timer_arm(&mdns_timer, 1000 * 280, 1);
  622. }
  623. } else {
  624. MDNS_DBG("ERR_MEM \n");
  625. err = ERR_MEM;
  626. }
  627. return err;
  628. }
  629. static char *append_nsec_record(char *query, u32_t actual_rr, int max_ttl) {
  630. struct mdns_answer ans;
  631. ans.type = htons(DNS_RRTYPE_NSEC);
  632. ans.class = htons(DNS_RRCLASS_IN);
  633. ans.ttl = htonl(min(max_ttl, 300));
  634. ans.len = htons(9);
  635. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  636. char *rr_len = query + ((char *) &ans.len - (char *) &ans) + 1;
  637. query = query + SIZEOF_DNS_ANSWER;
  638. *query++ = 0xc0;
  639. *query++ = sizeof(struct mdns_hdr);
  640. *query++ = 0;
  641. char *bm_len = query;
  642. *query++ = 5;
  643. char *abase = query;
  644. *query++ = 0;
  645. *query++ = 0;
  646. *query++ = 0;
  647. *query++ = 0;
  648. *query++ = 0;
  649. while (actual_rr > 0) {
  650. int v = actual_rr & 255;
  651. if (v < 5 * 8) {
  652. abase[v >> 3] |= 0x80 >> (v & 7);
  653. actual_rr = actual_rr >> 8;
  654. }
  655. }
  656. while (query[-1] == 0) {
  657. query--;
  658. (*bm_len)--;
  659. (*rr_len)--;
  660. }
  661. return query;
  662. }
  663. /**
  664. * This sends an empty response -- this is used when we doin't have an RR to send
  665. * but the name exists
  666. */
  667. static void
  668. mdns_send_no_rr(struct mdns_hdr *req, const char *name, u32_t actual_rr, struct ip_addr *dst_addr, u16_t dst_port) {
  669. int max_ttl = dst_addr ? 10 : 7200;
  670. struct pbuf *p;
  671. p = pbuf_alloc(PBUF_TRANSPORT,
  672. SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM);
  673. if (p != NULL) {
  674. LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
  675. /* fill dns header */
  676. struct mdns_hdr *hdr = (struct mdns_hdr*) p->payload;
  677. os_memset(hdr, 0, SIZEOF_DNS_HDR);
  678. hdr->id = req->id;
  679. hdr->flags1 = DNS_FLAG1_RESPONSE;
  680. hdr->numextrarr = htons(1);
  681. char *query = (char*) hdr + SIZEOF_DNS_HDR;
  682. char *query_end = (char *) p->payload + p->tot_len;
  683. // Now copy over the dns name
  684. int len = strlen(name);
  685. if (query_end - query >= len + SIZEOF_DNS_QUERY + 15) {
  686. query = copy_and_encode_name((char *) (hdr + 1), name);
  687. query = append_nsec_record(query, actual_rr, max_ttl);
  688. // Set the length code correctly
  689. pbuf_realloc(p, query - ((char*) (p->payload)));
  690. send_packet(p, dst_addr, dst_port, NULL);
  691. }
  692. }
  693. }
  694. /**
  695. * This sends a single A record and the NSEC record as additional
  696. */
  697. static void
  698. mdns_send_a_rr(struct mdns_hdr *req, const char *name, struct ip_addr *dst_addr, u16_t dst_port) {
  699. int max_ttl = dst_addr ? 10 : 7200;
  700. struct pbuf *p;
  701. p = pbuf_alloc(PBUF_TRANSPORT,
  702. SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM);
  703. if (p != NULL) {
  704. LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
  705. /* fill dns header */
  706. struct mdns_hdr *hdr = (struct mdns_hdr*) p->payload;
  707. os_memset(hdr, 0, SIZEOF_DNS_HDR);
  708. hdr->id = req->id;
  709. hdr->flags1 = DNS_FLAG1_RESPONSE;
  710. hdr->numanswers = htons(1);
  711. hdr->numextrarr = htons(1);
  712. char *query = (char*) hdr + SIZEOF_DNS_HDR;
  713. char *query_end = (char *) p->payload + p->tot_len;
  714. // Now copy over the dns name
  715. int len = strlen(name) + 1;
  716. if (query_end - query >= len + SIZEOF_DNS_QUERY + 4 + 2 + 4 + 15) {
  717. query = copy_and_encode_name((char *) (hdr + 1), name);
  718. struct mdns_answer ans;
  719. ans.type = htons(DNS_RRTYPE_A);
  720. ans.class = htons(DNS_RRCLASS_IN);
  721. ans.ttl = htonl(min(max_ttl, 300));
  722. ans.len = htons(4);
  723. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  724. query = query + SIZEOF_DNS_ANSWER;
  725. char *addr_ptr = query;
  726. query += 4;
  727. // Now add the NSEC record
  728. *query++ = 0xc0;
  729. *query++ = sizeof(*hdr);
  730. query = append_nsec_record(query, DNS_RRTYPE_A, max_ttl);
  731. // Set the length code correctly
  732. pbuf_realloc(p, query - ((char*) (p->payload)));
  733. send_packet(p, dst_addr, dst_port, addr_ptr);
  734. }
  735. }
  736. }
  737. /**
  738. * Receive input function for DNS response packets arriving for the dns UDP pcb.
  739. *
  740. * @params see udp.h
  741. */
  742. static void ICACHE_FLASH_ATTR
  743. mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr,
  744. u16_t port) {
  745. u16_t i;
  746. struct mdns_hdr *hdr;
  747. u8_t nquestions;
  748. LWIP_UNUSED_ARG(arg);
  749. LWIP_UNUSED_ARG(pcb);
  750. struct nodemcu_mdns_info *info = (struct nodemcu_mdns_info *)arg;
  751. /* is the dns message too big ? */
  752. if (p->tot_len > DNS_MSG_SIZE) {
  753. LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n"));
  754. /* free pbuf and return */
  755. goto memerr1;
  756. }
  757. /* is the dns message big enough ? */
  758. if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) {
  759. LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
  760. /* free pbuf and return */
  761. goto memerr1;
  762. }
  763. /* copy dns payload inside static buffer for processing */
  764. if (pbuf_copy_partial(p, mdns_payload, p->tot_len, 0) == p->tot_len) {
  765. /* The ID in the DNS header should be our entry into the name table. */
  766. hdr = (struct mdns_hdr*) mdns_payload;
  767. i = htons(hdr->id);
  768. nquestions = htons(hdr->numquestions);
  769. //nanswers = htons(hdr->numanswers);
  770. /* if we have a question send an answer if necessary */
  771. u8_t qno;
  772. u8_t *qptr = (u8_t *) (hdr + 1);
  773. u8_t *qend = mdns_payload + p->tot_len;
  774. for (qno = 0; qno < nquestions && qptr < qend; qno++) {
  775. char tmpBuf[PUCK_DATASHEET_SIZE + PUCK_SERVICE_LENGTH];
  776. struct mdns_query qry;
  777. int namelen = mdns_namelen(qptr, qend - qptr);
  778. memcpy(&qry, namelen + qptr, sizeof(qry));
  779. u16_t qry_type = ntohs(qry.type);
  780. if (port == 5353 && (ntohs(qry.class) & 0x8000) == 0) {
  781. addr = NULL;
  782. }
  783. u32_t actual_rr = 0;
  784. const char *no_rr_name = NULL;
  785. /* MDNS_DS_DOES_NAME_CHECK */
  786. /* Check if the name in the "question" part match with the name of the MDNS DS service. */
  787. if (mdns_compare_name((unsigned char *) DNS_SD_SERVICE,
  788. (unsigned char *) qptr, (unsigned char *) hdr) == 0) {
  789. if (qry_type == DNS_RRTYPE_PTR || qry_type == DNS_RRTYPE_ANY) {
  790. mdns_send_service_type(i, addr, port);
  791. } else {
  792. no_rr_name = DNS_SD_SERVICE;
  793. actual_rr = DNS_RRTYPE_PTR;
  794. }
  795. } else if (mdns_compare_name((unsigned char *) service_name_with_suffix,
  796. (unsigned char *) qptr, (unsigned char *) hdr) == 0) {
  797. if (qry_type == DNS_RRTYPE_PTR || qry_type == DNS_RRTYPE_ANY) {
  798. mdns_send_service(info, i, addr, port);
  799. } else {
  800. no_rr_name = service_name_with_suffix;
  801. actual_rr = DNS_RRTYPE_PTR;
  802. }
  803. } else {
  804. strlcpy(tmpBuf,ms_info->host_name, sizeof(tmpBuf));
  805. strlcat(tmpBuf, ".", sizeof(tmpBuf));
  806. strlcat(tmpBuf, MDNS_LOCAL, sizeof(tmpBuf));
  807. no_rr_name = tmpBuf;
  808. if (mdns_compare_name((unsigned char *) tmpBuf,
  809. (unsigned char *) qptr, (unsigned char *) hdr) == 0) {
  810. if (qry_type == DNS_RRTYPE_A || qry_type == DNS_RRTYPE_ANY) {
  811. mdns_send_a_rr(hdr, tmpBuf, addr, port);
  812. } else {
  813. actual_rr = DNS_RRTYPE_A;
  814. }
  815. } else {
  816. strlcpy(tmpBuf,ms_info->host_desc, sizeof(tmpBuf));
  817. strlcat(tmpBuf, ".", sizeof(tmpBuf));
  818. strlcat(tmpBuf, service_name_with_suffix, sizeof(tmpBuf));
  819. if (mdns_compare_name((unsigned char *) tmpBuf,
  820. (unsigned char *) qptr, (unsigned char *) hdr) == 0) {
  821. if (qry_type == DNS_RRTYPE_TXT || qry_type == DNS_RRTYPE_SRV || qry_type == DNS_RRTYPE_ANY) {
  822. mdns_send_service(info, i, addr, port);
  823. } else {
  824. actual_rr = (DNS_RRTYPE_TXT << 8) + DNS_RRTYPE_SRV;
  825. }
  826. }
  827. }
  828. }
  829. if (actual_rr) {
  830. mdns_send_no_rr(hdr, no_rr_name, actual_rr, addr, port);
  831. }
  832. qptr += namelen + sizeof(qry); // Now points to next question
  833. }
  834. }
  835. memerr1:
  836. /* free pbuf */
  837. pbuf_free(p);
  838. return;
  839. }
  840. static void
  841. mdns_free_info(struct nodemcu_mdns_info *info) {
  842. os_free((void *) info);
  843. }
  844. /**
  845. * close the UDP pcb .
  846. */
  847. void ICACHE_FLASH_ATTR
  848. nodemcu_mdns_close(void)
  849. {
  850. os_timer_disarm(&mdns_timer);
  851. if (mdns_pcb != NULL) {
  852. udp_remove(mdns_pcb);
  853. }
  854. if (mdns_payload) {
  855. os_free(mdns_payload);
  856. }
  857. mdns_payload = NULL;
  858. mdns_pcb = NULL;
  859. mdns_free_info(ms_info);
  860. ms_info = NULL;
  861. }
  862. static void ICACHE_FLASH_ATTR
  863. mdns_set_servicename(const char *name) {
  864. char tmpBuf[128];
  865. os_sprintf(tmpBuf, "_%s._tcp.local", name);
  866. if (service_name_with_suffix) {
  867. os_free((void *) service_name_with_suffix);
  868. }
  869. service_name_with_suffix = strdup(tmpBuf);
  870. }
  871. static u8_t reg_counter;
  872. static void
  873. mdns_reg_handler_restart(void) {
  874. reg_counter = 99;
  875. }
  876. static void ICACHE_FLASH_ATTR
  877. mdns_reg(struct nodemcu_mdns_info *info) {
  878. mdns_send_service(info,0,0,0);
  879. if (reg_counter++ > 10) {
  880. mdns_send_service_type(0,0,0);
  881. reg_counter = 0;
  882. }
  883. }
  884. static struct nodemcu_mdns_info *
  885. mdns_dup_info(const struct nodemcu_mdns_info *info) {
  886. struct nodemcu_mdns_info *result;
  887. // calculate length
  888. int len = sizeof(struct nodemcu_mdns_info);
  889. len += strlen(info->host_name) + 1;
  890. len += strlen(info->host_desc) + 1;
  891. len += strlen(info->service_name) + 1;
  892. int i;
  893. for (i = 0; i < sizeof(info->txt_data) / sizeof(info->txt_data[0]) && info->txt_data[i]; i++) {
  894. len += strlen(info->txt_data[i]) + 1;
  895. }
  896. #define COPY_OVER(dest, src, p) len = strlen(src) + 1; memcpy(p, src, len); dest = p; p += len
  897. result = (struct nodemcu_mdns_info *) os_zalloc(len);
  898. if (result) {
  899. char *p = (char *) (result + 1);
  900. result->service_port = info->service_port;
  901. COPY_OVER(result->host_name, info->host_name, p);
  902. COPY_OVER(result->host_desc, info->host_desc, p);
  903. COPY_OVER(result->service_name, info->service_name, p);
  904. for (i = 0; i < sizeof(info->txt_data) / sizeof(info->txt_data[0]) && info->txt_data[i]; i++) {
  905. COPY_OVER(result->txt_data[i], info->txt_data[i], p);
  906. }
  907. }
  908. #undef COPY_OVER
  909. return result;
  910. }
  911. #include "pm/swtimer.h"
  912. /**
  913. * Initialize the resolver: set up the UDP pcb and configure the default server
  914. * (NEW IP).
  915. *
  916. * returns TRUE if it worked, FALSE if it failed.
  917. */
  918. bool ICACHE_FLASH_ATTR
  919. nodemcu_mdns_init(struct nodemcu_mdns_info *info) {
  920. /* initialize default DNS server address */
  921. multicast_addr.addr = DNS_MULTICAST_ADDRESS;
  922. struct ip_info ipconfig;
  923. mdns_free_info(ms_info);
  924. ms_info = mdns_dup_info(info); // Save the passed block. We need all the data forever
  925. if (!ms_info) {
  926. return FALSE;
  927. }
  928. if (mdns_payload) {
  929. os_free(mdns_payload);
  930. }
  931. mdns_payload = (u8_t *) os_malloc(DNS_MSG_SIZE);
  932. if (!mdns_payload) {
  933. MDNS_DBG("Alloc fail\n");
  934. return FALSE;
  935. }
  936. LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n"));
  937. mdns_set_servicename(ms_info->service_name);
  938. // get the host name as instrumentName_serialNumber for MDNS
  939. // set the name of the service, the same as host name
  940. MDNS_DBG("host_name = %s\n", ms_info->host_name);
  941. MDNS_DBG("server_name = %s\n", service_name_with_suffix);
  942. /* initialize mDNS */
  943. mdns_pcb = udp_new();
  944. if (!mdns_pcb) {
  945. return FALSE;
  946. }
  947. /* join to the multicast address 224.0.0.251 */
  948. if(wifi_get_opmode() & 0x01) {
  949. struct netif *sta_netif = (struct netif *)eagle_lwip_getif(0x00);
  950. if (sta_netif && sta_netif->ip_addr.addr && igmp_joingroup(&sta_netif->ip_addr, &multicast_addr) != ERR_OK) {
  951. MDNS_DBG("sta udp_join_multigrup failed!\n");
  952. return FALSE;
  953. };
  954. }
  955. if(wifi_get_opmode() & 0x02) {
  956. struct netif *ap_netif = (struct netif *)eagle_lwip_getif(0x01);
  957. if (ap_netif && ap_netif->ip_addr.addr && igmp_joingroup(&ap_netif->ip_addr, &multicast_addr) != ERR_OK) {
  958. MDNS_DBG("ap udp_join_multigrup failed!\n");
  959. return FALSE;
  960. };
  961. }
  962. register_flag = 1;
  963. /* join to any IP address at the port 5353 */
  964. if (udp_bind(mdns_pcb, IP_ADDR_ANY, DNS_MDNS_PORT) != ERR_OK) {
  965. MDNS_DBG("udp_bind failed!\n");
  966. return FALSE;
  967. };
  968. /*loopback function for the multicast(224.0.0.251) messages received at port 5353*/
  969. udp_recv(mdns_pcb, mdns_recv, ms_info);
  970. mdns_flag = 1;
  971. /*
  972. * Register the name of the instrument
  973. */
  974. //MDNS_DBG("About to start timer\n");
  975. os_timer_disarm(&mdns_timer);
  976. os_timer_setfn(&mdns_timer, (os_timer_func_t *)mdns_reg,ms_info);
  977. SWTIMER_REG_CB(mdns_reg, SWTIMER_RESUME);
  978. //the function mdns_reg registers the mdns device on the network
  979. //My guess: Since wifi connection is restored after waking from light_sleep, the related timer would have no problem resuming it's normal function.
  980. os_timer_arm(&mdns_timer, 1000 * 280, 1);
  981. /* kick off the first one right away */
  982. mdns_reg_handler_restart();
  983. mdns_reg(ms_info);
  984. return TRUE;
  985. }
  986. #endif /* LWIP_MDNS */