Skip to content

Commit 1d28f6b

Browse files
authored
Merge pull request #837 from LeeLeahy2/page-not-found
WebSockets: Add page not found handler
2 parents 212ad2c + 19efd7d commit 1d28f6b

File tree

2 files changed

+182
-5
lines changed

2 files changed

+182
-5
lines changed

Firmware/RTK_Everywhere/RTK_Everywhere.ino

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ RTK_Everywhere.ino
181181
#include <NetworkClient.h>
182182
#include <NetworkClientSecure.h>
183183
#include <NetworkUdp.h>
184+
#include <lwip/sockets.h>
184185
#endif // COMPILE_NETWORK
185186

186187
#define RTK_MAX_CONNECTION_MSEC (15 * MILLISECONDS_IN_A_MINUTE)

Firmware/RTK_Everywhere/WebSockets.ino

Lines changed: 181 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,94 @@ void webSocketsCreateFirmwareVersionString(char *firmwareString)
132132
strcat(firmwareString, "\0");
133133
}
134134

135+
//----------------------------------------
136+
// Display the request
137+
//----------------------------------------
138+
void webSocketsDisplayRequest(httpd_req_t *req)
139+
{
140+
// Display the request and response
141+
if (settings.debugWebServer == true)
142+
{
143+
char ipAddress[80];
144+
145+
webSocketsGetClientIpAddressAndPort(req, ipAddress, sizeof(ipAddress));
146+
systemPrintf("WebServer Client: %s%s\r\n", ipAddress, req->uri);
147+
}
148+
}
149+
150+
//----------------------------------------
151+
// Get the client IP address
152+
//----------------------------------------
153+
void webSocketsGetClientIpAddressAndPort(httpd_req_t *req,
154+
char * ipAddress,
155+
size_t ipAddressBytes)
156+
{
157+
socklen_t addrBytes;
158+
const uint8_t ip4Address[12] =
159+
{
160+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff
161+
};
162+
struct sockaddr_in6 ip6Address;
163+
bool isIp6Address;
164+
size_t requiredStringLength;
165+
int socketFD;
166+
char temp[32 + 7 + 1];
167+
168+
// Validate the parameters
169+
if (ipAddress == nullptr)
170+
{
171+
systemPrintf("ERROR: ipAddress must be specified in WebSockets\r\n");
172+
return;
173+
}
174+
if (ipAddressBytes == 0)
175+
{
176+
systemPrintf("ERROR: ipAddressBytes must be > 0 in WebSockets\r\n");
177+
return;
178+
}
179+
ipAddress[0] = 0;
180+
181+
// Get the socket's file descriptor
182+
socketFD = httpd_req_to_sockfd(req);
183+
184+
// Get the IP6 address of the client from the httpd server
185+
addrBytes = sizeof(ip6Address);
186+
if (getpeername(socketFD, (struct sockaddr *)&ip6Address, &addrBytes) < 0)
187+
{
188+
if (settings.debugWebServer == true)
189+
systemPrintf("ERROR: WebSockets failed to get client IP address\r\n");
190+
return;
191+
}
192+
193+
// Determine the type of IP address
194+
isIp6Address = (memcmp(&ip6Address.sin6_addr, &ip4Address, sizeof(ip4Address)) != 0);
195+
196+
// Convert the IPv6 address into a string
197+
if (isIp6Address)
198+
inet_ntop(AF_INET6, &ip6Address.sin6_addr, temp, sizeof(temp));
199+
else
200+
inet_ntop(AF_INET, &ip6Address.sin6_addr.un.u8_addr[12], temp, sizeof(temp));
201+
202+
// Verify the length of the output buffer
203+
requiredStringLength = (isIp6Address ? 1 : 0) // Left bracket (IP6 only)
204+
+ strlen(temp) // IP address
205+
+ (isIp6Address ? 1 : 0) // Right bracket (IP6 only)
206+
+ 1 // Colon
207+
+ 5 // Port number
208+
+ 1; // Zero termination
209+
if (ipAddressBytes < requiredStringLength)
210+
{
211+
if (settings.debugWebServer == true)
212+
systemPrintf("ERROR: WebSockets failed to get client IP address\r\n");
213+
return;
214+
}
215+
216+
// Build the IP address string
217+
if (isIp6Address)
218+
sprintf(ipAddress, "[%s]:%d", temp, ip6Address.sin6_port);
219+
else
220+
sprintf(ipAddress, "%s:%d", temp, ip6Address.sin6_port);
221+
}
222+
135223
//----------------------------------------
136224
// Handler for web sockets requests
137225
//----------------------------------------
@@ -293,6 +381,56 @@ static esp_err_t webSocketsHandler(httpd_req_t *req)
293381
return ret;
294382
}
295383

