@@ -5,6 +5,7 @@ Version 1.1
5
5
Copyright (c) 2013 Tony DiCola (tony@tonydicola.com)
6
6
ESP8266 port (c) 2015 Ivan Grokhotkov (ivan@esp8266.com)
7
7
MDNS-SD Suport 2015 Hristo Gochkov
8
+ Extended MDNS-SD support 2016 Lars Englund
8
9
9
10
10
11
License (MIT license):
@@ -104,6 +105,7 @@ struct MDNSTxt{
104
105
MDNSResponder::MDNSResponder () : _conn(0 ) {
105
106
_services = 0 ;
106
107
_instanceName = " " ;
108
+ p_answer_function_ = NULL ;
107
109
}
108
110
MDNSResponder::~MDNSResponder () {}
109
111
@@ -221,6 +223,90 @@ void MDNSResponder::addService(char *name, char *proto, uint16_t port){
221
223
222
224
}
223
225
226
+ void MDNSResponder::queryService (char *service, void (*p_answer_function)(const char *)) {
227
+ Serial.print (" queryService: " );
228
+ Serial.println (service);
229
+ p_answer_function_ = p_answer_function;
230
+
231
+ // TODO: copy _reply() to new method called _query() that sends out a PTR query
232
+ // Relevant RFCs
233
+ // https://tools.ietf.org/html/rfc1035
234
+ // https://tools.ietf.org/html/rfc6762
235
+ // https://tools.ietf.org/html/rfc6763
236
+
237
+
238
+ // Example query sent by node.js for _lalala._tcp.local
239
+ // 0000 00 00 00 00 00 01 00 00 00 00 00 00 07 5f 6c 61 ............._la
240
+ // 0010 6c 61 6c 61 04 5f 74 63 70 05 6c 6f 63 61 6c 00 lala._tcp.local.
241
+ // 0020 00 0c 00 01 ....
242
+
243
+ // String instanceName = _instanceName;
244
+ // size_t instanceNameLen = instanceName.length();
245
+
246
+ // String hostName = _hostName;
247
+ // size_t hostNameLen = hostName.length();
248
+
249
+ // char underscore[] = "_";
250
+
251
+ // build service name with _
252
+ char serviceName[] = " _esp" ;
253
+ size_t serviceNameLen = 4 ;
254
+
255
+ // build proto name with _
256
+ char protoName[] = " _tcp" ;
257
+ size_t protoNameLen = 4 ;
258
+
259
+ // local string
260
+ char localName[] = " local" ;
261
+ size_t localNameLen = 5 ;
262
+
263
+ // terminator
264
+ char terminator[] = " \0 " ;
265
+
266
+ uint8_t questionCount = 1 ;
267
+
268
+ // Write the header
269
+ _conn->flush ();
270
+ uint8_t head[12 ] = {
271
+ 0x00 , 0x00 , // ID = 0
272
+ 0x00 , 0x00 , // Flags = response + authoritative answer
273
+ 0x00 , questionCount, // Question count
274
+ 0x00 , 0x00 , // Answer count
275
+ 0x00 , 0x00 , // Name server records
276
+ 0x00 , 0x00 // Additional records
277
+ };
278
+ _conn->append (reinterpret_cast <const char *>(head), 12 );
279
+
280
+ // PTR Query
281
+ // if(replyMask & 0x8){
282
+ // Send the Name field (eg. "_http._tcp.local")
283
+ _conn->append (reinterpret_cast <const char *>(&serviceNameLen), 1 ); // lenght of "_" + service
284
+ _conn->append (reinterpret_cast <const char *>(serviceName), serviceNameLen); // "_" + service
285
+ _conn->append (reinterpret_cast <const char *>(&protoNameLen), 1 ); // lenght of "_" + proto
286
+ _conn->append (reinterpret_cast <const char *>(protoName), protoNameLen); // "_" + proto
287
+ _conn->append (reinterpret_cast <const char *>(&localNameLen), 1 ); // lenght "local"
288
+ _conn->append (reinterpret_cast <const char *>(localName), localNameLen); // "local"
289
+ _conn->append (reinterpret_cast <const char *>(&terminator), 1 ); // terminator
290
+
291
+ // Send the type and class
292
+ // uint8_t ptrDataLen = instanceNameLen + serviceNameLen + protoNameLen + localNameLen + 5; // 5 is four label sizes and the terminator
293
+ uint8_t ptrAttrs[4 ] = {
294
+ 0x00 , 0x0c , // PTR record query
295
+ 0x00 , 0x01 // Class IN
296
+ };
297
+ _conn->append (reinterpret_cast <const char *>(ptrAttrs), 4 );
298
+ // }
299
+
300
+ _conn->send ();
301
+
302
+ /* const char *answer = "Hello from MDNSResponder!";
303
+
304
+ if (p_answer_function_) {
305
+ // Since a callback function has been registered, execute it.
306
+ p_answer_function_(answer);
307
+ }*/
308
+ }
309
+
224
310
MDNSTxt * MDNSResponder::_getServiceTxt (char *name, char *proto){
225
311
MDNSService* servicePtr;
226
312
for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next ) {
@@ -298,6 +384,95 @@ void MDNSResponder::_parsePacket(){
298
384
for (i=0 ; i<6 ; i++) packetHeader[i] = _conn_read16 ();
299
385
300
386
if ((packetHeader[1 ] & 0x8000 ) != 0 ){ // not parsing responses yet
387
+
388
+ Serial.println (" Response parsing" );
389
+ Serial.printf (" RX: REQ, ID:%u, Q:%u, A:%u, NS:%u, ADD:%u\n " , packetHeader[0 ], packetHeader[2 ], packetHeader[3 ], packetHeader[4 ], packetHeader[5 ]);
390
+
391
+ int numAnswers = packetHeader[3 ];
392
+
393
+ // TODO: parse answers and call p_answer_function_ with host (.local), IP, port,
394
+ // http://www.ietf.org/rfc/rfc1035.txt
395
+
396
+ // TODO: Parse 4 answers in 1 packet (that's what this library sends out, check if node.js mqtt advertisment sends out different answers (use esp8266_mdns to check)):
397
+ // 1. PTR - ignore for now (gives domain name (instance.service) (ex. Domain Name: ESP_81CC47._lalala._tcp.local))
398
+ // 2. TXT - ignore for now
399
+ // 3. SRV - gives service name, protocol, port and target host
400
+ // 4. A - gives ip addr of target host
401
+
402
+ /*
403
+ PTR
404
+ 0000 07 5f 6c 61 6c 61 6c 61 04 5f 74 63 70 05 6c 6f ._lalala._tcp.lo
405
+ 0010 63 61 6c 00 00 0c 00 01 00 00 11 94 00 1f 0a 45 cal............E
406
+ 0020 53 50 5f 38 31 43 43 34 37 07 5f 6c 61 6c 61 6c SP_81CC47._lalal
407
+ 0030 61 04 5f 74 63 70 05 6c 6f 63 61 6c 00 a._tcp.local.
408
+ */
409
+ uint8_t tmp8;
410
+ uint16_t tmp16;
411
+ uint32_t tmp32;
412
+
413
+ while (numAnswers--) {
414
+ Serial.println (" Parsing answer.." );
415
+ // Skip name
416
+ tmp8 = _conn_read8 ();
417
+ if (tmp8 & 0xC0 ) { // Compressed
418
+ tmp8 = _conn_read8 ();
419
+ }
420
+ else { // Not compressed
421
+ while (tmp8 != 0x00 ) {
422
+ Serial.print (" " );
423
+ Serial.print (tmp8);
424
+ _conn_readS (hostName, tmp8);
425
+ Serial.printf (" %s " , hostName);
426
+ tmp8 = _conn_read8 ();
427
+ if (tmp8 & 0xC0 ) { // Compressed
428
+ tmp8 = _conn_read8 ();
429
+ break ;
430
+ }
431
+ }
432
+ }
433
+ uint16_t type = _conn_read16 (); // Read type
434
+ if (type == MDNS_TYPE_PTR) {
435
+ Serial.println (" Got a PTR answer!" );
436
+ }
437
+ if (type == MDNS_TYPE_TXT) {
438
+ Serial.println (" Got a TXT answer!" );
439
+ }
440
+ if (type == MDNS_TYPE_SRV) {
441
+ Serial.println (" Got a SRV answer!" );
442
+ }
443
+ if (type == MDNS_TYPE_A) {
444
+ Serial.println (" Got a A answer!" );
445
+ }
446
+ tmp16 = _conn_read16 (); // Skip class
447
+ tmp32 = _conn_read32 (); // Skip ttl
448
+ tmp16 = _conn_read16 (); // Skip rdlength
449
+ Serial.println (" \n skip " );
450
+ Serial.print (tmp16);
451
+ _conn_readS (hostName, tmp16); // Skip rdata
452
+ Serial.printf (" %s " , hostName);
453
+ }
454
+ Serial.println (" All answers parsed!" );
455
+ /*
456
+ TXT
457
+ 0000 0a 45 53 50 5f 38 31 43 43 34 37 07 5f 6c 61 6c .ESP_81CC47._lal
458
+ 0010 61 6c 61 04 5f 74 63 70 05 6c 6f 63 61 6c 00 00 ala._tcp.local..
459
+ 0020 10 00 01 00 00 11 94 00 00 .........
460
+ */
461
+
462
+ /*
463
+ SRV
464
+ 0000 0a 45 53 50 5f 38 31 43 43 34 37 07 5f 6c 61 6c .ESP_81CC47._lal
465
+ 0010 61 6c 61 04 5f 74 63 70 05 6c 6f 63 61 6c 00 00 ala._tcp.local..
466
+ 0020 21 80 01 00 00 00 78 00 18 00 00 00 00 1f 90 0a !.....x.........
467
+ 0030 65 73 70 5f 38 31 63 63 34 37 05 6c 6f 63 61 6c esp_81cc47.local
468
+ 0040 00 .
469
+ */
470
+ /*
471
+ A
472
+ 0000 0a 65 73 70 5f 38 31 63 63 34 37 05 6c 6f 63 61 .esp_81cc47.loca
473
+ 0010 6c 00 00 01 80 01 00 00 00 78 00 04 c0 a8 01 0c l........x......
474
+ */
475
+
301
476
_conn->flush ();
302
477
return ;
303
478
}
0 commit comments