Skip to content

Fix issue #5507 "Constructor WebServer::WebServer(IPAddress addr, int… #5509

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Aug 23, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 173 additions & 0 deletions libraries/WebServer/examples/MultiHomedServers/MultiHomedServers.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>

/*
* MultiHomedServers
*
* MultiHomedServers tests support for multi-homed servers, i.e. a distinct web servers on each IP interface.
* It only tests the case n=2 because on a basic ESP32 device, we only have two IP interfaces, namely
* the WiFi station interfaces and the WiFi soft AP interface.
*
* For this to work, the WebServer and the WiFiServer classes must correctly handle the case where an
* IP address is passed to their relevant constructor. It also requires WebServer to work with multiple,
* simultaneous instances.
*
* Testing the WebServer and the WiFiServer constructors was the primary purpose of this script.
* The part of WebServer used by this sketch does seem to work with multiple, simultaneous instances.
* However there is much functionality in WebServer that is not tested here. It may all be well, but
* that is not proven here.
*
* This sketch starts the mDNS server, as did HelloServer, and it resolves esp32.local on both interfaces,
* but was not otherwise tested.
*
* This script also tests that a server not bound to a specific IP address still works.
*
* We create three, simultaneous web servers, one specific to each interface and one that listens on both:
*
* name IP Address Port
* ---- ---------- ----
* server0 INADDR_ANY 8080
* server1 station address 8081
* server2 soft AP address 8082
*
* The expected responses to a brower's requests are as follows:
*
* 1. when client connected to the same WLAN as the station:
* Request URL Response
* ----------- --------
* http://stationaddress:8080 "hello from server0"
* http://stationaddress:8081 "hello from server1"
* http://stationaddress:8082 browser reports failure to connect
*
* 2. when client is connected to the soft AP:
*
* Request URL Response
* ----------- --------
* http://softAPaddress:8080 "hello from server0"
* http://softAPaddress:8082 "hello from server2"
* http://softAPaddress:8081 browser reports failure to connect
*
* 3. Repeat 1 and 2 above with esp32.local in place of stationaddress and softAPaddress, respectively.
*
* MultiHomedServers was originally based on HelloServer.
*/

const char* ssid = "........";
const char* password = "........";
const char *apssid = "ESP32";

WebServer *server0, *server1, *server2;

const int led = 13;

void handleRoot(WebServer *server, const char *content) {
digitalWrite(led, 1);
server->send(200, "text/plain", content);
digitalWrite(led, 0);
}

void handleRoot0() {
handleRoot(server0, "hello from server0");
}

void handleRoot1() {
handleRoot(server1, "hello from server1");
}

void handleRoot2() {
handleRoot(server2, "hello from server2");
}

void handleNotFound(WebServer *server) {
digitalWrite(led, 1);
String message = "File Not Found\n\n";
message += "URI: ";
message += server->uri();
message += "\nMethod: ";
message += (server->method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: ";
message += server->args();
message += "\n";
for (uint8_t i = 0; i < server->args(); i++) {
message += " " + server->argName(i) + ": " + server->arg(i) + "\n";
}
server->send(404, "text/plain", message);
digitalWrite(led, 0);
}

void handleNotFound0() {
handleNotFound(server0);
}

void handleNotFound1() {
handleNotFound(server1);
}

void handleNotFound2() {
handleNotFound(server2);
}

void setup(void) {
pinMode(led, OUTPUT);
digitalWrite(led, 0);
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");

// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
if (!WiFi.softAP(apssid)) {
Serial.println("failed to start softAP");
for (;;) {
digitalWrite(led, 1);
delay(100);
digitalWrite(led, 0);
delay(100);
}
}
Serial.print("Soft AP: ");
Serial.print(apssid);
Serial.print(" IP address: ");
Serial.println(WiFi.softAPIP());

if (MDNS.begin("esp32")) {
Serial.println("MDNS responder started");
}

server0 = new WebServer(8080);
server1 = new WebServer(WiFi.localIP(), 8081);
server2 = new WebServer(WiFi.softAPIP(), 8082);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed port numbers as suggested. Expected results returned by test script. Pushed new commit. "All checks have passed".


server0->on("/", handleRoot0);
server1->on("/", handleRoot1);
server2->on("/", handleRoot2);

server0->onNotFound(handleNotFound0);
server1->onNotFound(handleNotFound1);
server2->onNotFound(handleNotFound2);

server0->begin();
Serial.println("HTTP server0 started");
server1->begin();
Serial.println("HTTP server1 started");
server2->begin();
Serial.println("HTTP server2 started");
}

void loop(void) {
server0->handleClient();
server1->handleClient();
server2->handleClient();
delay(2);//allow the cpu to switch to other tasks
}
4 changes: 3 additions & 1 deletion libraries/WebServer/src/WebServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ WebServer::WebServer(IPAddress addr, int port)
, _contentLength(0)
, _chunked(false)
{
log_v("WebServer::Webserver(addr=%s, port=%d)", addr.toString().c_str(), port);
}

WebServer::WebServer(int port)
Expand All @@ -81,6 +82,7 @@ WebServer::WebServer(int port)
, _contentLength(0)
, _chunked(false)
{
log_v("WebServer::Webserver(port=%d)", port);
}

WebServer::~WebServer() {
Expand Down Expand Up @@ -289,7 +291,7 @@ void WebServer::handleClient() {
return;
}

log_v("New client");
log_v("New client: client.localIP()=%s", client.localIP().toString().c_str());

_currentClient = client;
_currentStatus = HC_WAIT_READ;
Expand Down
2 changes: 1 addition & 1 deletion libraries/WiFi/src/WiFiServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ void WiFiServer::begin(uint16_t port, int enable){
return;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_addr.s_addr = _addr;
server.sin_port = htons(_port);
if(bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
return;
Expand Down
10 changes: 9 additions & 1 deletion libraries/WiFi/src/WiFiServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@
#include "Arduino.h"
#include "Server.h"
#include "WiFiClient.h"
#include "arpa/inet.h"
#include "IPAddress.h"

class WiFiServer : public Server {
private:
int sockfd;
int _accepted_sockfd = -1;
IPAddress _addr;
uint16_t _port;
uint8_t _max_clients;
bool _listening;
Expand All @@ -35,7 +38,12 @@ class WiFiServer : public Server {
public:
void listenOnLocalhost(){}

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){}
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) {
log_v("WiFiServer::WiFiServer(port=%d, ...)", port);
}
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) {
log_v("WiFiServer::WiFiServer(addr=%s, port=%d, ...)", addr.toString().c_str(), port);
}
~WiFiServer(){ end();}
WiFiClient available();
WiFiClient accept(){return available();}
Expand Down