Skip to content

Commit 640abe5

Browse files
committed
Multicast in SoftAP mode (esp8266#96)
SDK 1.3 fixed a bug which caused multicast UDP to fail on SoftAP interface. Update MDNSResponder and documentation appropriately.
1 parent f9f998f commit 640abe5

File tree

3 files changed

+58
-55
lines changed

3 files changed

+58
-55
lines changed

hardware/esp8266com/esp8266/doc/reference.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,6 @@ When listening to multicast packets, replace `udp.begin(port)` with
290290
`udp.beginMulticast(WiFi.localIP(), multicast_ip_addr, port)`.
291291
You can use `udp.destinationIP()` to tell whether the packet received was
292292
sent to the multicast or unicast address.
293-
Also note that multicast doesn't work on softAP interface.
294293

295294
`WiFiServer`, `WiFiClient`, and `WiFiUDP` behave mostly the same way as with WiFi shield library.
296295
Four samples are provided for this library.
@@ -373,7 +372,6 @@ instead of the one that comes with this package.
373372
## mDNS and DNS-SD responder (ESP8266mDNS library)
374373
375374
Allows the sketch to respond to multicast DNS queries for domain names like "foo.local", and DNS-SD (service dicovery) queries.
376-
Currently the library only works on STA interface, AP interface is not supported.
377375
See attached example for details.
378376
379377
## SSDP responder (ESP8266SSDP)

hardware/esp8266com/esp8266/libraries/ESP8266mDNS/ESP8266mDNS.cpp

Lines changed: 54 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ License (MIT license):
3636

3737
#include "ESP8266mDNS.h"
3838
#include <functional>
39-
39+
4040
#include "debug.h"
4141

4242
extern "C" {
@@ -88,28 +88,28 @@ static const int MDNS_PORT = 5353;
8888
MDNSResponder::MDNSResponder() : _conn(0) { _services = 0; }
8989
MDNSResponder::~MDNSResponder() {}
9090

91-
bool MDNSResponder::begin(const char* domain){
91+
bool MDNSResponder::begin(const char* domain){
9292
// Open the MDNS socket if it isn't already open.
93-
93+
9494
size_t n = strlen(domain);
9595
if (n > 255) { // Can only handle domains that are 255 chars in length.
9696
return false;
9797
}
98-
98+
9999
// Copy in domain characters as lowercase
100100
for (int i = 0; i < n; ++i)
101101
_hostName[i] = tolower(domain[i]);
102102
_hostName[n] = '\0';
103-
103+
104104
os_strcpy(_boardName, ARDUINO_BOARD);
105-
105+
106106
// Open the MDNS socket if it isn't already open.
107107
if (!_conn) {
108108
uint32_t ourIp = _getOurIp();
109109
if(ourIp == 0){
110110
return false;
111111
}
112-
112+
113113
ip_addr_t ifaddr;
114114
ifaddr.addr = ourIp;
115115
ip_addr_t multicast_addr;
@@ -135,7 +135,7 @@ bool MDNSResponder::begin(const char* domain){
135135

136136
void MDNSResponder::update() {
137137
if (!_conn->next()) {
138-
return;
138+
return;
139139
}
140140
_parsePacket();
141141
}
@@ -163,15 +163,21 @@ uint16_t MDNSResponder::_getServicePort(char *name, char *proto){
163163
}
164164

165165
uint32_t MDNSResponder::_getOurIp(){
166-
if(wifi_get_opmode() & STATION_MODE){
166+
int mode = wifi_get_opmode();
167+
if(mode & STATION_MODE){
167168
struct ip_info staIpInfo;
168169
wifi_get_ip_info(STATION_IF, &staIpInfo);
169170
return staIpInfo.ip.addr;
170-
}
171+
} else if (mode & SOFTAP_MODE) {
172+
struct ip_info staIpInfo;
173+
wifi_get_ip_info(SOFTAP_IF, &staIpInfo);
174+
return staIpInfo.ip.addr;
175+
} else {
171176
#ifdef MDNS_DEBUG_ERR
172177
os_printf("ERR_NO_LOCAL_IP\n");
173178
#endif
174-
return 0;
179+
return 0;
180+
}
175181
}
176182

177183
void MDNSResponder::_parsePacket(){
@@ -180,52 +186,52 @@ void MDNSResponder::_parsePacket(){
180186
bool serviceParsed = false;
181187
bool protoParsed = false;
182188
bool localParsed = false;
183-
189+
184190
char hostName[255];
185191
uint8_t hostNameLen;
186-
192+
187193
char serviceName[32];
188194
uint8_t serviceNameLen;
189195
uint16_t servicePort;
190-
196+
191197
char protoName[32];
192198
uint8_t protoNameLen;
193-
199+
194200
uint16_t packetHeader[6];
195-
201+
196202
for(i=0; i<6; i++) packetHeader[i] = _conn_read16();
197203

198204
if((packetHeader[1] & 0x8000) != 0){ //not parsing responses yet
199205
_conn->flush();
200206
return;
201207
}
202-
208+
203209
// PARSE REQUEST NAME
204-
210+
205211
hostNameLen = _conn_read8();
206212
_conn_readS(hostName, hostNameLen);
207213
hostName[hostNameLen] = '\0';
208-
214+
209215
if(hostName[0] == '_'){
210216
serviceParsed = true;
211217
memcpy(serviceName, hostName+1, hostNameLen);
212218
serviceNameLen = hostNameLen-1;
213219
hostNameLen = 0;
214220
}
215-
221+
216222
if(hostNameLen > 0 && strcmp(_hostName, hostName) != 0){
217223
#ifdef MDNS_DEBUG_ERR
218224
os_printf("ERR_NO_HOST: %s\n", hostName);
219225
#endif
220226
_conn->flush();
221227
return;
222228
}
223-
229+
224230
if(!serviceParsed){
225231
serviceNameLen = _conn_read8();
226232
_conn_readS(serviceName, serviceNameLen);
227233
serviceName[serviceNameLen] = '\0';
228-
234+
229235
if(serviceName[0] == '_'){
230236
memcpy(serviceName, serviceName+1, serviceNameLen);
231237
serviceNameLen--;
@@ -253,7 +259,7 @@ void MDNSResponder::_parsePacket(){
253259
return;
254260
}
255261
}
256-
262+
257263
if(!protoParsed){
258264
protoNameLen = _conn_read8();
259265
_conn_readS(protoName, protoNameLen);
@@ -270,7 +276,7 @@ void MDNSResponder::_parsePacket(){
270276
return;
271277
}
272278
}
273-
279+
274280
if(!localParsed){
275281
char localName[32];
276282
uint8_t localNameLen = _conn_read8();
@@ -287,7 +293,7 @@ void MDNSResponder::_parsePacket(){
287293
return;
288294
}
289295
}
290-
296+
291297
if(serviceNameLen > 0 && protoNameLen > 0){
292298
servicePort = _getServicePort(serviceName, protoName);
293299
if(servicePort == 0){
@@ -304,16 +310,16 @@ void MDNSResponder::_parsePacket(){
304310
_conn->flush();
305311
return;
306312
}
307-
313+
308314
// RESPOND
309-
315+
310316
#ifdef MDNS_DEBUG_RX
311317
os_printf("RX: REQ, ID:%u, Q:%u, A:%u, NS:%u, ADD:%u\n", packetHeader[0], packetHeader[2], packetHeader[3], packetHeader[4], packetHeader[5]);
312318
#endif
313319

314320
uint16_t currentType;
315321
uint16_t currentClass;
316-
322+
317323
int numQuestions = packetHeader[2];
318324
if(numQuestions > 4) numQuestions = 4;
319325
uint16_t questions[4];
@@ -326,21 +332,21 @@ void MDNSResponder::_parsePacket(){
326332
}
327333
currentClass = _conn_read16();
328334
if(currentClass & MDNS_CLASS_IN) questions[question++] = currentType;
329-
335+
330336
if(numQuestions > 0){
331337
if(_conn_read16() != 0xC00C){//new question but for another host/service
332338
_conn->flush();
333339
numQuestions = 0;
334340
}
335341
}
336-
342+
337343
#ifdef MDNS_DEBUG_RX
338344
os_printf("REQ: ");
339345
if(hostNameLen > 0) os_printf("%s.", hostName);
340346
if(serviceNameLen > 0) os_printf("_%s.", serviceName);
341347
if(protoNameLen > 0) os_printf("_%s.", protoName);
342348
os_printf("local. ");
343-
349+
344350
if(currentType == MDNS_TYPE_AAAA) os_printf(" AAAA ");
345351
else if(currentType == MDNS_TYPE_A) os_printf(" A ");
346352
else if(currentType == MDNS_TYPE_PTR) os_printf(" PTR ");
@@ -351,7 +357,7 @@ void MDNSResponder::_parsePacket(){
351357
if(currentClass == MDNS_CLASS_IN) os_printf(" IN ");
352358
else if(currentClass == MDNS_CLASS_IN_FLUSH_CACHE) os_printf(" IN[F] ");
353359
else os_printf(" 0x%04X ", currentClass);
354-
360+
355361
os_printf("\n");
356362
#endif
357363
}
@@ -362,7 +368,7 @@ void MDNSResponder::_parsePacket(){
362368
else if(questions[i] == MDNS_TYPE_TXT) responseMask |= 0x4;
363369
else if(questions[i] == MDNS_TYPE_PTR) responseMask |= 0xF;
364370
}
365-
371+
366372
return _reply(responseMask, (serviceName), (protoName), servicePort);
367373
}
368374

@@ -371,14 +377,14 @@ void MDNSResponder::_parsePacket(){
371377
void MDNSResponder::_reply(uint8_t replyMask, char * service, char *proto, uint16_t port){
372378
int i;
373379
if(replyMask == 0) return;
374-
380+
375381
#ifdef MDNS_DEBUG_TX
376382
os_printf("TX: mask:%01X, service:%s, proto:%s, port:%u\n", replyMask, service, proto, port);
377383
#endif
378-
384+
379385
char nameLen = os_strlen(_hostName);
380386
size_t serviceLen = os_strlen(service);
381-
387+
382388
uint8_t answerCount = 0;
383389
for(i=0;i<4;i++){
384390
if(replyMask & (1 << i)) answerCount++;
@@ -394,12 +400,12 @@ void MDNSResponder::_reply(uint8_t replyMask, char * service, char *proto, uint1
394400
0x00, 0x00, //Additional records
395401
};
396402
_conn->append(reinterpret_cast<const char*>(head), 12);
397-
403+
398404
if((replyMask & 0x8) == 0){
399405
_conn->append(reinterpret_cast<const char*>(&nameLen), 1);
400406
_conn->append(reinterpret_cast<const char*>(_hostName), nameLen);
401407
}
402-
408+
403409
if(replyMask & 0xE){
404410
uint8_t servHead[2] = {(uint8_t)(serviceLen+1), '_'};
405411
uint8_t protoHead[2] = {0x4, '_'};
@@ -408,14 +414,14 @@ void MDNSResponder::_reply(uint8_t replyMask, char * service, char *proto, uint1
408414
_conn->append(reinterpret_cast<const char*>(protoHead), 2);
409415
_conn->append(reinterpret_cast<const char*>(proto), 3);
410416
}
411-
417+
412418
uint8_t local[7] = {
413419
0x05, //strlen(_local)
414420
0x6C, 0x6F, 0x63, 0x61, 0x6C, //local
415421
0x00, //End of domain
416422
};
417423
_conn->append(reinterpret_cast<const char*>(local), 7);
418-
424+
419425
// PTR Response
420426
if(replyMask & 0x8){
421427
uint8_t ptr[10] = {
@@ -430,16 +436,16 @@ void MDNSResponder::_reply(uint8_t replyMask, char * service, char *proto, uint1
430436
uint8_t ptrTail[2] = {0xC0, 0x0C};
431437
_conn->append(reinterpret_cast<const char*>(ptrTail), 2);
432438
}
433-
439+
434440
// TXT Response
435441
if(replyMask & 0x4){
436442
if(replyMask & 0x8){//send the name
437443
uint8_t txtHead[2] = {0xC0, (uint8_t)(36 + serviceLen)};
438444
_conn->append(reinterpret_cast<const char*>(txtHead), 2);
439445
}
440-
446+
441447
uint8_t boardNameLen = os_strlen(_boardName);
442-
448+
443449
uint8_t txt[24] = {
444450
0x00, 0x10, //Type TXT
445451
0x80, 0x01, //Class IN, with cache flush
@@ -450,9 +456,9 @@ void MDNSResponder::_reply(uint8_t replyMask, char * service, char *proto, uint1
450456
};
451457
_conn->append(reinterpret_cast<const char*>(txt), 17);
452458
_conn->append(reinterpret_cast<const char*>(_boardName), boardNameLen);
453-
459+
454460
}
455-
461+
456462
// SRV Response
457463
if(replyMask & 0x2){
458464
if(replyMask & 0xC){//send the name
@@ -461,7 +467,7 @@ void MDNSResponder::_reply(uint8_t replyMask, char * service, char *proto, uint1
461467
srvHead[1] = 36 + serviceLen;
462468
_conn->append(reinterpret_cast<const char*>(srvHead), 2);
463469
}
464-
470+
465471
uint8_t srv[16] = {
466472
0x00, 0x21, //Type SRV
467473
0x80, 0x01, //Class IN, with cache flush
@@ -479,7 +485,7 @@ void MDNSResponder::_reply(uint8_t replyMask, char * service, char *proto, uint1
479485
srvTail[1] = 19 + serviceLen;
480486
_conn->append(reinterpret_cast<const char*>(srvTail), 2);
481487
}
482-
488+
483489
// A Response
484490
if(replyMask & 0x1){
485491
uint32_t ip = _getOurIp();
@@ -488,7 +494,7 @@ void MDNSResponder::_reply(uint8_t replyMask, char * service, char *proto, uint1
488494
_conn->append(reinterpret_cast<const char*>(_hostName), nameLen);
489495
_conn->append(reinterpret_cast<const char*>(local), 7);
490496
}
491-
497+
492498
uint8_t aaa[14] = {
493499
0x00, 0x01, //TYPE A
494500
0x80, 0x01, //Class IN, with cache flush

hardware/esp8266com/esp8266/libraries/ESP8266mDNS/ESP8266mDNS.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@ implemented.
1313
1414
Usage:
1515
- Include the ESP8266 Multicast DNS library in the sketch.
16-
- Create an instance of the MDNSResponder class.
1716
- Call the begin method in the sketch's setup and provide a domain name (without
18-
the '.local' suffix, i.e. just provide 'foo' to resolve 'foo.local'), and the
19-
Adafruit CC3000 class instance. Optionally provide a time to live (in seconds)
17+
the '.local' suffix, i.e. just provide 'foo' to resolve 'foo.local'), and the
18+
Adafruit CC3000 class instance. Optionally provide a time to live (in seconds)
2019
for the DNS record--the default is 1 hour.
2120
- Call the update method in each iteration of the sketch's loop function.
2221
@@ -70,15 +69,15 @@ class MDNSResponder {
7069
return begin(hostName);
7170
}
7271
void update();
73-
72+
7473
void addService(char *service, char *proto, uint16_t port);
7574
void addService(const char *service, const char *proto, uint16_t port){
7675
addService((char *)service, (char *)proto, port);
7776
}
7877
void addService(String service, String proto, uint16_t port){
7978
addService(service.c_str(), proto.c_str(), port);
8079
}
81-
80+
8281
private:
8382
struct MDNSService * _services;
8483
UdpContext* _conn;

0 commit comments

Comments
 (0)