Webserver running on Core0 issues

spyder0069
Posts: 35
Joined: Tue Jan 29, 2019 2:46 am

Webserver running on Core0 issues

Postby spyder0069 » Tue Jan 29, 2019 3:04 am

I have a program that I am utilizing core1 for some tight timing application so I am using core0 for webserver and user interface. When I run a the simple webserver example and pin it to core0 this is what I get:

It will server a page fine. I can jump to the next page fine.

If I use a page that has a form that posts such as a login it will work fine if its posting back to itself.

If I use a page that has a form that posts data which then sets a cookie or goes to another page using the

Code: Select all

 server.sendHeader("Location", "/"); 
Then the browser almost always gives " This site can’t be reached The connection was reset."

If you do a refresh on the browser it recovers.

If you run the handleclient command in the core1 loop everything is happy and works. I feel like the native wifi tasks running on core0 are causing the reset somehow? Its fine for single page but anything that requires more gives the browser reset.

My initial solution was to switch the handleclient over to the core1 in my program anytime I needed more than a single page but this does interrupt my task there and would prefer it to run totally on core0. I appreciate any advice!

spyder0069
Posts: 35
Joined: Tue Jan 29, 2019 2:46 am

Re: Webserver running on Core0 issues

Postby spyder0069 » Tue Jan 29, 2019 3:45 am

Here is a code example that recreates the failure. It is the SimpleAuthentification example that is built in slightly modified to be pinned to core0. Wifi credentials would need to be inserted for your router.

Code: Select all

TaskHandle_t Task0;
TaskHandle_t Task1;

#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>

const char* ssid = "xxxxxxxxx";
const char* password = "xxxxxxxx";

WebServer server(80);

//Check if header is present and correct
bool is_authentified() {
  Serial.println("Enter is_authentified");
  if (server.hasHeader("Cookie")) {
    Serial.print("Found cookie: ");
    String cookie = server.header("Cookie");
    Serial.println(cookie);
    if (cookie.indexOf("ESPSESSIONID=1") != -1) {
      Serial.println("Authentification Successful");
      return true;
    }
  }
  Serial.println("Authentification Failed");
  return false;
}

//login page, also called for disconnect
void handleLogin() {
  String msg;
  if (server.hasHeader("Cookie")) {
    Serial.print("Found cookie: ");
    String cookie = server.header("Cookie");
    Serial.println(cookie);
  }
  if (server.hasArg("DISCONNECT")) {
    Serial.println("Disconnection");
    server.sendHeader("Location", "/login");
    server.sendHeader("Cache-Control", "no-cache");
    server.sendHeader("Set-Cookie", "ESPSESSIONID=0");
    server.send(301);
    return;
  }
  if (server.hasArg("PASSWORD")) {
    if (server.arg("PASSWORD") == "admin") {
      server.sendHeader("Location", "/");
      server.sendHeader("Cache-Control", "no-cache");
      server.sendHeader("Set-Cookie", "ESPSESSIONID=1");
      server.send(301);
      Serial.println("Log in Successful");
      return;
    }
    msg = "Wrong username/password! try again.";
    Serial.println("Log in Failed");
  }
  String content = "<html><body><form action='/login' method='POST'>To log in, please use : admin<br>";
  content += "Password:<input type='password' name='PASSWORD' placeholder='password'><br>";
  content += "<input type='submit' name='SUBMIT' value='Submit'></form>" + msg + "<br>";
  content += "You also can go <a href='/inline'>here</a></body></html>";
  server.send(200, "text/html", content);
}

//root page can be accessed only if authentification is ok
void handleRoot() {
  Serial.println("Enter handleRoot");
  String header;
  if (!is_authentified()) {
    server.sendHeader("Location", "/login");
    server.sendHeader("Cache-Control", "no-cache");
    server.send(301);
    return;
  }
  String content = "<html><body><H2>hello, you successfully connected to esp8266!</H2><br>";
  if (server.hasHeader("User-Agent")) {
    content += "the user agent used is : " + server.header("User-Agent") + "<br><br>";
  }
  content += "You can access this page until you <a href=\"/login?DISCONNECT=YES\">disconnect</a></body></html>";
  server.send(200, "text/html", content);
}

//no need authentification
void handleNotFound() {
  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);
}




void setup(void) {
  Serial.begin(115200);
  

 xTaskCreatePinnedToCore(
                    Task0code,   /* Task function. */
                    "Task0",     /* name of task. */
                    10000,       /* Stack size of task */
                    NULL,        /* parameter of the task */
                    2,           /* priority of the task */
                    &Task0,      /* Task handle to keep track of created task */
                    0);          /* pin task to core 0 */                  
  delay(500); 

  //create a task that will be executed in the Task2code() function, with priority 1 and executed on core 1
  xTaskCreatePinnedToCore(
                    Task1code,   /* Task function. */
                    "Task1",     /* name of task. */
                    10000,       /* Stack size of task */
                    NULL,        /* parameter of the task */
                    2,           /* priority of the task */
                    // when priority was set to 100 then network scan would not complete
                    &Task1,      /* Task handle to keep track of created task */
                    1);          /* pin task to core 1 */
    delay(500); 
}    


