Skip to content
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

webserver stops responding during send() #1554

Closed
ghost opened this issue Feb 2, 2016 · 10 comments
Closed

webserver stops responding during send() #1554

ghost opened this issue Feb 2, 2016 · 10 comments
Labels
waiting for feedback Waiting on additional info. If it's not received, the issue may be closed.

Comments

@ghost
Copy link

ghost commented Feb 2, 2016

I have a strange issue here that I have trouble searching for information on the net.
I found some similar issues but not exactly what I got here...

I am using Arduino 1.6.5 and the latest Arduino-master downloaded today.
The sketch is getting data over UART and outputing a html-table with this data.
As the table is quite big, it is streamed out in bits of about 2k.

During the command "pclient->print(sTable);" the server stops sending data and the table is not updated in the browser.
A new request from the browser works fine. (With an older version of Ardiuno-master the device did reset with wdt_reset.)

debug output on a failing transmission is:

new client
GET / HTTP/1.1
:wr
:sent 86
:ww
:wr
:sent 576
:ww
:wr
:sent 1460
:sent 673
:ww
:wr
:sent 1460
:sent 667
:ww
:wr
:er -8 2108 1
:ww
:wr !_pcb
:wr !_pcb
:wr !_pcb
:ur 1
WS:dis
:del
Client disconnected
ip:192.168.0.100,mask:255.255.255.0,gw:192.168.0.254
wifi evt: 3

Any idea what error -8 means? Still haven't found good documentation of all this and am not able to track it down in the source code.

It happens in different positions of the transmission and after different time/number of request from the browser.
Transmitting more data seems to make the error appear sooner, but I cannot confirm that for sure.

What's more, I get this debug output

ip:192.168.0.100,mask:255.255.255.0,gw:192.168.0.254
wifi evt: 3

every few minutes, even with the ESP with no activity UART or WiFi. It's basicallly idling.
I cannot find where this is output in the firmware...

I hope that I described this behaviour in an intelligible manner...

best regards,
Bob

Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

@igrr
Copy link
Member

igrr commented Feb 3, 2016

Hi, could you please share the minimal example which leads to this issue?

@ghost
Copy link
Author

ghost commented Feb 4, 2016

Of course.

I threw out the whole UART thing and stripped it down to just creating one html table that auto-loads every two seconds.

Took a few minutes but now it hangs. Requesting the page again, and all is fine (until it hangs for the next time...)

Last debug output:

WS:ac
:rn 318
:ref 1
WS:av
:ref 2
:ur 2
:wr
:sent 85
:ww
:wr
:er -8 1349 1
:ww
:wr !_pcb
:ur 1
WS:dis
:del

Here's the code, I hope it's ok to post directly...

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

// WiFi connection
char Receive_ssid[33] = "TP-LINK_791EC4";
char Receive_password[65] = "C2791EC4";

unsigned long ulReqcount;       // how often has a valid page been requested
unsigned long ulReconncount;    // how often did we connect to WiFi

int WiFiStatus = WL_IDLE_STATUS;

// storage for Measurements; keep some mem free; allocate remainder
#define KEEP_MEM_FREE 10240

// Create an instance of the server on Port 80
WiFiServer server(80);

// needed to avoid link error on ram check
extern "C"
{  
  #include "user_interface.h"
}

/////////////////////
// the setup routine
/////////////////////
void setup()
{
  // setup globals
  ulReqcount = 0;
  ulReconncount = 0;

  // start serial
  Serial.begin(115200);
  Serial.println("  ");
  Serial.println("Webserver-Test");

  WiFi.mode(WIFI_STA);
  WiFiStart(Receive_ssid, Receive_password);

  Serial1.begin(115200);
  Serial.setDebugOutput(true);
}

///////////////////
// (re-)start WiFi
///////////////////
void WiFiStart(char* ssid, char* password)
{
  unsigned int uiTimeOut = 0;
  ulReconncount++;

  // Connect to WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.print(ssid);
  Serial.print(" with password ");
  Serial.println(password);

  WiFi.begin((const char*)ssid, (const char*)password);

  while (WiFiStatus != WL_CONNECTED)
  {
    WiFiStatus = WiFi.status();
    delay(500);
    Serial.print(".");
    uiTimeOut++;
    if(uiTimeOut == 20)
    {      
      Serial.println("retry");
      WiFi.begin((const char*)ssid, (const char*)password);
    }
    if(uiTimeOut == 40)
    {      
      break;
    }
  }
  if(uiTimeOut >= 40)
  {    
    Serial.println("Could not establish connection!");
    switch (WiFiStatus)
    {
      case WL_IDLE_STATUS:
      {
        Serial.println("WL_IDLE_STATUS");
        break;
      }
      case WL_CONNECTED:
      {
        Serial.println("WL_CONNECTED");
        break;
      }
      case WL_NO_SHIELD:
      {
        Serial.println("WL_NO_SHIELD");
        break;
      }
      case WL_CONNECT_FAILED:
      {
        Serial.println("WL_CONNECT_FAILED");
        break;
      }
      case WL_NO_SSID_AVAIL:
      {
        Serial.println("WL_NO_SSID_AVAIL");
        break;
      }
      case WL_SCAN_COMPLETED:
      {
        Serial.println("WL_SCAN_COMPLETED");
        break;
      }
      case WL_CONNECTION_LOST:
      {
        Serial.println("WL_CONNECTION_LOST");
        break;
      }
      case WL_DISCONNECTED:
      {
        Serial.println("WL_DISCONNECTED");
        break;
      }
      default:
      {
        Serial.println("No idea what went wrong...");
      }
    }


    return;
  }
  Serial.println();
  Serial.println("WiFi connected");

  delay(500);
  // Start the server
  server.begin();
  Serial.println("Server started");

  // Print the IP address
  Serial.print("IP: ");
  Serial.println(WiFi.localIP());
}


