Skip to content

Commit 29455a0

Browse files
authored
Fix issue #5507 "Constructor WebServer::WebServer(IPAddress addr, int… (#5509)
* Fix issue #5507 "Constructor WebServer::WebServer(IPAddress addr, int port) produces an unexpected result" "The class Webserver is declared with two explicit constructors, one with signature: WebServer::WebServer(IPAddress addr, int port) Using this results in a server listening on the port number obtained by converting the value of the IPAddress addr argument (in host byte order) to a uint32_t and then to a uint16_t, which is manifestly not the result that would be expected. ... As for a fix, we can assume from these results that this constructor is not being used and therefore could simply be deleted." * Issue 5507 Reverse changes in commit bee1e70 after discussion. Alternative fix to be done. * Fix issue #5507 "Constructor WebServer::WebServer(IPAddress addr, int port) produces an unexpected result" This change adds support for multi-homed servers to libraries/WiFi. It was assumed to be there already by libraries/WebServer, but was not. This led to unexpected results when the IP address-specific constructor of class WebServer was used (see issue 5507). This change was tested using three concurrent instances of WebServer, one bound to the WiFi station address, one bound to the WiFi soft AP address, and one bound to INADDR_ANY. See libraries/WebServer/examples/MultiHomedServers for the test method. * Fix issue #5507 "Constructor WebServer::WebServer(IPAddress addr, int port) produces an unexpected result" (cont.) This fixes what I think might be the cause of CI failures on GitHub for the previous commit, namely the absence of an include file in examples/MultiHomedServers. * Fix issue #5507 "Constructor WebServer::WebServer(IPAddress addr, int port) produces an unexpected result" (cont.) Change port numbers in examples/MultiHomedServers per pull-request comment from me-no-dev ... "for this test to be valid, both servers should be on the same port. That is how you can make sure that the functionality works."
1 parent 78499c4 commit 29455a0

File tree

4 files changed

+184
-3
lines changed

4 files changed

+184
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
#include <WiFi.h>
2+
#include <WiFiClient.h>
3+
#include <WebServer.h>
4+
#include <ESPmDNS.h>
5+
6+
/*
7+
* MultiHomedServers
8+
*
9+
* MultiHomedServers tests support for multi-homed servers, i.e. a distinct web servers on each IP interface.
10+
* It only tests the case n=2 because on a basic ESP32 device, we only have two IP interfaces, namely
11+
* the WiFi station interfaces and the WiFi soft AP interface.
12+
*
13+
* For this to work, the WebServer and the WiFiServer classes must correctly handle the case where an
14+
* IP address is passed to their relevant constructor. It also requires WebServer to work with multiple,
15+
* simultaneous instances.
16+
*
17+
* Testing the WebServer and the WiFiServer constructors was the primary purpose of this script.
18+
* The part of WebServer used by this sketch does seem to work with multiple, simultaneous instances.
19+
* However there is much functionality in WebServer that is not tested here. It may all be well, but
20+
* that is not proven here.
21+
*
22+
* This sketch starts the mDNS server, as did HelloServer, and it resolves esp32.local on both interfaces,
23+
* but was not otherwise tested.
24+
*
25+
* This script also tests that a server not bound to a specific IP address still works.
26+
*
27+
* We create three, simultaneous web servers, one specific to each interface and one that listens on both:
28+
*
29+
* name IP Address Port
30+
* ---- ---------- ----
31+
* server0 INADDR_ANY 8080
32+
* server1 station address 8081
33+
* server2 soft AP address 8081
34+
*
35+
* The expected responses to a brower's requests are as follows:
36+
*
37+
* 1. when client connected to the same WLAN as the station:
38+
* Request URL Response
39+
* ----------- --------
40+
* http://stationaddress:8080 "hello from server0"
41+
* http://stationaddress:8081 "hello from server1"
42+
*
43+
* 2. when client is connected to the soft AP:
44+
*
45+
* Request URL Response
46+
* ----------- --------
47+
* http://softAPaddress:8080 "hello from server0"
48+
* http://softAPaddress:8081 "hello from server2"
49+
*
50+
* 3. Repeat 1 and 2 above with esp32.local in place of stationaddress and softAPaddress, respectively.
51+
*
52+
* MultiHomedServers was originally based on HelloServer.
53+
*/
54+
55+
const char* ssid = "........";
56+
const char* password = "........";
57+
const char *apssid = "ESP32";
58+
59+
WebServer *server0, *server1, *server2;
60+
61+
const int led = 13;
62+
63+
void handleRoot(WebServer *server, const char *content) {
64+
digitalWrite(led, 1);
65+
server->send(200, "text/plain", content);
66+
digitalWrite(led, 0);
67+
}
68+
69+
void handleRoot0() {
70+
handleRoot(server0, "hello from server0");
71+
}
72+
73+
void handleRoot1() {
74+
handleRoot(server1, "hello from server1");
75+
}
76+
77+
void handleRoot2() {
78+
handleRoot(server2, "hello from server2");
79+
}
80+
81+
void handleNotFound(WebServer *server) {
82+
digitalWrite(led, 1);
83+
String message = "File Not Found\n\n";
84+
message += "URI: ";
85+
message += server->uri();
86+
message += "\nMethod: ";
87+
message += (server->method() == HTTP_GET) ? "GET" : "POST";
88+
message += "\nArguments: ";
89+
message += server->args();
90+
message += "\n";
91+
for (uint8_t i = 0; i < server->args(); i++) {
92+
message += " " + server->argName(i) + ": " + server->arg(i) + "\n";
93+
}
94+
server->send(404, "text/plain", message);
95+
digitalWrite(led, 0);
96+
}
97+
98+
void handleNotFound0() {
99+
handleNotFound(server0);
100+
}
101+
102+
void handleNotFound1() {
103+
handleNotFound(server1);
104+
}
105+
106+
void handleNotFound2() {
107+
handleNotFound(server2);
108+
}
109+
110+
void setup(void) {
111+
pinMode(led, OUTPUT);
112+
digitalWrite(led, 0);
113+
Serial.begin(115200);
114+
WiFi.mode(WIFI_STA);
115+
WiFi.begin(ssid, password);
116+
Serial.println("");
117+
118+
// Wait for connection
119+
while (WiFi.status() != WL_CONNECTED) {
120+
delay(500);
121+
Serial.print(".");
122+
}
123+
Serial.println("");
124+
Serial.print("Connected to ");
125+
Serial.println(ssid);
126+
Serial.print("IP address: ");
127+
Serial.println(WiFi.localIP());
128+
if (!WiFi.softAP(apssid)) {
129+
Serial.println("failed to start softAP");
130+
for (;;) {
131+
digitalWrite(led, 1);
132+
delay(100);
133+
digitalWrite(led, 0);
134+
delay(100);
135+
}
136+
}
137+
Serial.print("Soft AP: ");
138+
Serial.print(apssid);
139+
Serial.print(" IP address: ");
140+
Serial.println(WiFi.softAPIP());
141+
142+
if (MDNS.begin("esp32")) {
143+
Serial.println("MDNS responder started");
144+
}
145+
146+
server0 = new WebServer(8080);
147+
server1 = new WebServer(WiFi.localIP(), 8081);
148+
server2 = new WebServer(WiFi.softAPIP(), 8081);
149+
150+
server0->on("/", handleRoot0);
151+
server1->on("/", handleRoot1);
152+
server2->on("/", handleRoot2);
153+
154+
server0->onNotFound(handleNotFound0);
155+
server1->onNotFound(handleNotFound1);
156+
server2->onNotFound(handleNotFound2);
157+
158+
server0->begin();
159+
Serial.println("HTTP server0 started");
160+
server1->begin();
161+
Serial.println("HTTP server1 started");
162+
server2->begin();
163+
Serial.println("HTTP server2 started");
164+
}
165+
166+
void loop(void) {
167+
server0->handleClient();
168+
server1->handleClient();
169+
server2->handleClient();
170+
delay(2);//allow the cpu to switch to other tasks
171+
}

