Skip to content

Commit d912710

Browse files
vortigontlucasssvazme-no-dev
authored
DNSServer refactoring, switch to AsyncUDP (#7482)
* DNSServer: switch to AsyncUDP instead of WiFiUDP AsyncUDP offers event driven approch for handling udp dns req's WiFiUDP hooks to loop() for packet processing and making useless malloc's each run * DNSServer code refactoring get rid of intermediate mem buffers and extra data copies, most of the data could be referenced or copied from the source packet - removed _buffer member - replaced DNSQuestion.QName from uint8_t[] to char* added sanity checks for mem bounds optimize label/packet length calculations other code cleanup * DNSServer drop dynamically allocated member structs DNSHeader and DNSQuestion structs could be created on stack no need to keep it as obj members * DNSServer: labels min length checks, simplified labels parser * DNSServer use default settings for catch-all setup - default constructor and start() method simply runs a catch-all DNS setup - avoid string comparison for domain reqs in catch-all mode - use IPaddress class for _resolvedIP (looking for IPv6 support in future) * CaptivePortal example refactored - use webserver instead of simple tcp setver - use redirects to allows CaptivePortal detection pop-ups in modern systems * DNSServer status getters added add isUp() method - returns 'true' if server is up and UDP socket is listening for UDP req's add isCaptive() method - returns 'true' if server runs in catch-all (captive portal mode) some doxygen comments added start() method now keeps existing IP address if any --------- Co-authored-by: Lucas Saavedra Vaz <[email protected]> Co-authored-by: Me No Dev <[email protected]>
1 parent 44f83b0 commit d912710

File tree

3 files changed

+252
-199
lines changed

3 files changed

+252
-199
lines changed
+44-37
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,59 @@
1+
/*
2+
This example enables catch-all Captive portal for ESP32 Access-Point
3+
It will allow modern devices/OSes to detect that WiFi connection is
4+
limited and offer a user to access a banner web-page.
5+
There is no need to find and open device's IP address/URL, i.e. http://192.168.4.1/
6+
This works for Android, Ubuntu, FireFox, Windows, maybe others...
7+
*/
8+
9+
#include <Arduino.h>
110
#include <WiFi.h>
211
#include <DNSServer.h>
12+
#include <WebServer.h>
13+
314

4-
const byte DNS_PORT = 53;
5-
IPAddress apIP(8,8,4,4); // The default android DNS
615
DNSServer dnsServer;
7-
WiFiServer server(80);
16+
WebServer server(80);
17+
18+
static const char responsePortal[] = R"===(
19+
<!DOCTYPE html><html><head><title>ESP32 CaptivePortal</title></head><body>
20+
<h1>Hello World!</h1><p>This is a captive portal example page. All unknown http requests will
21+
be redirected here.</p></body></html>
22+
)===";
23+
24+
// index page handler
25+
void handleRoot() {
26+
server.send(200, "text/plain", "Hello from esp32!");
27+
}
828

9-
String responseHTML = ""
10-
"<!DOCTYPE html><html><head><title>CaptivePortal</title></head><body>"
11-
"<h1>Hello World!</h1><p>This is a captive portal example. All requests will "
12-
"be redirected here.</p></body></html>";
29+
// this will redirect unknown http req's to our captive portal page
30+
// based on this redirect various systems could detect that WiFi AP has a captive portal page
31+
void handleNotFound() {
32+
server.sendHeader("Location", "/portal");
33+
server.send(302, "text/plain", "redirect to captive portal");
34+
}
1335

14-
void setup() {
36+
void setup() {
37+
Serial.begin(115200);
1538
WiFi.mode(WIFI_AP);
1639
WiFi.softAP("ESP32-DNSServer");
17-
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
1840

19-
// if DNSServer is started with "*" for domain name, it will reply with
20-
// provided IP to all DNS request
21-
dnsServer.start(DNS_PORT, "*", apIP);
41+
// by default DNSServer is started serving any "*" domain name. It will reply
42+
// AccessPoint's IP to all DNS request (this is requred for Captive Portal detection)
43+
dnsServer.start();
44+
45+
// serve a simple root page
46+
server.on("/", handleRoot);
47+
48+
// serve portal page
49+
server.on("/portal",[](){server.send(200, "text/html", responsePortal);});
2250

51+
// all unknown pages are redirected to captive portal
52+
server.onNotFound(handleNotFound);
2353
server.begin();
2454
}
2555

2656
void loop() {
27-
dnsServer.processNextRequest();
28-
WiFiClient client = server.available(); // listen for incoming clients
29-
30-
if (client) {
31-
String currentLine = "";
32-
while (client.connected()) {
33-
if (client.available()) {
34-
char c = client.read();
35-
if (c == '\n') {
36-
if (currentLine.length() == 0) {
37-
client.println("HTTP/1.1 200 OK");
38-
client.println("Content-type:text/html");
39-
client.println();
40-
client.print(responseHTML);
41-
break;
42-
} else {
43-
currentLine = "";
44-
}
45-
} else if (c != '\r') {
46-
currentLine += c;
47-
}
48-
}
49-
}
50-
client.stop();
51-
}
57+
server.handleClient();
58+
delay(5); // give CPU some idle time
5259
}

0 commit comments

Comments
 (0)