void Task0code( void * pvParameters ){

// task0code runs on core0 


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());

 
  server.on("/", handleRoot);
  server.on("/login", handleLogin);
  server.on("/inline", []() {
    server.send(200, "text/plain", "this works without need of authentification");
  });

  server.onNotFound(handleNotFound);
  //here the list of headers to be recorded
  const char * headerkeys[] = {"User-Agent", "Cookie"} ;
  size_t headerkeyssize = sizeof(headerkeys) / sizeof(char*);
  //ask server to track these headers
  server.collectHeaders(headerkeys, headerkeyssize);
  server.begin();
  Serial.println("HTTP server started");

  
  for (;;){ //task0code main loop
    server.handleClient();  //when run from core0 causes connection reset in browser and no page when submitting.
    // on occasion it will log in but often it will fail.  Most likely depending on background services.
    // if you get logged in then click the disconnect and relogin a few times and it will recreate.
    // f5 browser refresh completes the login
    // also while disconnecting sometimes it loses the next page for a sec but seems to autorefresh and then shows the login.
    // the lost page while disconnecting also is solved by running the handleclient in core1
    delay(1);
  }
}


void Task1code( void * pvParameters ){

// task1code runs on core1 
  for (;;){
    //server.handleClient();  //if you run from core1 then works
    Serial.println("Doing tasks on core1");
    delay(1000);
  }
}

void loop(void) {
  
}




boarchuz
Posts: 566
Joined: Tue Aug 21, 2018 5:28 am

Re: Webserver running on Core0 issues

Postby boarchuz » Tue Jan 29, 2019 4:13 am

Look up ESPAsyncWebServer

spyder0069
Posts: 35
Joined: Tue Jan 29, 2019 2:46 am

Re: Webserver running on Core0 issues

Postby spyder0069 » Tue Jan 29, 2019 3:23 pm

Thank you for the input. Is my scenario a known issue? Have you had any experience with running ESPAsyncWebServer solely on core0?

boarchuz
Posts: 566
Joined: Tue Aug 21, 2018 5:28 am

Re: Webserver running on Core0 issues

Postby boarchuz » Wed Jan 30, 2019 3:54 am

It's not really an issue, or anything particular to Core0*, it's a reasonable outcome within the constraints of running a single-threaded webserver on a tiny MCU with many concurrent requests. If you were to have a HTML page that redirects and then calls for loading external images, javascript, and css also from the ESP32, then your browser will make all of those requests very quickly and something has got to give. And yeah, I've seen this myself.

Try the Async library. I'm not sure if there's a way to pin it to Core 0 only, but you might even find that the performance increase is so significant that you won't need to worry about it.

*Though Core0 has a bunch of other higher priority tasks running on it, so the effect will be much more noticeable here

spyder0069
Posts: 35
Joined: Tue Jan 29, 2019 2:46 am

Re: Webserver running on Core0 issues

Postby spyder0069 » Wed Jan 30, 2019 4:59 am

I started playing around with the async today and have the beginnings of it running. I have the setup and so forth running from the task pinned to core0 and OTA working. I have not verified if the async background tasks are actually running there yet which will come when I add my timing sensitive task there. It does seem to respond quick. Its just a learning curve as I have to figure out how it works. I didn't find examples for an admin/login page using async but I've figure out how to create them. From what I see you cannot just go to a page that is a http post page in a browser. Since nothing is posted it bounces. So I wonder if you could just send your password to a post page and then store it in a hidden input in the form that gets posted to later pages. This way the password once checked is always stored page to page. As long as every page is a post page and checks that password input and redirects if false it seems like it would work for security. The other webserver examples used a cookie that it set (haven't tried that with the async). I am not sure if one is any more secure than the other.

boarchuz
Posts: 566
Joined: Tue Aug 21, 2018 5:28 am

Re: Webserver running on Core0 issues

Postby boarchuz » Wed Jan 30, 2019 1:53 pm

Are you the only one accessing the admin portal? It might be easier to set a password for the AP and let the WiFi stack handle the encryption, rather than implementing it at the server level. It's very easy and more secure than what you're doing now, and probably sufficient security for whatever your project is.

spyder0069
Posts: 35
Joined: Tue Jan 29, 2019 2:46 am

Re: Webserver running on Core0 issues

Postby spyder0069 » Wed Jan 30, 2019 3:25 pm

I won't be the only one. It will just be temperature readings but it will also have email login/password info in the admin as the device will send out email reports.

spyder0069
Posts: 35
Joined: Tue Jan 29, 2019 2:46 am

Re: Webserver running on Core0 issues

Postby spyder0069 » Wed Jan 30, 2019 8:30 pm

Sadly even with all the calls in the task0 (core0) the async server affects core1. This goes for any metarefresh of a webpage. Using the standard webserver server I can get past this and only have interruptions during a post which I can deal with. The only other option is to put my time sensitive portion of the project on a pic micro and then just send serial control to it but cost and pcb space isn't going to be worth it for this project.

ESP_Sprite
Posts: 9014
Joined: Thu Nov 26, 2015 4:08 am

Re: Webserver running on Core0 issues

Postby ESP_Sprite » Thu Jan 31, 2019 7:22 am

In theory, FreeRTOS is a pretty good RTOS so if you write your code right, it should stay responsive even when handling other tasks. Can I ask what weird stuff you're doing on core 1 that's so easily disturbed?

Who is online

Users browsing this forum: No registered users and 45 guests