Diff for: libraries/WebServer/src/WebServer.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ WebServer::WebServer(IPAddress addr, int port)
5959
, _contentLength(0)
6060
, _chunked(false)
6161
{
62+
log_v("WebServer::Webserver(addr=%s, port=%d)", addr.toString().c_str(), port);
6263
}
6364

6465
WebServer::WebServer(int port)
@@ -81,6 +82,7 @@ WebServer::WebServer(int port)
8182
, _contentLength(0)
8283
, _chunked(false)
8384
{
85+
log_v("WebServer::Webserver(port=%d)", port);
8486
}
8587

8688
WebServer::~WebServer() {
@@ -289,7 +291,7 @@ void WebServer::handleClient() {
289291
return;
290292
}
291293

292-
log_v("New client");
294+
log_v("New client: client.localIP()=%s", client.localIP().toString().c_str());
293295

294296
_currentClient = client;
295297
_currentStatus = HC_WAIT_READ;

Diff for: libraries/WiFi/src/WiFiServer.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ void WiFiServer::begin(uint16_t port, int enable){
8282
return;
8383
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
8484
server.sin_family = AF_INET;
85-
server.sin_addr.s_addr = INADDR_ANY;
85+
server.sin_addr.s_addr = _addr;
8686
server.sin_port = htons(_port);
8787
if(bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
8888
return;

Diff for: libraries/WiFi/src/WiFiServer.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@
2222
#include "Arduino.h"
2323
#include "Server.h"
2424
#include "WiFiClient.h"
25+
#include "arpa/inet.h"
26+
#include "IPAddress.h"
2527

2628
class WiFiServer : public Server {
2729
private:
2830
int sockfd;
2931
int _accepted_sockfd = -1;
32+
IPAddress _addr;
3033
uint16_t _port;
3134
uint8_t _max_clients;
3235
bool _listening;
@@ -35,7 +38,12 @@ class WiFiServer : public Server {
3538
public:
3639
void listenOnLocalhost(){}
3740

38-
WiFiServer(uint16_t port=80, uint8_t max_clients=4):sockfd(-1),_accepted_sockfd(-1),_port(port),_max_clients(max_clients),_listening(false),_noDelay(false){}
41+
WiFiServer(uint16_t port=80, uint8_t max_clients=4):sockfd(-1),_accepted_sockfd(-1),_addr(INADDR_ANY),_port(port),_max_clients(max_clients),_listening(false),_noDelay(false) {
42+
log_v("WiFiServer::WiFiServer(port=%d, ...)", port);
43+
}
44+
WiFiServer(const IPAddress& addr, uint16_t port=80, uint8_t max_clients=4):sockfd(-1),_accepted_sockfd(-1),_addr(addr),_port(port),_max_clients(max_clients),_listening(false),_noDelay(false) {
45+
log_v("WiFiServer::WiFiServer(addr=%s, port=%d, ...)", addr.toString().c_str(), port);
46+
}
3947
~WiFiServer(){ end();}
4048
WiFiClient available();
4149
WiFiClient accept(){return available();}

0 commit comments

Comments
 (0)