espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.75k stars 7.43k forks source link

WiFiClient::flush() is blocked when using httpClient.post some time. #1868

Closed lzw7603 closed 5 years ago

lzw7603 commented 6 years ago

Hardware:

Board: ESP32 Dev Module Core Installation/update date: 9/9/2018 IDE name: Arduino IDE Flash Frequency: 80Mhz Upload Speed: 921600

Description:

  1. web server is tomcat 8.5.31
  2. os is debian 9
  3. runing in Docker

Sketch:


//Change the code below by your sketch
#include <Arduino.h>

String httpPost(const char *pUrl, char *pBuf, int& nCode)
{
    //check
    if(WiFi.status() != WL_CONNECTED) return "";

    //init
    HTTPClient http;
    String payload;

    //http pos
    http.begin(pUrl); //HTTP
    //http.setTimeout(3000);
    http.addHeader("content-type", "application/json");

    // start connection and send HTTP header
    Serial.print("[HTTP] GET...\n");
    int httpCode = http.POST((uint8_t*)pBuf, strlen(pBuf));

    // httpCode will be negative on error
    if(httpCode > 0) 
    {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTP] GET... code: %d\n", httpCode);

        // file found at server
        if(httpCode == HTTP_CODE_OK) {
            payload = http.getString();
            Serial.println(payload);
        }
    } else {
        Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
    }

    //last
    http.end();
    nCode = httpCode;
    return payload;
}

void setup() {
    //init serial
    Serial.begin(115200);

    //init wifi
    WiFi.mode(WIFI_STA);
    WiFi.begin("LESSO",  "");
    while (WiFi.waitForConnectResult() != WL_CONNECTED) {
      Serial.println(".");
      delay(5000);
    }

    char buf[100];
    memset(buf, 0x00, 100 * sizeof(char));
    sprintf(buf, "{\"devID\":\"%s\"}", g_chipID);
    Serial.println(buf);

    //send online
    int nCode = 0;
    String strJson = httpPost("http://192.168.3.197:49315/upload-file/getUpdateInfo", buf, nCode);
    Serial.println("good!!");
}

void loop() {
}

First time, i found that is block on line 688 in file HTTPClient.cpp

String HTTPClient::getString(void)
{
    StreamString sstring;
    if(_size) {
        // try to reserve needed memmory
        if(!sstring.reserve((_size + 1))) {
            log_d("not enough memory to reserve a string! need: %d", (_size + 1));
            return "";
        }
    }
    writeToStream(&sstring); // <------------- block here
    return sstring;
}

And then I found that is block on line 668 in file HTTPClient.cpp

int HTTPClient::writeToStream(Stream * stream)
{
   ......
    end();  // <------------- block here, the last 2 line
    return ret;
}

And then I found that is block on line 235 in file HTTPClient.cpp

void HTTPClient::end(void)
{
    if(connected()) {
        if(_tcp->available() > 0) {
            log_d("still data in buffer (%d), clean up.", _tcp->available());
            _tcp->flush(); // <------------- block here
        }
        ......
    } else {
        log_v("tcp is closed");
    }
}

And then I found that is block on line 425 in file WiFiClient.cpp

void WiFiClient::flush() {
    ......
    while(a){
        toRead = (a>WIFI_CLIENT_FLUSH_BUFFER_SIZE)?WIFI_CLIENT_FLUSH_BUFFER_SIZE:a;
        res = recv(fd(), buf, toRead, MSG_DONTWAIT); // <------------- block here
        if(res < 0) {
            log_e("%d", errno);
            stop();
            break;
        }
        a -= res;
    }
    free(buf);
}

java code on server

@Controller
public class UpdateController {

    @Autowired
    private UpdateService updateService;

    @RequestMapping("getUpdateInfo")
    @ResponseBody
    public Object getUpdateInfo(HttpServletRequest request, @RequestBody String json) {
        // {"devID":"", "IP":"", "Ver":"", "update":""}
        //" {\"devID\":\"%s\", \"IP\":\"%s\", \"Ver\":\"%s\", \"update\":\"%d\"}"
        JSONObject machineInfo = JSONObject.parseObject(json);
        String devID = machineInfo.getString("devID");
        Object returnJson = updateService.getUpdateInfo(devID);
        return returnJson;
    } 
}
hpsaturn commented 5 years ago

Hi, I have a possible similar behavior with last version of HTTPClient.

My code use a InfluxDB Library, the implementation there is:

bool InfluxArduino::write(const char *measurement,const char *tagString,const char *fieldString)
{   
    HTTPClient http;
    char uri[32];
    sprintf(uri, "/write?db=%s", _database);

    if(_isSecure)
    {
       http.begin(_host, _port, uri, _cert);
    }
    else
    {
        http.begin(_host, _port, uri);
    }
    http.addHeader("Content-Type", "text/plain"); // not sure what influx is looking for but this works?

    if(_isAuthorised)
    {
        http.setAuthorization(_username,_password);
    }

    char writeBuf[512]; // ¯\_(ツ)_/¯ 
    if(strlen(tagString) > 0)
    {
        sprintf(writeBuf,"%s,%s %s",measurement,tagString,fieldString); //no comma between tags and fields
    }

    else
    {
        //no tags
        sprintf(writeBuf,"%s %s",measurement,fieldString); //no comma between tags and fields
    }
    if(debug) Serial.println(writeBuf);
    _latestResponse = http.POST(writeBuf);
    http.end();
    return _latestResponse == 204;
}

after some hours, this enter to a internal loop on HTTPClient and it stays there, because other functions in my code works, like Bluetooth callbacks and Bluetooth advertising

I have the next frameworks versions in my platformio installation:

    "framework-arduinoespressif32": {
      "type": "framework",
      "optional": true,
      "version": "~2.10002.190416"
    },
    "framework-espidf": {
      "type": "framework",
      "optional": true,
      "version": "~3.30200.190418"
    }

and espressif32 Version: 1.8.0

My project libraries:

Updating Adafruit AM2320 sensor library  @ 1.1.1          [Up-to-date]
Updating Adafruit BME680 Library         @ 1.0.7          [Up-to-date]
Updating Adafruit Unified Sensor         @ 1.0.3          [Up-to-date]
Updating ArduinoJson                     @ 6.10.1         [Up-to-date]
Updating ClosedCube BME680               @ 1.2.0          [Up-to-date]
Updating HPMA115S0 Arduino Library       @ 23cbd44        [Up-to-date]
Updating Influx-Arduino                  @ ce16fc3        [Up-to-date]
Updating U8g2                            @ 2.26.5         [Up-to-date]
stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 5 years ago

This stale issue has been automatically closed. Thank you for your contributions.