mdns.c 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967
  1. // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. #include "mdns.h"
  14. #include <string.h>
  15. #ifndef MDNS_TEST_MODE
  16. #include "sdkconfig.h"
  17. #include "freertos/FreeRTOS.h"
  18. #include "freertos/queue.h"
  19. #include "freertos/semphr.h"
  20. #include "lwip/ip_addr.h"
  21. #include "lwip/pbuf.h"
  22. #include "lwip/igmp.h"
  23. #include "lwip/udp.h"
  24. #include "esp_wifi.h"
  25. #endif
  26. #define MDNS_FLAGS_AUTHORITATIVE 0x8400
  27. #define MDNS_NAME_REF 0xC000
  28. #define MDNS_TYPE_AAAA 0x001C
  29. #define MDNS_TYPE_A 0x0001
  30. #define MDNS_TYPE_PTR 0x000C
  31. #define MDNS_TYPE_SRV 0x0021
  32. #define MDNS_TYPE_TXT 0x0010
  33. #define MDNS_TYPE_NSEC 0x002F
  34. #define MDNS_TYPE_ANY 0x00FF
  35. #define MDNS_CLASS_IN 0x0001
  36. #define MDNS_CLASS_IN_FLUSH_CACHE 0x8001
  37. #define MDNS_ANSWER_ALL 0x3F
  38. #define MDNS_ANSWER_PTR 0x08
  39. #define MDNS_ANSWER_TXT 0x04
  40. #define MDNS_ANSWER_SRV 0x02
  41. #define MDNS_ANSWER_A 0x01
  42. #define MDNS_ANSWER_AAAA 0x10
  43. #define MDNS_ANSWER_NSEC 0x20
  44. #define MDNS_ANSWER_SDPTR 0x80
  45. #define MDNS_SERVICE_PORT 5353 // UDP port that the server runs on
  46. #define MDNS_SERVICE_STACK_DEPTH 4096 // Stack size for the service thread
  47. #define MDNS_PACKET_QUEUE_LEN 16 // Maximum packets that can be queued for parsing
  48. #define MDNS_TXT_MAX_LEN 1024 // Maximum string length of text data in TXT record
  49. #define MDNS_NAME_MAX_LEN 64 // Maximum string length of hostname, instance, service and proto
  50. #define MDNS_NAME_BUF_LEN (MDNS_NAME_MAX_LEN+1) // Maximum char buffer size to hold hostname, instance, service or proto
  51. #define MDNS_MAX_PACKET_SIZE 1460 // Maximum size of mDNS outgoing packet
  52. #define MDNS_ANSWER_PTR_TTL 4500
  53. #define MDNS_ANSWER_TXT_TTL 4500
  54. #define MDNS_ANSWER_SRV_TTL 120
  55. #define MDNS_ANSWER_A_TTL 120
  56. #define MDNS_ANSWER_AAAA_TTL 120
  57. #define MDNS_HEAD_LEN 12
  58. #define MDNS_HEAD_ID_OFFSET 0
  59. #define MDNS_HEAD_FLAGS_OFFSET 2
  60. #define MDNS_HEAD_QUESTIONS_OFFSET 4
  61. #define MDNS_HEAD_ANSWERS_OFFSET 6
  62. #define MDNS_HEAD_SERVERS_OFFSET 8
  63. #define MDNS_HEAD_ADDITIONAL_OFFSET 10
  64. #define MDNS_TYPE_OFFSET 0
  65. #define MDNS_CLASS_OFFSET 2
  66. #define MDNS_TTL_OFFSET 4
  67. #define MDNS_LEN_OFFSET 8
  68. #define MDNS_DATA_OFFSET 10
  69. #define MDNS_SRV_PRIORITY_OFFSET 0
  70. #define MDNS_SRV_WEIGHT_OFFSET 2
  71. #define MDNS_SRV_PORT_OFFSET 4
  72. #define MDNS_SRV_FQDN_OFFSET 6
  73. typedef struct {
  74. char host[MDNS_NAME_BUF_LEN];
  75. char service[MDNS_NAME_BUF_LEN];
  76. char proto[MDNS_NAME_BUF_LEN];
  77. char domain[MDNS_NAME_BUF_LEN];
  78. uint8_t parts;
  79. uint8_t sub;
  80. } mdns_name_t;
  81. typedef struct {
  82. char host[MDNS_NAME_BUF_LEN];
  83. char instance[MDNS_NAME_BUF_LEN];
  84. char txt[MDNS_TXT_MAX_LEN];
  85. uint16_t priority;
  86. uint16_t weight;
  87. uint16_t port;
  88. uint32_t addr;
  89. uint8_t addrv6[16];
  90. uint8_t ptr;
  91. } mdns_result_temp_t;
  92. typedef struct {
  93. const char * host;
  94. const char * sub;
  95. const char * service;
  96. const char * proto;
  97. const char * domain;
  98. uint8_t parts;
  99. uint8_t done;
  100. } mdns_string_t;
  101. typedef struct mdns_service_s {
  102. const char * instance;
  103. const char * service;
  104. const char * proto;
  105. uint16_t priority;
  106. uint16_t weight;
  107. uint16_t port;
  108. uint8_t txt_num_items;
  109. const char ** txt;
  110. } mdns_service_t;
  111. typedef struct mdns_srv_item_s {
  112. mdns_service_t * service;
  113. struct mdns_srv_item_s * next;
  114. } mdns_srv_item_t;
  115. typedef struct mdns_answer_item_s {
  116. mdns_service_t * service;
  117. uint8_t answer;
  118. struct mdns_answer_item_s * next;
  119. } mdns_answer_item_t;
  120. struct mdns_server_s {
  121. tcpip_adapter_if_t tcpip_if;
  122. struct udp_pcb * pcb;
  123. const char * hostname;
  124. const char * instance;
  125. mdns_srv_item_t * services;
  126. xSemaphoreHandle lock;
  127. xQueueHandle queue;
  128. struct {
  129. char host[MDNS_NAME_BUF_LEN];
  130. char service[MDNS_NAME_BUF_LEN];
  131. char proto[MDNS_NAME_BUF_LEN];
  132. bool running;
  133. xSemaphoreHandle lock;
  134. mdns_result_t * results;
  135. } search;
  136. };
  137. #define MDNS_MUTEX_LOCK() xSemaphoreTake(server->lock, portMAX_DELAY)
  138. #define MDNS_MUTEX_UNLOCK() xSemaphoreGive(server->lock)
  139. #define MDNS_SEARCH_LOCK() xSemaphoreTake(server->search.lock, portMAX_DELAY)
  140. #define MDNS_SEARCH_UNLOCK() xSemaphoreGive(server->search.lock)
  141. static const char * MDNS_DEFAULT_DOMAIN = "local";
  142. static const char * MDNS_SUB_STR = "_sub";
  143. static mdns_server_t * _mdns_servers[TCPIP_ADAPTER_IF_MAX] = {0,0,0};
  144. #ifndef MDNS_TEST_MODE
  145. static TaskHandle_t _mdns_service_task_handle = NULL;
  146. static QueueSetHandle_t _mdns_queue_set = NULL;
  147. static xSemaphoreHandle _mdns_service_semaphore = NULL;
  148. #define MDNS_SERVICE_LOCK() xSemaphoreTake(_mdns_service_semaphore, portMAX_DELAY)
  149. #define MDNS_SERVICE_UNLOCK() xSemaphoreGive(_mdns_service_semaphore)
  150. /*
  151. * MDNS Server Networking
  152. * */
  153. /**
  154. * @brief the receive callback of the raw udp api. Packets are received here
  155. *
  156. */
  157. static void _mdns_server_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *addr, uint16_t port)
  158. {
  159. while(pb != NULL) {
  160. struct pbuf * this_pb = pb;
  161. pb = pb->next;
  162. this_pb->next = NULL;
  163. mdns_server_t * server = (mdns_server_t *)arg;
  164. if (!server || !server->queue || xQueueSend(server->queue, &this_pb, (portTickType)0) != pdPASS) {
  165. pbuf_free(this_pb);
  166. }
  167. }
  168. }
  169. /**
  170. * @brief init the network of MDNS server
  171. *
  172. * @param server The server
  173. *
  174. * @return
  175. * - ESP_OK on success
  176. * - ESP_ERR_INVALID_STATE on igmp/bind error
  177. * - ESP_ERR_NO_MEM on memory error
  178. */
  179. esp_err_t _mdns_server_init(mdns_server_t * server)
  180. {
  181. esp_err_t err = ESP_OK;
  182. tcpip_adapter_ip_info_t if_ip_info;
  183. err = tcpip_adapter_get_ip_info(server->tcpip_if, &if_ip_info);
  184. if (err) {
  185. return err;
  186. }
  187. ip_addr_t laddr;
  188. IP_ADDR4(&laddr, 224, 0, 0, 251);
  189. ip_addr_t multicast_if_addr = IPADDR4_INIT(if_ip_info.ip.addr);
  190. if (igmp_joingroup((const struct ip4_addr *)&multicast_if_addr.u_addr.ip4, (const struct ip4_addr *)&laddr.u_addr.ip4)) {
  191. return ESP_ERR_INVALID_STATE;
  192. }
  193. struct udp_pcb * pcb = udp_new();
  194. if (!pcb) {
  195. return ESP_ERR_NO_MEM;
  196. }
  197. pcb->remote_port = MDNS_SERVICE_PORT;
  198. if (udp_bind(pcb, &multicast_if_addr, pcb->remote_port) != 0) {
  199. udp_remove(pcb);
  200. return ESP_ERR_INVALID_STATE;
  201. }
  202. pcb->mcast_ttl = 1;
  203. ip_addr_copy(pcb->multicast_ip, multicast_if_addr);
  204. ip_addr_copy(pcb->remote_ip, laddr);
  205. server->pcb = pcb;
  206. udp_recv(pcb, &_mdns_server_recv, server);
  207. return err;
  208. }
  209. /**
  210. * @brief stop the network of MDNS server
  211. *
  212. * @param server The server
  213. *
  214. * @return ESP_OK
  215. */
  216. esp_err_t _mdns_server_deinit(mdns_server_t * server)
  217. {
  218. if (server->pcb) {
  219. udp_recv(server->pcb, NULL, NULL);
  220. udp_disconnect(server->pcb);
  221. udp_remove(server->pcb);
  222. server->pcb = NULL;
  223. }
  224. return ESP_OK;
  225. }
  226. #endif
  227. /**
  228. * @brief send packet over UDP
  229. *
  230. * @param server The server
  231. * @param data byte array containing the packet data
  232. * @param len length of the packet data
  233. *
  234. * @return length of sent packet or 0 on error
  235. */
  236. static size_t _mdns_server_write(mdns_server_t * server, uint8_t * data, size_t len)
  237. {
  238. #ifndef MDNS_TEST_MODE
  239. struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
  240. if (pbt == NULL) {
  241. return 0;
  242. }
  243. uint8_t* dst = (uint8_t *)pbt->payload;
  244. memcpy(dst, data, len);
  245. err_t err = udp_sendto(server->pcb, pbt, &(server->pcb->remote_ip), server->pcb->remote_port);
  246. pbuf_free(pbt);
  247. if (err) {
  248. return 0;
  249. }
  250. #endif
  251. return len;
  252. }
  253. /*
  254. * MDNS Servers
  255. * */
  256. #ifndef MDNS_TEST_MODE
  257. void mdns_parse_packet(mdns_server_t * server, const uint8_t * data, size_t len);
  258. /**
  259. * @brief the main MDNS service task. Packets are received and parsed here
  260. */
  261. static void _mdns_service_task(void *pvParameters)
  262. {
  263. uint8_t i;
  264. struct pbuf * pb;
  265. QueueSetMemberHandle_t queue;
  266. for(;;) {
  267. queue = xQueueSelectFromSet(_mdns_queue_set, portMAX_DELAY);
  268. if (queue && xQueueReceive(queue, &pb, 0) == pdTRUE) {
  269. for(i=0; i<TCPIP_ADAPTER_IF_MAX; i++) {
  270. mdns_server_t * server = _mdns_servers[i];
  271. if (server && server->queue == queue) {
  272. MDNS_MUTEX_LOCK();
  273. mdns_parse_packet(server, (uint8_t*)pb->payload, pb->len);
  274. MDNS_MUTEX_UNLOCK();
  275. break;
  276. }
  277. }
  278. pbuf_free(pb);
  279. }
  280. }
  281. }
  282. #endif
  283. /**
  284. * @brief get the server assigned to particular interface
  285. *
  286. * @param tcpip_if The interface
  287. *
  288. * @return reference to the server from the server list or NULL if not found
  289. */
  290. static mdns_server_t * _mdns_server_get(tcpip_adapter_if_t tcpip_if)
  291. {
  292. if (tcpip_if < TCPIP_ADAPTER_IF_MAX) {
  293. return _mdns_servers[tcpip_if];
  294. }
  295. return NULL;
  296. }
  297. /**
  298. * @brief add server to the server list. Start the service thread if not running
  299. *
  300. * @param server The server to add
  301. *
  302. * @return
  303. * - ESP_OK on success
  304. * - ESP_FAIL on error
  305. * - ESP_ERR_* on network error
  306. */
  307. static esp_err_t _mdns_server_add(mdns_server_t * server)
  308. {
  309. #ifndef MDNS_TEST_MODE
  310. if (!_mdns_service_semaphore) {
  311. _mdns_service_semaphore = xSemaphoreCreateMutex();
  312. if (!_mdns_service_semaphore) {
  313. return ESP_FAIL;
  314. }
  315. }
  316. MDNS_SERVICE_LOCK();
  317. if (!_mdns_service_task_handle) {
  318. _mdns_queue_set = xQueueCreateSet(TCPIP_ADAPTER_IF_MAX * MDNS_PACKET_QUEUE_LEN);
  319. if (!_mdns_queue_set) {
  320. MDNS_SERVICE_UNLOCK();
  321. return ESP_FAIL;
  322. }
  323. xTaskCreatePinnedToCore(_mdns_service_task, "mdns", MDNS_SERVICE_STACK_DEPTH, NULL, 1, &_mdns_service_task_handle, 0);
  324. if (!_mdns_service_task_handle) {
  325. vQueueDelete(_mdns_queue_set);
  326. _mdns_queue_set = NULL;
  327. MDNS_SERVICE_UNLOCK();
  328. return ESP_FAIL;
  329. }
  330. }
  331. MDNS_SERVICE_UNLOCK();
  332. if (xQueueAddToSet(server->queue, _mdns_queue_set) != pdPASS) {
  333. return ESP_FAIL;
  334. }
  335. //start UDP
  336. esp_err_t err = _mdns_server_init(server);
  337. if (err) {
  338. return err;
  339. }
  340. #endif
  341. _mdns_servers[server->tcpip_if] = server;
  342. return ESP_OK;
  343. }
  344. /**
  345. * @brief remove server from server list. Stop the service thread in no more servers are running
  346. *
  347. * @param server The server to remove
  348. *
  349. * @return
  350. * - ESP_OK on success
  351. * - ESP_FAIL on error
  352. */
  353. static esp_err_t _mdns_server_remove(mdns_server_t * server)
  354. {
  355. _mdns_servers[server->tcpip_if] = NULL;
  356. #ifndef MDNS_TEST_MODE
  357. //stop UDP
  358. _mdns_server_deinit(server);
  359. if (xQueueRemoveFromSet(server->queue, _mdns_queue_set) != pdPASS) {
  360. return ESP_FAIL;
  361. }
  362. uint8_t i;
  363. for(i=0; i<TCPIP_ADAPTER_IF_MAX; i++) {
  364. if (_mdns_servers[i]) {
  365. break;
  366. }
  367. }
  368. if (i == TCPIP_ADAPTER_IF_MAX) {
  369. //none of the servers are running
  370. MDNS_SERVICE_LOCK();
  371. if (_mdns_service_task_handle) {
  372. vTaskDelete(_mdns_service_task_handle);
  373. vQueueDelete(_mdns_queue_set);
  374. _mdns_queue_set = NULL;
  375. _mdns_service_task_handle = NULL;
  376. }
  377. MDNS_SERVICE_UNLOCK();
  378. }
  379. #endif
  380. return ESP_OK;
  381. }
  382. /*
  383. * PARSING
  384. * */
  385. /**
  386. * @brief queues service for answer (if service is already added, append the new answer type)
  387. *
  388. * @param answers Linked list of answers
  389. * @param service Service to add to the answers
  390. * @param type Type of the answer
  391. *
  392. * @return the new linked list of answers
  393. */
  394. static mdns_answer_item_t * _mdns_add_answer(mdns_answer_item_t * answers, mdns_service_t * service, uint8_t type)
  395. {
  396. //see if we already have the service queued
  397. mdns_answer_item_t * a = answers;
  398. while(a) {
  399. if (a->service == service) {
  400. //just add the new answer type to it
  401. a->answer |= type;
  402. return answers;
  403. }
  404. a = a->next;
  405. }
  406. //prepend the q with this new answer
  407. a = (mdns_answer_item_t *)malloc(sizeof(mdns_answer_item_t));
  408. if (!a) {
  409. return answers;//fail!
  410. }
  411. a->service = service;
  412. a->answer = type;
  413. a->next = answers;
  414. answers = a;
  415. return a;
  416. }
  417. /**
  418. * @brief reads MDNS FQDN into mdns_name_t structure
  419. * FQDN is in format: [hostname.|[instance.]_service._proto.]local.
  420. *
  421. * @param packet MDNS packet
  422. * @param start Starting point of FQDN
  423. * @param name mdns_name_t structure to populate
  424. * @param buf temporary char buffer
  425. *
  426. * @return the address after the parsed FQDN in the packet or NULL on error
  427. */
  428. static const uint8_t * _mdns_read_fqdn(const uint8_t * packet, const uint8_t * start, mdns_name_t * name, char * buf)
  429. {
  430. size_t index = 0;
  431. while(start[index]) {
  432. if (name->parts == 4) {
  433. return NULL;
  434. }
  435. uint8_t len = start[index++];
  436. if ((len & 0xC0) == 0) {
  437. if (len > 64) {
  438. //length can not be more than 64
  439. return NULL;
  440. }
  441. uint8_t i;
  442. for(i=0; i<len; i++) {
  443. buf[i] = start[index++];
  444. }
  445. buf[len] = '\0';
  446. if (name->parts == 1 && buf[0] != '_'
  447. && (strcmp(buf, MDNS_DEFAULT_DOMAIN) != 0)
  448. && (strcmp(buf, "ip6") != 0)
  449. && (strcmp(buf, "in-addr") != 0)) {
  450. snprintf((char*)name, MDNS_NAME_BUF_LEN, "%s.%s", name->host, buf);
  451. } else if (strcmp(buf, MDNS_SUB_STR) == 0) {
  452. name->sub = 1;
  453. } else {
  454. memcpy((uint8_t*)name + (name->parts++ * (MDNS_NAME_BUF_LEN)), buf, len+1);
  455. }
  456. } else {
  457. size_t address = (((uint16_t)len & 0x3F) << 8) | start[index++];
  458. if ((packet + address) >= start) {
  459. //reference address can not be after where we are
  460. return NULL;
  461. }
  462. if (_mdns_read_fqdn(packet, packet + address, name, buf)) {
  463. return start + index;
  464. }
  465. return NULL;
  466. }
  467. }
  468. return start + index + 1;
  469. }
  470. /**
  471. * @brief reads and formats MDNS FQDN into mdns_name_t structure
  472. *
  473. * @param packet MDNS packet
  474. * @param start Starting point of FQDN
  475. * @param name mdns_name_t structure to populate
  476. *
  477. * @return the address after the parsed FQDN in the packet or NULL on error
  478. */
  479. static const uint8_t * _mdns_parse_fqdn(const uint8_t * packet, const uint8_t * start, mdns_name_t * name)
  480. {
  481. name->parts = 0;
  482. name->sub = 0;
  483. name->host[0] = 0;
  484. name->service[0] = 0;
  485. name->proto[0] = 0;
  486. name->domain[0] = 0;
  487. static char buf[MDNS_NAME_BUF_LEN];
  488. const uint8_t * next_data = (uint8_t*)_mdns_read_fqdn(packet, start, name, buf);
  489. if (!next_data || name->parts < 2) {
  490. return 0;
  491. }
  492. if (name->parts == 3) {
  493. memmove((uint8_t*)name + (MDNS_NAME_BUF_LEN), (uint8_t*)name, 3*(MDNS_NAME_BUF_LEN));
  494. name->host[0] = 0;
  495. } else if (name->parts == 2) {
  496. memmove((uint8_t*)(name->domain), (uint8_t*)(name->service), (MDNS_NAME_BUF_LEN));
  497. name->service[0] = 0;
  498. name->proto[0] = 0;
  499. }
  500. if (strcmp(name->domain, MDNS_DEFAULT_DOMAIN) == 0 || strcmp(name->domain, "arpa") == 0) {
  501. return next_data;
  502. }
  503. return 0;
  504. }
  505. /*
  506. * Packet construction
  507. * */
  508. /**
  509. * @brief sets uint16_t value in a packet
  510. *
  511. * @param packet MDNS packet
  512. * @param index offset of uint16_t value
  513. * @param value the value to set
  514. */
  515. static inline void _mdns_set_u16(uint8_t * packet, uint16_t index, uint16_t value)
  516. {
  517. if ((index + 1) >= MDNS_MAX_PACKET_SIZE) {
  518. return;
  519. }
  520. packet[index] = (value >> 8) & 0xFF;
  521. packet[index+1] = value & 0xFF;
  522. }
  523. /**
  524. * @brief appends byte in a packet, incrementing the index
  525. *
  526. * @param packet MDNS packet
  527. * @param index offset in the packet
  528. * @param value the value to set
  529. *
  530. * @return length of added data: 0 on error or 1 on success
  531. */
  532. static inline uint8_t _mdns_append_u8(uint8_t * packet, uint16_t * index, uint8_t value)
  533. {
  534. if (*index >= MDNS_MAX_PACKET_SIZE) {
  535. return 0;
  536. }
  537. packet[*index] = value;
  538. *index += 1;
  539. return 1;
  540. }
  541. /**
  542. * @brief appends uint16_t in a packet, incrementing the index
  543. *
  544. * @param packet MDNS packet
  545. * @param index offset in the packet
  546. * @param value the value to set
  547. *
  548. * @return length of added data: 0 on error or 2 on success
  549. */
  550. static inline uint8_t _mdns_append_u16(uint8_t * packet, uint16_t * index, uint16_t value)
  551. {
  552. if ((*index + 1) >= MDNS_MAX_PACKET_SIZE) {
  553. return 0;
  554. }
  555. _mdns_append_u8(packet, index, (value >> 8) & 0xFF);
  556. _mdns_append_u8(packet, index, value & 0xFF);
  557. return 2;
  558. }
  559. /**
  560. * @brief appends uint32_t in a packet, incrementing the index
  561. *
  562. * @param packet MDNS packet
  563. * @param index offset in the packet
  564. * @param value the value to set
  565. *
  566. * @return length of added data: 0 on error or 4 on success
  567. */
  568. static inline uint8_t _mdns_append_u32(uint8_t * packet, uint16_t * index, uint32_t value)
  569. {
  570. if ((*index + 3) >= MDNS_MAX_PACKET_SIZE) {
  571. return 0;
  572. }
  573. _mdns_append_u8(packet, index, (value >> 24) & 0xFF);
  574. _mdns_append_u8(packet, index, (value >> 16) & 0xFF);
  575. _mdns_append_u8(packet, index, (value >> 8) & 0xFF);
  576. _mdns_append_u8(packet, index, value & 0xFF);
  577. return 4;
  578. }
  579. /**
  580. * @brief appends answer type, class, ttl and data length to a packet, incrementing the index
  581. *
  582. * @param packet MDNS packet
  583. * @param index offset in the packet
  584. * @param type answer type
  585. * @param ttl answer ttl
  586. *
  587. * @return length of added data: 0 on error or 10 on success
  588. */
  589. static inline uint8_t _mdns_append_type(uint8_t * packet, uint16_t * index, uint8_t type, uint32_t ttl)
  590. {
  591. if ((*index + 10) >= MDNS_MAX_PACKET_SIZE) {
  592. return 0;
  593. }
  594. if (type == MDNS_ANSWER_PTR) {
  595. _mdns_append_u16(packet, index, MDNS_TYPE_PTR);
  596. _mdns_append_u16(packet, index, MDNS_CLASS_IN);
  597. } else if (type == MDNS_ANSWER_TXT) {
  598. _mdns_append_u16(packet, index, MDNS_TYPE_TXT);
  599. _mdns_append_u16(packet, index, MDNS_CLASS_IN_FLUSH_CACHE);
  600. } else if (type == MDNS_ANSWER_SRV) {
  601. _mdns_append_u16(packet, index, MDNS_TYPE_SRV);
  602. _mdns_append_u16(packet, index, MDNS_CLASS_IN_FLUSH_CACHE);
  603. } else if (type == MDNS_ANSWER_A) {
  604. _mdns_append_u16(packet, index, MDNS_TYPE_A);
  605. _mdns_append_u16(packet, index, MDNS_CLASS_IN_FLUSH_CACHE);
  606. } else if (type == MDNS_ANSWER_AAAA) {
  607. _mdns_append_u16(packet, index, MDNS_TYPE_AAAA);
  608. _mdns_append_u16(packet, index, MDNS_CLASS_IN_FLUSH_CACHE);
  609. } else {
  610. return 0;
  611. }
  612. _mdns_append_u32(packet, index, ttl);
  613. _mdns_append_u16(packet, index, 0);
  614. return 10;
  615. }
  616. /**
  617. * @brief appends single string to a packet, incrementing the index
  618. *
  619. * @param packet MDNS packet
  620. * @param index offset in the packet
  621. * @param string the string to append
  622. *
  623. * @return length of added data: 0 on error or length of the string + 1 on success
  624. */
  625. static inline uint8_t _mdns_append_string(uint8_t * packet, uint16_t * index, const char * string)
  626. {
  627. uint8_t len = strlen(string);
  628. if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) {
  629. return 0;
  630. }
  631. _mdns_append_u8(packet, index, len);
  632. memcpy(packet + *index, string, len);
  633. *index += len;
  634. return len + 1;
  635. }
  636. /**
  637. * @brief appends FQDN to a packet, incrementing the index
  638. *
  639. * @param packet MDNS packet
  640. * @param index offset in the packet
  641. * @param strings string array containing the parts of the FQDN
  642. * @param count number of strings in the array
  643. *
  644. * @return length of added data: 0 on error or length on success
  645. */
  646. static uint16_t _mdns_append_fqdn(uint8_t * packet, uint16_t * index, const char * strings[], uint8_t count)
  647. {
  648. if (!count) {
  649. return _mdns_append_u8(packet, index, 0);
  650. }
  651. mdns_name_t name;
  652. static char buf[MDNS_NAME_BUF_LEN];
  653. uint8_t len = strlen(strings[0]);
  654. uint8_t * len_location = (uint8_t *)memchr(packet, (char)len, *index);
  655. while(len_location) {
  656. if (memcmp(len_location+1, strings[0], len)) { //not continuing with our string
  657. search_next:
  658. len_location = (uint8_t *)memchr(len_location+1, (char)len, *index - (len_location+1 - packet));
  659. continue;
  660. }
  661. //read string into name and compare
  662. name.parts = 0;
  663. name.sub = 0;
  664. name.host[0] = 0;
  665. name.service[0] = 0;
  666. name.proto[0] = 0;
  667. name.domain[0] = 0;
  668. const uint8_t * content = _mdns_read_fqdn(packet, len_location, &name, buf);
  669. if (!content) {
  670. return 0;
  671. }
  672. if (name.parts == count) {
  673. uint8_t i;
  674. for(i=0; i<count; i++) {
  675. if (strcmp(strings[i], (const char *)&name + (i * (MDNS_NAME_BUF_LEN)))) {
  676. //not our string
  677. goto search_next;
  678. }
  679. }
  680. //we actually have found the string
  681. break;
  682. } else {
  683. goto search_next;
  684. }
  685. }
  686. if (!len_location) {
  687. uint8_t written = _mdns_append_string(packet, index, strings[0]);
  688. if (!written) {
  689. return 0;
  690. }
  691. return written + _mdns_append_fqdn(packet, index, &strings[1], count - 1);
  692. }
  693. uint16_t offset = len_location - packet;
  694. offset |= MDNS_NAME_REF;
  695. return _mdns_append_u16(packet, index, offset);
  696. }
  697. /**
  698. * @brief appends PTR record for service to a packet, incrementing the index
  699. *
  700. * @param packet MDNS packet
  701. * @param index offset in the packet
  702. * @param server the server that is hosting the service
  703. * @param service the service to add record for
  704. *
  705. * @return length of added data: 0 on error or length on success
  706. */
  707. static uint16_t _mdns_append_ptr_record(uint8_t * packet, uint16_t * index, mdns_server_t * server, mdns_service_t * service)
  708. {
  709. const char * str[4];
  710. uint16_t record_length = 0;
  711. uint8_t part_length;
  712. str[0] = (service->instance)?service->instance
  713. :(server->instance)?server->instance
  714. :server->hostname;
  715. str[1] = service->service;
  716. str[2] = service->proto;
  717. str[3] = MDNS_DEFAULT_DOMAIN;
  718. part_length = _mdns_append_fqdn(packet, index, str + 1, 3);
  719. if (!part_length) {
  720. return 0;
  721. }
  722. record_length += part_length;
  723. part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, MDNS_ANSWER_PTR_TTL);
  724. if (!part_length) {
  725. return 0;
  726. }
  727. record_length += part_length;
  728. uint16_t data_len_location = *index - 2;
  729. part_length = _mdns_append_fqdn(packet, index, str, 4);
  730. if (!part_length) {
  731. return 0;
  732. }
  733. _mdns_set_u16(packet, data_len_location, part_length);
  734. record_length += part_length;
  735. return record_length;
  736. }
  737. /**
  738. * @brief appends DNS-SD PTR record for service to a packet, incrementing the index
  739. *
  740. * @param packet MDNS packet
  741. * @param index offset in the packet
  742. * @param server the server that is hosting the service
  743. * @param service the service to add record for
  744. *
  745. * @return length of added data: 0 on error or length on success
  746. */
  747. static uint16_t _mdns_append_sdptr_record(uint8_t * packet, uint16_t * index, mdns_server_t * server, mdns_service_t * service)
  748. {
  749. const char * str[3];
  750. const char * sd_str[4];
  751. uint16_t record_length = 0;
  752. uint8_t part_length;
  753. sd_str[0] = (char*)"_services";
  754. sd_str[1] = (char*)"_dns-sd";
  755. sd_str[2] = (char*)"_udp";
  756. sd_str[3] = MDNS_DEFAULT_DOMAIN;
  757. str[0] = service->service;
  758. str[1] = service->proto;
  759. str[2] = MDNS_DEFAULT_DOMAIN;
  760. part_length = _mdns_append_fqdn(packet, index, sd_str, 4);
  761. record_length += part_length;
  762. part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, MDNS_ANSWER_PTR_TTL);
  763. if (!part_length) {
  764. return 0;
  765. }
  766. record_length += part_length;
  767. uint16_t data_len_location = *index - 2;
  768. part_length = _mdns_append_fqdn(packet, index, str, 3);
  769. if (!part_length) {
  770. return 0;
  771. }
  772. _mdns_set_u16(packet, data_len_location, part_length);
  773. record_length += part_length;
  774. return record_length;
  775. }
  776. /**
  777. * @brief appends TXT record for service to a packet, incrementing the index
  778. *
  779. * @param packet MDNS packet
  780. * @param index offset in the packet
  781. * @param server the server that is hosting the service
  782. * @param service the service to add record for
  783. *
  784. * @return length of added data: 0 on error or length on success
  785. */
  786. static uint16_t _mdns_append_txt_record(uint8_t * packet, uint16_t * index, mdns_server_t * server, mdns_service_t * service)
  787. {
  788. const char * str[4];
  789. uint16_t record_length = 0;
  790. uint8_t part_length;
  791. str[0] = (service->instance)?service->instance
  792. :(server->instance)?server->instance
  793. :server->hostname;
  794. str[1] = service->service;
  795. str[2] = service->proto;
  796. str[3] = MDNS_DEFAULT_DOMAIN;
  797. part_length = _mdns_append_fqdn(packet, index, str, 4);
  798. if (!part_length) {
  799. return 0;
  800. }
  801. record_length += part_length;
  802. part_length = _mdns_append_type(packet, index, MDNS_ANSWER_TXT, MDNS_ANSWER_TXT_TTL);
  803. if (!part_length) {
  804. return 0;
  805. }
  806. record_length += part_length;
  807. uint16_t data_len_location = *index - 2;
  808. uint16_t data_len = 0;
  809. if (service->txt_num_items) {
  810. uint8_t len = service->txt_num_items;
  811. const char ** txt = service->txt;
  812. uint8_t i, l;
  813. for(i=0; i<len; i++) {
  814. l = _mdns_append_string(packet, index, txt[i]);
  815. if (!l) {
  816. return 0;
  817. }
  818. data_len += l;
  819. }
  820. }
  821. _mdns_set_u16(packet, data_len_location, data_len);
  822. record_length += data_len;
  823. return record_length;
  824. }
  825. /**
  826. * @brief appends SRV record for service to a packet, incrementing the index
  827. *
  828. * @param packet MDNS packet
  829. * @param index offset in the packet
  830. * @param server the server that is hosting the service
  831. * @param service the service to add record for
  832. *
  833. * @return length of added data: 0 on error or length on success
  834. */
  835. static uint16_t _mdns_append_srv_record(uint8_t * packet, uint16_t * index, mdns_server_t * server, mdns_service_t * service)
  836. {
  837. const char * str[4];
  838. uint16_t record_length = 0;
  839. uint8_t part_length;
  840. str[0] = (service->instance)?service->instance
  841. :(server->instance)?server->instance
  842. :server->hostname;
  843. str[1] = service->service;
  844. str[2] = service->proto;
  845. str[3] = MDNS_DEFAULT_DOMAIN;
  846. part_length = _mdns_append_fqdn(packet, index, str, 4);
  847. if (!part_length) {
  848. return 0;
  849. }
  850. record_length += part_length;
  851. part_length = _mdns_append_type(packet, index, MDNS_ANSWER_SRV, MDNS_ANSWER_SRV_TTL);
  852. if (!part_length) {
  853. return 0;
  854. }
  855. record_length += part_length;
  856. uint16_t data_len_location = *index - 2;
  857. part_length = 0;
  858. part_length += _mdns_append_u16(packet, index, service->priority);
  859. part_length += _mdns_append_u16(packet, index, service->weight);
  860. part_length += _mdns_append_u16(packet, index, service->port);
  861. if (part_length != 6) {
  862. return 0;
  863. }
  864. str[0] = server->hostname;
  865. str[1] = MDNS_DEFAULT_DOMAIN;
  866. part_length = _mdns_append_fqdn(packet, index, str, 2);
  867. if (!part_length) {
  868. return 0;
  869. }
  870. _mdns_set_u16(packet, data_len_location, part_length + 6);
  871. record_length += part_length + 6;
  872. return record_length;
  873. }
  874. /**
  875. * @brief appends A record to a packet, incrementing the index
  876. *
  877. * @param packet MDNS packet
  878. * @param index offset in the packet
  879. * @param server the server
  880. * @param ip the IP address to add
  881. *
  882. * @return length of added data: 0 on error or length on success
  883. */
  884. static uint16_t _mdns_append_a_record(uint8_t * packet, uint16_t * index, mdns_server_t * server, uint32_t ip)
  885. {
  886. const char * str[2];
  887. uint16_t record_length = 0;
  888. uint8_t part_length;
  889. str[0] = server->hostname;
  890. str[1] = MDNS_DEFAULT_DOMAIN;
  891. part_length = _mdns_append_fqdn(packet, index, str, 2);
  892. if (!part_length) {
  893. return 0;
  894. }
  895. record_length += part_length;
  896. part_length = _mdns_append_type(packet, index, MDNS_ANSWER_A, MDNS_ANSWER_A_TTL);
  897. if (!part_length) {
  898. return 0;
  899. }
  900. record_length += part_length;
  901. uint16_t data_len_location = *index - 2;
  902. if ((*index + 3) >= MDNS_MAX_PACKET_SIZE) {
  903. return 0;
  904. }
  905. _mdns_append_u8(packet, index, ip & 0xFF);
  906. _mdns_append_u8(packet, index, (ip >> 8) & 0xFF);
  907. _mdns_append_u8(packet, index, (ip >> 16) & 0xFF);
  908. _mdns_append_u8(packet, index, (ip >> 24) & 0xFF);
  909. _mdns_set_u16(packet, data_len_location, 4);
  910. record_length += 4;
  911. return record_length;
  912. }
  913. /**
  914. * @brief appends AAAA record to a packet, incrementing the index
  915. *
  916. * @param packet MDNS packet
  917. * @param index offset in the packet
  918. * @param server the server
  919. * @param ipv6 the IPv6 address to add
  920. *
  921. * @return length of added data: 0 on error or length on success
  922. */
  923. static uint16_t _mdns_append_aaaa_record(uint8_t * packet, uint16_t * index, mdns_server_t * server, uint8_t * ipv6)
  924. {
  925. const char * str[2];
  926. uint16_t record_length = 0;
  927. uint8_t part_length;
  928. str[0] = server->hostname;
  929. str[1] = MDNS_DEFAULT_DOMAIN;
  930. part_length = _mdns_append_fqdn(packet, index, str, 2);
  931. if (!part_length) {
  932. return 0;
  933. }
  934. record_length += part_length;
  935. part_length = _mdns_append_type(packet, index, MDNS_ANSWER_AAAA, MDNS_ANSWER_AAAA_TTL);
  936. if (!part_length) {
  937. return 0;
  938. }
  939. record_length += part_length;
  940. uint16_t data_len_location = *index - 2;
  941. if ((*index + 15) >= MDNS_MAX_PACKET_SIZE) {
  942. return 0;
  943. }
  944. part_length = sizeof(ip6_addr_t);
  945. memcpy(packet + *index, ipv6, part_length);
  946. *index += part_length;
  947. _mdns_set_u16(packet, data_len_location, part_length);
  948. record_length += part_length;
  949. return record_length;
  950. }
  951. /**
  952. * @brief sends all collected answers
  953. *
  954. * @param server the server
  955. * @param answers linked list of answers
  956. */
  957. static void _mdns_send_answers(mdns_server_t * server, mdns_answer_item_t * answers)
  958. {
  959. bool send_ip = false;
  960. static uint8_t packet[MDNS_MAX_PACKET_SIZE];
  961. uint16_t index = MDNS_HEAD_LEN;
  962. uint8_t answer_count = 0;
  963. memset(packet, 0, MDNS_HEAD_LEN);
  964. _mdns_set_u16(packet, MDNS_HEAD_FLAGS_OFFSET, MDNS_FLAGS_AUTHORITATIVE);
  965. while(answers) {
  966. if (answers->answer & MDNS_ANSWER_A) {
  967. answers->answer &= ~MDNS_ANSWER_A;
  968. send_ip = true;
  969. }
  970. if (answers->service) {
  971. if (answers->answer & MDNS_ANSWER_PTR) {
  972. if (!_mdns_append_ptr_record(packet, &index, server, answers->service)) {
  973. return;
  974. }
  975. answer_count += 1;
  976. }
  977. if (answers->answer & MDNS_ANSWER_TXT) {
  978. if (!_mdns_append_txt_record(packet, &index, server, answers->service)) {
  979. return;
  980. }
  981. answer_count += 1;
  982. }
  983. if (answers->answer & MDNS_ANSWER_SRV) {
  984. if (!_mdns_append_srv_record(packet, &index, server, answers->service)) {
  985. return;
  986. }
  987. answer_count += 1;
  988. }
  989. if (answers->answer & MDNS_ANSWER_SDPTR) {
  990. if (!_mdns_append_sdptr_record(packet, &index, server, answers->service)) {
  991. return;
  992. }
  993. answer_count += 1;
  994. }
  995. }
  996. mdns_answer_item_t * a = answers;
  997. answers = answers->next;
  998. free(a);
  999. }
  1000. if (send_ip) {
  1001. tcpip_adapter_ip_info_t if_ip_info;
  1002. tcpip_adapter_get_ip_info(server->tcpip_if, &if_ip_info);
  1003. if (!_mdns_append_a_record(packet, &index, server, if_ip_info.ip.addr)) {
  1004. return;
  1005. }
  1006. answer_count += 1;
  1007. //add ipv6 if available
  1008. struct ip6_addr if_ip6;
  1009. if (!tcpip_adapter_get_ip6_linklocal(server->tcpip_if, &if_ip6)) {
  1010. uint8_t * v6addr = (uint8_t*)if_ip6.addr;
  1011. //check if not 0
  1012. int i;
  1013. for(i=0;i<sizeof(ip6_addr_t);i++) {
  1014. if (v6addr[i]) {
  1015. break;
  1016. }
  1017. }
  1018. if (i<sizeof(ip6_addr_t)) {
  1019. if (!_mdns_append_aaaa_record(packet, &index, server, v6addr)) {
  1020. return;
  1021. }
  1022. answer_count += 1;
  1023. }
  1024. }
  1025. }
  1026. _mdns_set_u16(packet, MDNS_HEAD_ANSWERS_OFFSET, answer_count);
  1027. _mdns_server_write(server, packet, index);
  1028. }
  1029. /**
  1030. * @brief appends search result from query
  1031. *
  1032. * @param server the server
  1033. * @param r the temporary result to copy
  1034. */
  1035. static void _mdns_add_result(mdns_server_t * server, mdns_result_temp_t * r)
  1036. {
  1037. mdns_result_t * n = (mdns_result_t *)malloc(sizeof(mdns_result_t));
  1038. if (!n) {
  1039. return;
  1040. }
  1041. n->priority = r->priority;
  1042. n->weight = r->weight;
  1043. n->port = r->port;
  1044. n->addr.addr = r->addr;
  1045. size_t hlen = strlen(r->host);
  1046. if (hlen) {
  1047. n->host = strdup(r->host);
  1048. if (!n->host) {
  1049. free(n);
  1050. return;
  1051. }
  1052. } else {
  1053. n->host = NULL;
  1054. }
  1055. size_t ilen = strlen(r->instance);
  1056. if (ilen) {
  1057. n->instance = strdup(r->instance);
  1058. if (!n->instance) {
  1059. free((char *)n->host);
  1060. free(n);
  1061. return;
  1062. }
  1063. } else {
  1064. n->instance = NULL;
  1065. }
  1066. size_t tlen = strlen(r->txt);
  1067. if (tlen) {
  1068. n->txt = strdup(r->txt);
  1069. if (!n->txt) {
  1070. free((char *)n->host);
  1071. free((char *)n->instance);
  1072. free(n);
  1073. return;
  1074. }
  1075. } else {
  1076. n->txt = NULL;
  1077. }
  1078. memcpy((uint8_t *)n->addrv6.addr, r->addrv6, sizeof(ip6_addr_t));
  1079. mdns_result_t * o = server->search.results;
  1080. server->search.results = n;
  1081. n->next = o;
  1082. }
  1083. /**
  1084. * @brief finds service from given service type
  1085. * @param server the server
  1086. * @param service service type to match
  1087. * @param proto proto to match
  1088. *
  1089. * @return the service item if found or NULL on error
  1090. */
  1091. static mdns_srv_item_t * _mdns_get_service_item(mdns_server_t * server, const char * service, const char * proto)
  1092. {
  1093. mdns_srv_item_t * s = server->services;
  1094. while(s) {
  1095. if (!strcmp(s->service->service, service) && !strcmp(s->service->proto, proto)) {
  1096. return s;
  1097. }
  1098. s = s->next;
  1099. }
  1100. return NULL;
  1101. }
  1102. /**
  1103. * @brief creates/allocates new service
  1104. * @param service service type
  1105. * @param proto service proto
  1106. * @param port service port
  1107. *
  1108. * @return pointer to the service or NULL on error
  1109. */
  1110. static mdns_service_t * _mdns_create_service(const char * service, const char * proto, uint16_t port)
  1111. {
  1112. mdns_service_t * s = (mdns_service_t *)malloc(sizeof(mdns_service_t));
  1113. if (!s) {
  1114. return NULL;
  1115. }
  1116. s->priority = 0;
  1117. s->weight = 0;
  1118. s->txt_num_items = 0;
  1119. s->instance = NULL;
  1120. s->txt = NULL;
  1121. s->port = port;
  1122. s->service = strndup(service, MDNS_NAME_BUF_LEN - 1);
  1123. if (!s->service) {
  1124. free(s);
  1125. return NULL;
  1126. }
  1127. s->proto = strndup(proto, MDNS_NAME_BUF_LEN - 1);
  1128. if (!s->proto) {
  1129. free((char *)s->service);
  1130. free(s);
  1131. return NULL;
  1132. }
  1133. return s;
  1134. }
  1135. /**
  1136. * @brief free service memory
  1137. *
  1138. * @param service the service
  1139. */
  1140. static void _mdns_free_service(mdns_service_t * service)
  1141. {
  1142. if (!service) {
  1143. return;
  1144. }
  1145. free((char *)service->instance);
  1146. free((char *)service->service);
  1147. free((char *)service->proto);
  1148. if (service->txt_num_items) {
  1149. uint8_t i;
  1150. for(i=0; i<service->txt_num_items; i++) {
  1151. free((char *)service->txt[i]);
  1152. }
  1153. }
  1154. free(service->txt);
  1155. free(service);
  1156. }
  1157. /**
  1158. * @brief read uint16_t from a packet
  1159. * @param packet the packet
  1160. * @param index index in the packet where the value starts
  1161. *
  1162. * @return the value
  1163. */
  1164. static inline uint16_t _mdns_read_u16(const uint8_t * packet, uint16_t index)
  1165. {
  1166. return (uint16_t)(packet[index]) << 8 | packet[index+1];
  1167. }
  1168. /**
  1169. * @brief main packet parser
  1170. *
  1171. * @param server the server
  1172. * @param data byte array holding the packet data
  1173. * @param len length of the byte array
  1174. */
  1175. void mdns_parse_packet(mdns_server_t * server, const uint8_t * data, size_t len)
  1176. {
  1177. static mdns_name_t n;
  1178. static mdns_result_temp_t a;
  1179. const uint8_t * content = data + MDNS_HEAD_LEN;
  1180. mdns_name_t * name = &n;
  1181. memset(name, 0, sizeof(mdns_name_t));
  1182. uint16_t questions = _mdns_read_u16(data, MDNS_HEAD_QUESTIONS_OFFSET);
  1183. uint16_t answers = _mdns_read_u16(data, MDNS_HEAD_ANSWERS_OFFSET);
  1184. uint16_t additional = _mdns_read_u16(data, MDNS_HEAD_ADDITIONAL_OFFSET);
  1185. if (questions) {
  1186. uint8_t qs = questions;
  1187. mdns_answer_item_t * answer_items = NULL;
  1188. while(qs--) {
  1189. content = _mdns_parse_fqdn(data, content, name);
  1190. if (!content) {
  1191. answers = 0;
  1192. additional = 0;
  1193. break;//error
  1194. }
  1195. uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET);
  1196. content = content + 4;
  1197. if (!name->service[0] || !name->proto[0]) {
  1198. if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA || type == MDNS_TYPE_ANY) {//send A + AAAA
  1199. if (name->host[0] && server->hostname && server->hostname[0] && !strcmp(name->host, server->hostname)) {
  1200. answer_items = _mdns_add_answer(answer_items, NULL, MDNS_ANSWER_A);
  1201. }
  1202. }
  1203. continue;
  1204. }
  1205. //is this a dns-sd service discovery meta query?
  1206. if (!strcmp(name->host, "_services") && !strcmp(name->service, "_dns-sd") && !strcmp(name->proto, "_udp") && !strcmp(name->domain, MDNS_DEFAULT_DOMAIN) && type == MDNS_TYPE_PTR)
  1207. {
  1208. //add answers for all services
  1209. mdns_srv_item_t * s = server->services;
  1210. while(s) {
  1211. if (s->service->service && s->service->proto) {
  1212. answer_items = _mdns_add_answer(answer_items, s->service, MDNS_ANSWER_SDPTR);
  1213. }
  1214. s = s->next;
  1215. }
  1216. continue;
  1217. }
  1218. if (name->sub) {
  1219. continue;
  1220. }
  1221. mdns_srv_item_t * si = _mdns_get_service_item(server, name->service, name->proto);
  1222. if (!si) {
  1223. //service not found
  1224. continue;
  1225. }
  1226. if (type == MDNS_TYPE_PTR) {
  1227. answer_items = _mdns_add_answer(answer_items, si->service, MDNS_ANSWER_ALL);
  1228. } else if (type == MDNS_TYPE_TXT) {
  1229. //match instance/host
  1230. const char * host = (si->service->instance)?si->service->instance
  1231. :(server->instance)?server->instance
  1232. :server->hostname;
  1233. if (!host || !host[0] || !name->host[0] || strcmp(name->host, host)) {
  1234. continue;
  1235. }
  1236. answer_items = _mdns_add_answer(answer_items, si->service, MDNS_ANSWER_TXT);
  1237. } else if (type == MDNS_TYPE_SRV) {
  1238. //match instance/host
  1239. const char * host = (si->service->instance)?si->service->instance
  1240. :(server->instance)?server->instance
  1241. :server->hostname;
  1242. if (!host || !host[0] || !name->host[0] || strcmp(name->host, host)) {
  1243. continue;
  1244. }
  1245. answer_items = _mdns_add_answer(answer_items, si->service, MDNS_ANSWER_SRV | MDNS_ANSWER_A);
  1246. } else if (type == MDNS_TYPE_ANY) {//send all
  1247. //match host
  1248. if (!name->host[0] || !server->hostname || !server->hostname[0] || strcmp(name->host, server->hostname)) {
  1249. answer_items = _mdns_add_answer(answer_items, si->service, MDNS_ANSWER_ALL);
  1250. }
  1251. }
  1252. }
  1253. if (answer_items) {
  1254. _mdns_send_answers(server, answer_items);
  1255. }
  1256. }
  1257. if (server->search.running && (answers || additional)) {
  1258. mdns_result_temp_t * answer = &a;
  1259. memset(answer, 0, sizeof(mdns_result_temp_t));
  1260. while(content < (data + len)) {
  1261. content = _mdns_parse_fqdn(data, content, name);
  1262. if (!content) {
  1263. return;//error
  1264. }
  1265. uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET);
  1266. uint16_t data_len = _mdns_read_u16(content, MDNS_LEN_OFFSET);
  1267. const uint8_t * data_ptr = content + MDNS_DATA_OFFSET;
  1268. content = data_ptr + data_len;
  1269. if(content > (data + len)){
  1270. return;
  1271. }
  1272. if (type == MDNS_TYPE_PTR) {
  1273. if (!_mdns_parse_fqdn(data, data_ptr, name)) {
  1274. continue;//error
  1275. }
  1276. #ifndef MDNS_TEST_MODE
  1277. if (server->search.host[0] ||
  1278. (strcmp(name->service, server->search.service) != 0) ||
  1279. (strcmp(name->proto, server->search.proto) != 0)) {
  1280. continue;//not searching for service or wrong service/proto
  1281. }
  1282. #endif
  1283. strlcpy(answer->instance, name->host, MDNS_NAME_BUF_LEN);
  1284. } else if (type == MDNS_TYPE_SRV) {
  1285. #ifndef MDNS_TEST_MODE
  1286. if (server->search.host[0] ||
  1287. (strcmp(name->service, server->search.service) != 0) ||
  1288. (strcmp(name->proto, server->search.proto) != 0)) {
  1289. continue;//not searching for service or wrong service/proto
  1290. }
  1291. #endif
  1292. if (answer->instance[0]) {
  1293. if (strcmp(answer->instance, name->host) != 0) {
  1294. continue;//instance name is not the same as the one in the PTR record
  1295. }
  1296. } else {
  1297. strlcpy(answer->instance, name->host, MDNS_NAME_BUF_LEN);
  1298. }
  1299. //parse record value
  1300. if (!_mdns_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name)) {
  1301. continue;//error
  1302. }
  1303. answer->ptr = 1;
  1304. answer->priority = _mdns_read_u16(data_ptr, MDNS_SRV_PRIORITY_OFFSET);
  1305. answer->weight = _mdns_read_u16(data_ptr, MDNS_SRV_WEIGHT_OFFSET);
  1306. answer->port = _mdns_read_u16(data_ptr, MDNS_SRV_PORT_OFFSET);
  1307. if (answer->host[0]) {
  1308. if (strcmp(answer->host, name->host) != 0) {
  1309. answer->addr = 0;
  1310. strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN);
  1311. }
  1312. } else {
  1313. strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN);
  1314. }
  1315. } else if (type == MDNS_TYPE_TXT) {
  1316. uint16_t i=0,b=0, y;
  1317. while(i < data_len) {
  1318. uint8_t partLen = data_ptr[i++];
  1319. if((i+partLen) > data_len){
  1320. break;//error
  1321. }
  1322. //check if partLen will fit in the buffer
  1323. if (partLen > (MDNS_TXT_MAX_LEN - b - 1)) {
  1324. break;
  1325. }
  1326. for(y=0; y<partLen; y++) {
  1327. char d = data_ptr[i++];
  1328. answer->txt[b++] = d;
  1329. }
  1330. if (i<data_len) {
  1331. answer->txt[b++] = '&';
  1332. }
  1333. }
  1334. answer->txt[b] = 0;
  1335. } else if (type == MDNS_TYPE_AAAA) {
  1336. if (server->search.host[0]) {
  1337. #ifndef MDNS_TEST_MODE
  1338. if (strcmp(name->host, server->search.host) != 0) {
  1339. continue;//wrong host
  1340. }
  1341. #endif
  1342. } else if (!answer->ptr) {
  1343. strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN);
  1344. } else if (strcmp(answer->host, name->host) != 0) {
  1345. continue;//wrong host
  1346. }
  1347. memcpy(answer->addrv6, data_ptr, sizeof(ip6_addr_t));
  1348. } else if (type == MDNS_TYPE_A) {
  1349. if (server->search.host[0]) {
  1350. #ifndef MDNS_TEST_MODE
  1351. if (strcmp(name->host, server->search.host) != 0) {
  1352. continue;//wrong host
  1353. }
  1354. #endif
  1355. } else if (!answer->ptr) {
  1356. strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN);
  1357. } else if (strcmp(answer->host, name->host) != 0) {
  1358. continue;//wrong host
  1359. }
  1360. if (server->search.running && answer->addr) {
  1361. _mdns_add_result(server, answer);//another IP for our host
  1362. }
  1363. IP4_ADDR(answer, data_ptr[0], data_ptr[1], data_ptr[2], data_ptr[3]);
  1364. }
  1365. }
  1366. if (server->search.running && (server->search.host[0] || answer->ptr) && answer->addr) {
  1367. _mdns_add_result(server, answer);
  1368. }
  1369. //end while
  1370. }
  1371. }
  1372. /*
  1373. * Public Methods
  1374. * */
  1375. esp_err_t mdns_init(tcpip_adapter_if_t tcpip_if, mdns_server_t ** mdns_server)
  1376. {
  1377. esp_err_t err = ESP_OK;
  1378. if (tcpip_if >= TCPIP_ADAPTER_IF_MAX) {
  1379. return ESP_ERR_INVALID_ARG;
  1380. }
  1381. if (_mdns_server_get(tcpip_if)) {
  1382. return ESP_ERR_INVALID_STATE;
  1383. }
  1384. uint8_t mode;
  1385. err = esp_wifi_get_mode((wifi_mode_t*)&mode);
  1386. if (err) {
  1387. return err;
  1388. }
  1389. if ((tcpip_if == TCPIP_ADAPTER_IF_STA && !(mode & WIFI_MODE_STA))
  1390. || (tcpip_if == TCPIP_ADAPTER_IF_AP && !(mode & WIFI_MODE_AP))) {
  1391. return ESP_ERR_INVALID_ARG;
  1392. }
  1393. mdns_server_t * server = (mdns_server_t *)malloc(sizeof(mdns_server_t));
  1394. if (!server) {
  1395. return ESP_ERR_NO_MEM;
  1396. }
  1397. server->tcpip_if = tcpip_if;
  1398. server->hostname = NULL;
  1399. server->instance = NULL;
  1400. server->services = NULL;
  1401. server->search.host[0] = 0;
  1402. server->search.service[0] = 0;
  1403. server->search.proto[0] = 0;
  1404. server->search.running = false;
  1405. server->search.results = NULL;
  1406. server->pcb = NULL;
  1407. server->lock = xSemaphoreCreateMutex();
  1408. if (!server->lock) {
  1409. free(server);
  1410. return ESP_ERR_NO_MEM;
  1411. }
  1412. server->search.lock = xSemaphoreCreateMutex();
  1413. if (!server->search.lock) {
  1414. vSemaphoreDelete(server->lock);
  1415. free(server);
  1416. return ESP_ERR_NO_MEM;
  1417. }
  1418. server->queue = xQueueCreate(MDNS_PACKET_QUEUE_LEN, sizeof(struct pbuf *));
  1419. if (!server->queue) {
  1420. vSemaphoreDelete(server->lock);
  1421. vSemaphoreDelete(server->search.lock);
  1422. free(server);
  1423. return ESP_ERR_NO_MEM;
  1424. }
  1425. if (_mdns_server_add(server)) {
  1426. //service start failed!
  1427. vSemaphoreDelete(server->lock);
  1428. vSemaphoreDelete(server->search.lock);
  1429. vQueueDelete(server->queue);
  1430. free(server);
  1431. return ESP_FAIL;
  1432. }
  1433. const char * hostname = NULL;
  1434. tcpip_adapter_get_hostname(server->tcpip_if, &hostname);
  1435. mdns_set_hostname(server, hostname);
  1436. *mdns_server = server;
  1437. return ESP_OK;
  1438. }
  1439. void mdns_free(mdns_server_t * server)
  1440. {
  1441. if (!server) {
  1442. return;
  1443. }
  1444. _mdns_server_remove(server);
  1445. mdns_service_remove_all(server);
  1446. MDNS_MUTEX_LOCK();
  1447. free((char*)server->hostname);
  1448. free((char*)server->instance);
  1449. if (server->queue) {
  1450. struct pbuf * c;
  1451. while(xQueueReceive(server->queue, &c, 0) == pdTRUE) {
  1452. pbuf_free(c);
  1453. }
  1454. vQueueDelete(server->queue);
  1455. }
  1456. if (server->search.running) {
  1457. mdns_query_end(server);
  1458. }
  1459. mdns_result_free(server);
  1460. vSemaphoreDelete(server->search.lock);
  1461. MDNS_MUTEX_UNLOCK();
  1462. vSemaphoreDelete(server->lock);
  1463. free(server);
  1464. }
  1465. esp_err_t mdns_set_hostname(mdns_server_t * server, const char * hostname)
  1466. {
  1467. if (!server) {
  1468. return ESP_ERR_INVALID_ARG;
  1469. }
  1470. if (strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) {
  1471. return ESP_ERR_INVALID_ARG;
  1472. }
  1473. MDNS_MUTEX_LOCK();
  1474. free((char*)server->hostname);
  1475. server->hostname = strndup(hostname, MDNS_NAME_BUF_LEN - 1);
  1476. if (!server->hostname) {
  1477. MDNS_MUTEX_UNLOCK();
  1478. return ESP_ERR_NO_MEM;
  1479. }
  1480. MDNS_MUTEX_UNLOCK();
  1481. return ERR_OK;
  1482. }
  1483. esp_err_t mdns_set_instance(mdns_server_t * server, const char * instance)
  1484. {
  1485. if (!server) {
  1486. return ESP_ERR_INVALID_ARG;
  1487. }
  1488. if (strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) {
  1489. return ESP_ERR_INVALID_ARG;
  1490. }
  1491. MDNS_MUTEX_LOCK();
  1492. free((char*)server->instance);
  1493. server->instance = strndup(instance, MDNS_NAME_BUF_LEN - 1);
  1494. if (!server->instance) {
  1495. MDNS_MUTEX_UNLOCK();
  1496. return ESP_ERR_NO_MEM;
  1497. }
  1498. MDNS_MUTEX_UNLOCK();
  1499. return ERR_OK;
  1500. }
  1501. /*
  1502. * MDNS SERVICES
  1503. * */
  1504. esp_err_t mdns_service_add(mdns_server_t * server, const char * service, const char * proto, uint16_t port)
  1505. {
  1506. if (!server || !service || !proto || !port) {
  1507. //bad argument
  1508. return ESP_ERR_INVALID_ARG;
  1509. }
  1510. mdns_srv_item_t * item = _mdns_get_service_item(server, service, proto);
  1511. if (item) {
  1512. //we already have that service
  1513. return mdns_service_port_set(server, service, proto, port);
  1514. }
  1515. mdns_service_t * s = _mdns_create_service(service, proto, port);
  1516. if (!s) {
  1517. return ESP_ERR_NO_MEM;
  1518. }
  1519. item = (mdns_srv_item_t *)malloc(sizeof(mdns_srv_item_t));
  1520. if (!item) {
  1521. return ESP_ERR_NO_MEM;
  1522. }
  1523. item->service = s;
  1524. item->next = server->services;
  1525. server->services = item;
  1526. return ESP_OK;
  1527. }
  1528. esp_err_t mdns_service_port_set(mdns_server_t * server, const char * service, const char * proto, uint16_t port)
  1529. {
  1530. if (!server || !server->services || !service || !proto || !port) {
  1531. return ESP_ERR_INVALID_ARG;
  1532. }
  1533. mdns_srv_item_t * s = _mdns_get_service_item(server, service, proto);
  1534. if (!s) {
  1535. return ESP_ERR_NOT_FOUND;
  1536. }
  1537. MDNS_MUTEX_LOCK();
  1538. s->service->port = port;
  1539. MDNS_MUTEX_UNLOCK();
  1540. return ESP_OK;
  1541. }
  1542. esp_err_t mdns_service_txt_set(mdns_server_t * server, const char * service, const char * proto, uint8_t num_items, const char ** txt)
  1543. {
  1544. if (!server || !server->services || !service || !proto) {
  1545. return ESP_ERR_INVALID_ARG;
  1546. }
  1547. mdns_srv_item_t * s = _mdns_get_service_item(server, service, proto);
  1548. if (!s) {
  1549. return ESP_ERR_NOT_FOUND;
  1550. }
  1551. MDNS_MUTEX_LOCK();
  1552. if (s->service->txt_num_items) {
  1553. uint8_t i;
  1554. for(i=0; i<s->service->txt_num_items; i++) {
  1555. free((char *)s->service->txt[i]);
  1556. }
  1557. }
  1558. free(s->service->txt);
  1559. if (num_items) {
  1560. s->service->txt = (const char **)malloc(sizeof(char *) * num_items);
  1561. if (!s->service->txt) {
  1562. s->service->txt_num_items = 0;
  1563. goto fail;
  1564. }
  1565. uint8_t i;
  1566. s->service->txt_num_items = num_items;
  1567. for(i=0; i<num_items; i++) {
  1568. s->service->txt[i] = strdup(txt[i]);
  1569. if (!s->service->txt[i]) {
  1570. s->service->txt_num_items = i;
  1571. goto fail;
  1572. }
  1573. }
  1574. }
  1575. MDNS_MUTEX_UNLOCK();
  1576. return ESP_OK;
  1577. fail:
  1578. MDNS_MUTEX_UNLOCK();
  1579. return ESP_ERR_NO_MEM;
  1580. }
  1581. esp_err_t mdns_service_instance_set(mdns_server_t * server, const char * service, const char * proto, const char * instance)
  1582. {
  1583. if (!server || !server->services || !service || !proto) {
  1584. return ESP_ERR_INVALID_ARG;
  1585. }
  1586. if (strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) {
  1587. return ESP_ERR_INVALID_ARG;
  1588. }
  1589. mdns_srv_item_t * s = _mdns_get_service_item(server, service, proto);
  1590. if (!s) {
  1591. return ESP_ERR_NOT_FOUND;
  1592. }
  1593. MDNS_MUTEX_LOCK();
  1594. free((char*)s->service->instance);
  1595. s->service->instance = strdup(instance);
  1596. if (!s->service->instance) {
  1597. MDNS_MUTEX_UNLOCK();
  1598. return ESP_ERR_NO_MEM;
  1599. }
  1600. MDNS_MUTEX_UNLOCK();
  1601. return ESP_OK;
  1602. }
  1603. esp_err_t mdns_service_remove(mdns_server_t * server, const char * service, const char * proto)
  1604. {
  1605. if (!server || !server->services || !service || !proto) {
  1606. return ESP_ERR_INVALID_ARG;
  1607. }
  1608. mdns_srv_item_t * s = _mdns_get_service_item(server, service, proto);
  1609. if (!s) {
  1610. return ESP_ERR_NOT_FOUND;
  1611. }
  1612. //first item
  1613. if (server->services == s) {
  1614. MDNS_MUTEX_LOCK();
  1615. server->services = server->services->next;
  1616. MDNS_MUTEX_UNLOCK();
  1617. _mdns_free_service(s->service);
  1618. free(s);
  1619. return ESP_OK;
  1620. }
  1621. //not first item
  1622. mdns_srv_item_t * a = server->services;
  1623. while(a->next && a->next != s) {
  1624. a = a->next;
  1625. }
  1626. //next item of the current item is our item
  1627. if (a->next == s) {
  1628. MDNS_MUTEX_LOCK();
  1629. a->next = s->next;
  1630. MDNS_MUTEX_UNLOCK();
  1631. _mdns_free_service(s->service);
  1632. free(s);
  1633. return ESP_OK;
  1634. }
  1635. //how did we end here?
  1636. return ESP_FAIL;
  1637. }
  1638. esp_err_t mdns_service_remove_all(mdns_server_t * server)
  1639. {
  1640. if (!server) {
  1641. return ESP_ERR_INVALID_ARG;
  1642. }
  1643. if (!server->services) {
  1644. return ESP_OK;
  1645. }
  1646. MDNS_MUTEX_LOCK();
  1647. mdns_srv_item_t * a = server->services;
  1648. server->services = NULL;
  1649. while(a) {
  1650. mdns_srv_item_t * s = a;
  1651. a = a->next;
  1652. _mdns_free_service(s->service);
  1653. free(s);
  1654. }
  1655. MDNS_MUTEX_UNLOCK();
  1656. return ESP_OK;
  1657. }
  1658. /*
  1659. * MDNS QUERY
  1660. * */
  1661. size_t mdns_query(mdns_server_t * server, const char * service, const char * proto, uint32_t timeout)
  1662. {
  1663. if (!server || !service) {
  1664. return 0;
  1665. }
  1666. MDNS_SEARCH_LOCK();
  1667. uint16_t qtype = MDNS_TYPE_PTR;
  1668. mdns_result_free(server);
  1669. if (proto) {
  1670. server->search.host[0] = 0;
  1671. strlcpy(server->search.service, service, MDNS_NAME_BUF_LEN);
  1672. strlcpy(server->search.proto, proto, MDNS_NAME_BUF_LEN);
  1673. } else {
  1674. strlcpy(server->search.host, service, MDNS_NAME_BUF_LEN);
  1675. server->search.service[0] = 0;
  1676. server->search.proto[0] = 0;
  1677. qtype = MDNS_TYPE_A;
  1678. }
  1679. uint8_t hostname_len = strlen(server->search.host);
  1680. uint8_t service_type_len = strlen(server->search.service);
  1681. uint8_t protoname_len = strlen(server->search.proto);
  1682. size_t len = 23; //head+type+class+(strlen(local)+1)+fqdn_end
  1683. if (hostname_len) {
  1684. len += hostname_len + 1;
  1685. } else if (service_type_len) {
  1686. len += service_type_len + protoname_len + 2;
  1687. }
  1688. uint8_t * packet = (uint8_t *)malloc(len);
  1689. if (!packet) {
  1690. return 0;
  1691. }
  1692. memset(packet, 0, len);
  1693. _mdns_set_u16(packet, MDNS_HEAD_QUESTIONS_OFFSET, 1);
  1694. uint16_t index = MDNS_HEAD_LEN;
  1695. if (hostname_len) {
  1696. _mdns_append_string(packet, &index, server->search.host);
  1697. } else if (service_type_len) {
  1698. _mdns_append_string(packet, &index, server->search.service);
  1699. _mdns_append_string(packet, &index, server->search.proto);
  1700. }
  1701. _mdns_append_string(packet, &index, MDNS_DEFAULT_DOMAIN);
  1702. _mdns_append_u8(packet, &index, 0); //fqdn_end
  1703. _mdns_append_u16(packet, &index, qtype);
  1704. _mdns_append_u16(packet, &index, MDNS_CLASS_IN);
  1705. MDNS_MUTEX_LOCK();
  1706. size_t written = _mdns_server_write(server, packet, index);
  1707. MDNS_MUTEX_UNLOCK();
  1708. free(packet);
  1709. if (written != index) {
  1710. return 0;
  1711. }
  1712. server->search.running = true;
  1713. if (timeout) {
  1714. uint32_t startAt = xTaskGetTickCount() * portTICK_PERIOD_MS;
  1715. while(server->search.running && ((xTaskGetTickCount() * portTICK_PERIOD_MS) - startAt) < timeout) {
  1716. vTaskDelay(1 / portTICK_PERIOD_MS);
  1717. }
  1718. server->search.running = false;
  1719. MDNS_SEARCH_UNLOCK();
  1720. return mdns_result_get_count(server);
  1721. }
  1722. return 0;
  1723. }
  1724. size_t mdns_query_end(mdns_server_t * server)
  1725. {
  1726. if (!server || !server->search.running) {
  1727. return 0;
  1728. }
  1729. server->search.running = false;
  1730. MDNS_SEARCH_UNLOCK();
  1731. return mdns_result_get_count(server);
  1732. }
  1733. esp_err_t mdns_result_free(mdns_server_t * server)
  1734. {
  1735. if (!server || server->search.running || !server->search.results) {
  1736. return ESP_ERR_INVALID_ARG;
  1737. }
  1738. while(server->search.results) {
  1739. const mdns_result_t * r = server->search.results;
  1740. server->search.results = (mdns_result_t *)r->next;
  1741. free((char *)r->host);
  1742. free((char *)r->instance);
  1743. free((char *)r->txt);
  1744. free((mdns_result_t *)r);
  1745. }
  1746. server->search.results = NULL;
  1747. return ESP_OK;
  1748. }
  1749. size_t mdns_result_get_count(mdns_server_t * server)
  1750. {
  1751. if (!server || !server->search.results) {
  1752. return 0;
  1753. }
  1754. size_t len = 0;
  1755. const mdns_result_t * r = server->search.results;
  1756. while(r) {
  1757. len++;
  1758. r = r->next;
  1759. }
  1760. return len;
  1761. }
  1762. const mdns_result_t * mdns_result_get(mdns_server_t * server, size_t num)
  1763. {
  1764. if (!server || !server->search.results) {
  1765. return NULL;
  1766. }
  1767. size_t len = 0;
  1768. const mdns_result_t * r = server->search.results;
  1769. while(r) {
  1770. if (len++ == num) {
  1771. return r;
  1772. }
  1773. r = r->next;
  1774. }
  1775. return NULL;
  1776. }