//////////////////////////
// create HTTP 1.1 header
//////////////////////////
String MakeHTTPHeader(unsigned long ulLength)
{
  String sHeader;

  sHeader  = F("HTTP/1.1 200 OK\r\nContent-Length: ");
  sHeader += ulLength;
  sHeader += F("\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n");  

  return (sHeader);
}


////////////////////
// make html footer
////////////////////
String MakeHTTPFooter()
{
  String sResponse;

  sResponse  = F("\r\n<div style=\"font-size:x-small\">");
  sResponse += F("\r\n\t<BR>Aufrufz&auml;hler = ");
  sResponse += ulReqcount;
  sResponse += F("\r\n\t<BR>Verbindungsz&auml;hler = ");
  sResponse += ulReconncount;
  sResponse += F("\r\n\t<BR>Freies RAM = ");
  sResponse += (uint32_t)system_get_free_heap_size();
  sResponse += F("\r\n</div>\r\n</body>\r\n</html>");

  return (sResponse);
}


/////////////
// main look
/////////////
void loop()
{ 
  delay(50);

  //////////////////////////////
  // check if WLAN is connected
  //////////////////////////////

  if(WiFi.status() != WL_CONNECTED)
  {
    Serial.println("restart server if not connected");
    WiFiStart(Receive_ssid, Receive_password);
  }

  ///////////////////////////////////
  // Check if a client has connected
  ///////////////////////////////////
  WiFiClient client = server.available();
  if (!client)
  {
    return;
  }

  // Wait until the client sends some data
  Serial.println("new client");
  unsigned long ultimeout = millis() + 250;
  while (!client.available() && (millis() < ultimeout) )
  {
    delay(1);
  }

  if (millis() > ultimeout)
  {
    Serial.println("client connection time-out!");
    return;
  }

  /////////////////////////////////////
  // Read the first line of the request
  /////////////////////////////////////
  String sRequest = client.readStringUntil('\r');
  Serial.println(sRequest);
  client.flush();

  // stop client, if request is empty
  if (sRequest == "")
  {
    Serial.println("empty request! - stopping client");
    client.stop();
    return;
  }

  // get path; end of path is either space or ?
  // Syntax is e.g. GET /?show=1234 HTTP/1.1
  String sPath = "", sParam = "", sCmd = "";
  String sGetstart = "GET ";
  int iStart, iEndSpace, iEndQuest;
  iStart = sRequest.indexOf(sGetstart);
  if (iStart >= 0)
  {
    iStart += +sGetstart.length();
    iEndSpace = sRequest.indexOf(" ", iStart);
    iEndQuest = sRequest.indexOf("?", iStart);

    // are there parameters?
    if (iEndSpace > 0)
    {
      if (iEndQuest > 0)
      {
        // there are parameters
        sPath  = sRequest.substring(iStart, iEndQuest);
        sParam = sRequest.substring(iEndQuest, iEndSpace);
      }
      else
      {
        // NO parameters
        sPath  = sRequest.substring(iStart, iEndSpace);
      }
    }
  }


  ///////////////////////////
  // format the html response
  ///////////////////////////
  String sResponse, sResponse2, sHeader;


  if (sPath == "/")
    ////////////////////////////////////
    // format the html page for /tabelle
    ////////////////////////////////////
  {
    ulReqcount++;
    sResponse  = F("<!DOCTYPE HTML>");
    sResponse += F("\r\n<html>\r\n<head>\r\n<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">");
    sResponse += F("\r\n\t<meta http-equiv=\"refresh\" content=\"2; url=/\">");
    sResponse += F("\r\n\t<style>");
    sResponse += F("\r\n\t\tbody {background-color: #dfdfdf;}");
    sResponse += F("\r\n\t\tfont {color: #000000;}");
    sResponse += F("\r\n\t\ttable {font-size: large; width:100%;}");
    sResponse += F("\r\n\t\ttable, th, td {border: 2px solid black; border-collapse: collapse;}");
    sResponse += F("\r\n\t\tth, td {padding: 5px;}");
    sResponse += F("\r\n\t\tth {text-align: left;}");
    sResponse += F("\r\n\t</style>\r\n<title>Test</title>\r\n</head>\r\n<body>");
    sResponse += F("\r\n<h1>Testdata</h1>");

    sResponse += "\r\n<table>";
    sResponse += "\r\n\t<tbody><tr><th>#</th><th>Time</th><th>Calibration used</th><th>Sesnor 1</th><th>Sensor2</th></tr>";
    sResponse += "\r\n\t<tr><td>1</td><td>04.02.2016 09:40:12</td><td>Standard</td><td>25,12</td><td>10,60</td></tr>";
    sResponse += "\r\n\t<tr><td>1</td><td>04.02.2016 09:40:14</td><td>Standard</td><td>25,14</td><td>10,67</td></tr>";
    sResponse += "\r\n\t<tr><td>1</td><td>04.02.2016 09:40:16</td><td>Standard</td><td>25,09</td><td>10,58</td></tr>";
    sResponse += "\r\n\t<tr><td>1</td><td>04.02.2016 09:40:18</td><td>Standard</td><td>25,11</td><td>10,62</td></tr>";
    sResponse += "\r\n\t<tr><td>1</td><td>04.02.2016 09:40:20</td><td>Standard</td><td>25,12</td><td>10,61</td></tr>";
    sResponse += "\r\n\t<tr><td>1</td><td>04.02.2016 09:40:22</td><td>Standard</td><td>25,15</td><td>10,70</td></tr>";
    sResponse += "\r\n\t<tr><td>1</td><td>04.02.2016 09:40:24</td><td>Standard</td><td>25,10</td><td>10,63</td></tr>";
    sResponse += "\r\n\t<tr><td>1</td><td>04.02.2016 09:40:26</td><td>Standard</td><td>25,13</td><td>10,67</td></tr>";
    sResponse += "\r\n</tbody></table>";

    sResponse2 = MakeHTTPFooter().c_str();

    // Send the response to the client - delete strings after use to keep mem low

    client.print(MakeHTTPHeader(sResponse.length() + sResponse2.length()));
    client.print(sResponse);
    sResponse = "";
    client.print(sResponse2);      
    sResponse2 = "";
  }

  else
    ////////////////////////////
    // 404 for non-matching path
    ////////////////////////////
  {
    sResponse = "<html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL was not found on this server.</p></body></html>";

    sHeader  = F("HTTP/1.1 404 Not found\r\nContent-Length: ");
    sHeader += sResponse.length();
    sHeader += F("\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n");

    // Send the response to the client
    client.print(sHeader);
    client.print(sResponse);
  }

  // and stop the client
  client.stop();
  Serial.println("Client disconnected");
  delay(50);
}

@ghost
Copy link
Author

ghost commented Feb 8, 2016

could anyone recreate this behaviour or is it my hardware setup?

@ghost
Copy link
Author

ghost commented Feb 17, 2016

Got the same issue when using ESP8266WebServer.h
and the corresponding WebServer.send() command

Requests from the browser are processed correctly, but after a while sending just stops.

debug output:

URL is: /
HTTP Method on request was: GET
Number of query properties: 0
:wr
:sent 117
:ww
:wr
:sent 1460
:ww
:wr
:sent 1460
:ww
:wr
:er -8 1460 1
:ww
:ur 1
WS:dis
:del

@ghost ghost changed the title webserver stops responding during sent webserver stops responding during send() Feb 17, 2016
@ghost
Copy link
Author

ghost commented Feb 17, 2016

I would even be happy with a workaround...

@ghost
Copy link
Author

ghost commented Feb 17, 2016

I found that it has to do with tcp_output( _pcb ); in ClientContext.h

But I don't know how I could debug deeper...
I also tried to enable LWIP debugging but didn't succeed.
Any ideas?
I think I lack some basic knowledge about Arduino and how libraries are included...

@mcr-ksh
Copy link

mcr-ksh commented May 16, 2017

+1. got a !_pcb during send in a TCP connection.

@devyte
Copy link
Collaborator

devyte commented Oct 18, 2017

@d-a-v is this worth testing with lwip2?

@devyte devyte added the waiting for feedback Waiting on additional info. If it's not received, the issue may be closed. label Oct 18, 2017
@d-a-v
Copy link
Collaborator

d-a-v commented Oct 18, 2017

I think this was solved by PR #2874 (issue #2871) and also described in #2925.
The truth is I can't reproduce the issue with lwip1.4 (on master) with the sketch above, much bigger data, 300 iterations and still running.

It's nice to have sketches to try :)

@devyte
Copy link
Collaborator

devyte commented Oct 18, 2017

I figured, that's partly why I'm throwing them your way :)
Closing as can't reproduce.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
waiting for feedback Waiting on additional info. If it's not received, the issue may be closed.
Projects
None yet
Development

No branches or pull requests

4 participants