This repository has been archived by the owner on Jan 29, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathAsyncCaptivePortalAdvanced_STM32_LAN8720.ino
205 lines (155 loc) · 5.65 KB
/
AsyncCaptivePortalAdvanced_STM32_LAN8720.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/****************************************************************************************************************************
AsyncCaptivePortalAdvanced_STM32_LAN8720.ino
For STM32 with LAN8720 (STM32F4/F7)or built-in LAN8742A Ethernet (Nucleo-144, DISCOVERY, etc)
AsyncDNSServer_STM32 is a Async DNS Server library for the STM32 using built-in LAN8742A Ethernet
Based on and modified from ESPAsyncDNSServer Library (https://github.com/devyte/ESPAsyncDNSServer)
Built by Khoi Hoang https://github.com/khoih-prog/AsyncDNSServer_STM32
Licensed under MIT license
*****************************************************************************************************************************/
#include "defines.h"
#include <AsyncDNSServer_STM32.h>
#include <AsyncWebServer_STM32.h>
/*
This example serves a "hello world".
Now the STM32 is in your network. You can reach it through http://192.168.x.x/
This is a captive portal because it will redirect any http request to http://192.168.x.x/
*/
// DNS server
const byte DNS_PORT = 53;
AsyncDNSServer dnsServer;
// Web server
AsyncWebServer server(80);
IPAddress apIP;
/** Is this an IP? */
bool isIp(String str)
{
for (size_t i = 0; i < str.length(); i++)
{
int c = str.charAt(i);
if (c != '.' && (c < '0' || c > '9'))
{
return false;
}
}
return true;
}
/** IP to String? */
String toStringIp(IPAddress ip)
{
String res = "";
for (int i = 0; i < 3; i++)
{
res += String((ip >> (8 * i)) & 0xFF) + ".";
}
res += String(((ip >> 8 * 3)) & 0xFF);
return res;
}
/** Handle root or redirect to captive portal */
void handleRoot(AsyncWebServerRequest * request)
{
if (captivePortal(request))
{
// If captive portal redirect instead of displaying the page.
return;
}
String Page = F(
"<!DOCTYPE html><html lang='en'><head>"
"<meta name='viewport' content='width=device-width'>"
"<title>LAN8720-CaptivePortal</title></head><body>"
"<h1>HELLO WORLD!!</h1>");
Page += "<h2>From " + String(BOARD_NAME) + " using LAN8720</h2>";
AsyncWebServerResponse *response = request->beginResponse(200, "text/html", Page);
response->addHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response->addHeader("Pragma", "no-cache");
response->addHeader("Expires", "-1");
request->send(response);
}
// Redirect to captive portal if we got a request for another domain.
// Return true in that case so the page handler do not try to handle the request again.
bool captivePortal(AsyncWebServerRequest * request)
{
if (!isIp(request->host()))
{
Serial.println("Request redirected to captive portal");
// Empty content inhibits Content-length header so we have to close the socket ourselves.
AsyncWebServerResponse *response = request->beginResponse(302, "text/plain", "");
response->addHeader("Location", String("http://") + toStringIp(request->client()->localIP()));
request->send(response);
request->client()->stop(); // Stop is needed because we sent no content length
return true;
}
return false;
}
void handleNotFound(AsyncWebServerRequest * request)
{
if (captivePortal(request))
{
// If captive portal redirect instead of displaying the error page.
return;
}
String message = F("File Not Found\n\n");
message += F("URI: ");
message += request->url();
message += F("\nMethod: ");
message += (request->method() == HTTP_GET) ? "GET" : "POST";
message += F("\nArguments: ");
message += request->args();
message += F("\n");
for (uint8_t i = 0; i < request->args(); i++)
{
message += String(F(" ")) + request->argName(i) + F(": ") + request->arg(i) + F("\n");
}
AsyncWebServerResponse *response = request->beginResponse(404, "text/plain", message);
response->addHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response->addHeader("Pragma", "no-cache");
response->addHeader("Expires", "-1");
request->send(response);
}
void setup()
{
Serial.begin(115200);
delay(2000);
Serial.print("\nStart AsyncCaptivePortalAdvanced_STM32_LAN8720 on ");
Serial.println(BOARD_NAME);
Serial.println(ASYNC_DNS_SERVER_STM32_VERSION);
// start the ethernet connection and the server
// Use random mac
uint16_t index = millis() % NUMBER_OF_MAC;
// Use Static IP
//Ethernet.begin(mac[index], ip);
// Use DHCP dynamic IP and random mac
Ethernet.begin(mac[index]);;
apIP = Ethernet.localIP();
// modify TTL associated with the domain name (in seconds)
// default is 60 seconds
dnsServer.setTTL(300);
// set which return code will be used for all other domains (e.g. sending
// ServerFailure instead of NonExistentDomain will reduce number of queries
// sent by clients)
// default is AsyncDNSReplyCode::NonExistentDomain
dnsServer.setErrorReplyCode(AsyncDNSReplyCode::ServerFailure);
dnsServer.start(DNS_PORT, "*", apIP);
/* Setup web pages: root, wifi config pages, SO captive portal detectors and not found. */
// simple HTTP server to see that DNS server is working
server.on("/", HTTP_GET, [](AsyncWebServerRequest * request)
{
handleRoot(request);
});
//Android captive portal. Maybe not needed. Might be handled by notFound handler.
server.on("/generate_204", HTTP_GET, [](AsyncWebServerRequest * request)
{
handleRoot(request);
});
//Microsoft captive portal. Maybe not needed. Might be handled by notFound handler.
server.on("/fwlink", HTTP_GET, [](AsyncWebServerRequest * request)
{
handleRoot(request);
});
server.onNotFound(handleNotFound);
server.begin(); // Web server start
Serial.print(F("HTTP DNSServer is @ IP : "));
Serial.println(apIP);
}
void loop()
{
}