384+
//----------------------------------------
385+
// Generate the Not Found page
386+
//----------------------------------------
387+
esp_err_t webSocketsHandlerPageNotFound(httpd_req_t *req, httpd_err_code_t err)
388+
{
389+
char ipAddress[80];
390+
String logMessage;
391+
392+
// Display an error
393+
webSocketsGetClientIpAddressAndPort(req, ipAddress, sizeof(ipAddress));
394+
logMessage = "WebSockets, Page ";
395+
logMessage += req->uri;
396+
logMessage += " not found, cliient: ";
397+
logMessage += ipAddress;
398+
systemPrintln(logMessage);
399+
400+
/*
401+
if (settings.enableCaptivePortal == true && knownCaptiveUrl(webServer->uri()) == true)
402+
{
403+
if (settings.debugWebServer == true)
404+
{
405+
String logmessage =
406+
"Known captive URI: " + webServer->client().remoteIP().toString() + " " + webServer->uri();
407+
systemPrintln(logmessage);
408+
}
409+
webServer->sendHeader("Location", "/");
410+
webServer->send(302, "text/plain", "Redirect to Web Config");
411+
return;
412+
}
413+
*/
414+
415+
// Set the 404 status code
416+
const char * statusText = "Error 404, page not found";
417+
httpd_resp_set_status(req, statusText);
418+
419+
// Set the content type
420+
httpd_resp_set_type(req, "text/html");
421+
422+
// Send the response
423+
String htmlResponse = "<h1>";
424+
htmlResponse += statusText;
425+
htmlResponse += "</h1><p>The requested page (";
426+
htmlResponse += req->uri;
427+
htmlResponse += ") was not found.</p>";
428+
httpd_resp_send(req, htmlResponse.c_str(), htmlResponse.length());
429+
430+
// Return ESP_OK to indicate the error was handled successfully
431+
return ESP_OK;
432+
}
433+
296434
//----------------------------------------
297435
// Determine if webSockets is connected to a client
298436
//----------------------------------------
@@ -301,6 +439,26 @@ bool webSocketsIsConnected()
301439
return (webSocketsClientListHead != nullptr);
302440
}
303441

442+
//----------------------------------------
443+
// Register an error handler
444+
//----------------------------------------
445+
bool webSocketsRegisterErrorHandler(httpd_err_code_t error,
446+
httpd_err_handler_func_t handler)
447+
{
448+
esp_err_t status;
449+
450+
// Register the error handler
451+
status = httpd_register_err_handler(webSocketsHandle, error, handler);
452+
if (settings.debugWebServer == true)
453+
{
454+
if (status == ESP_OK)
455+
systemPrintf("webSockets registered %d error handler\r\n", error);
456+
else
457+
systemPrintf("webSockets Failed to register %d error handler!\r\n", error);
458+
}
459+
return (status == ESP_OK);
460+
}
461+
304462
//----------------------------------------
305463
// Send the formware version via web sockets
306464
//----------------------------------------
@@ -460,11 +618,29 @@ bool webSocketsStart(void)
460618
status = httpd_start(&webSocketsHandle, &config);
461619
if (status == ESP_OK)
462620
{
463-
// Registering the ws handler
464-
if (settings.debugWebServer == true)
465-
systemPrintln("webSockets registering URI handlers");
466-
httpd_register_uri_handler(webSocketsHandle, &webSocketsPage);
467-
return true;
621+
do
622+
{
623+
if (settings.debugWebServer == true)
624+
systemPrintln("webSockets registering page handlers");
625+
626+
// Register the page not found (404) error handler
627+
if (!webSocketsRegisterErrorHandler(HTTPD_404_NOT_FOUND,
628+
webSocketsHandlerPageNotFound))
629+
break;
630+
631+
// Registering the ws handler
632+
if (settings.debugWebServer == true)
633+
systemPrintln("webSockets registering URI handlers");
634+
httpd_register_uri_handler(webSocketsHandle, &webSocketsPage);
635+
636+
// The web server is ready to handle incoming requests
637+
if (settings.debugWebServer)
638+
systemPrintf("webSockets successfully started\r\n");
639+
return true;
640+
} while (0);
641+
642+
// Stop the web server
643+
httpd_stop(webSocketsHandle);
468644
}
469645

470646
// Display the failure to start

0 commit comments

Comments
 (0)