Skip to content
This repository has been archived by the owner on Feb 4, 2023. It is now read-only.

Cannot send requests to different addresses #4

Closed
DavidAntonin opened this issue Jan 29, 2022 · 10 comments
Closed

Cannot send requests to different addresses #4

DavidAntonin opened this issue Jan 29, 2022 · 10 comments

Comments

@DavidAntonin
Copy link

DavidAntonin commented Jan 29, 2022

Could not send requests to different addresses in quick succession - to the same address works. In the example below it says "Can't send bad request"
After a while it ends with an error and ESP32 restarts
CORRUPT HEAP: Bad tail at 0x3ffcefb8. Expected 0xbaad5678 got 0xbaad5600

assert failed: multi_heap_free multi_heap_poisoning.c:253 (head != NULL)

  • Arduino IDE version 1.8.19
    ESP32 Core Version 2.0.2
    Windows 10 64b
/****************************************************************************************************************************
  AsyncHTTPSRequest_ESP.ino - Dead simple AsyncHTTPSRequest for ESP8266, ESP32 and currently STM32 with built-in LAN8742A Ethernet

  For ESP8266, ESP32 and STM32 with built-in LAN8742A Ethernet (Nucleo-144, DISCOVERY, etc)

  AsyncHTTPSRequest_Generic is a library for the ESP8266, ESP32 and currently STM32 run built-in Ethernet WebServer

  Based on and modified from AsyncHTTPSRequest Library (https://github.com/boblemaire/AsyncHTTPSRequest)

  Built by Khoi Hoang https://github.com/khoih-prog/AsyncHTTPSRequest_Generic
  Licensed under MIT license

  Copyright (C) <2018>  <Bob Lemaire, IoTaWatt, Inc.>
  This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
  as published bythe Free Software Foundation, either version 3 of the License, or (at your option) any later version.
  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
  You should have received a copy of the GNU General Public License along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *****************************************************************************************************************************/
//************************************************************************************************************
//
// There are scores of ways to use AsyncHTTPSRequest.  The important thing to keep in mind is that
// it is asynchronous and just like in JavaScript, everything is event driven.  You will have some
// reason to initiate an asynchronous HTTP request in your program, but then sending the request
// headers and payload, gathering the response headers and any payload, and processing
// of that response, can (and probably should) all be done asynchronously.
//
// In this example, a Ticker function is setup to fire every 300 seconds to initiate a request.
// Everything is handled in AsyncHTTPSRequest without blocking.
// The callback onReadyStateChange is made progressively and like most JS scripts, we look for
// readyState == 4 (complete) here.  At that time the response is retrieved and printed.
//
// Note that there is no code in loop().  A code entered into loop would run oblivious to
// the ongoing HTTP requests.  The Ticker could be removed and periodic calls to sendRequest()
// could be made in loop(), resulting in the same asynchronous handling.
//
// For demo purposes, debug is turned on for handling of the first request.  These are the
// events that are being handled in AsyncHTTPSRequest.  They all begin with Debug(nnn) where
// nnn is the elapsed time in milliseconds since the transaction was started.
//
//*************************************************************************************************************

#if !( defined(ESP8266) ||  defined(ESP32) )
#error This code is intended to run on the ESP8266 or ESP32 platform! Please check your Tools->Board setting.
#endif

#define ASYNC_HTTPS_REQUEST_GENERIC_VERSION_MIN_TARGET      "AsyncHTTPSRequest_Generic v1.3.0"
#define ASYNC_HTTPS_REQUEST_GENERIC_VERSION_MIN             1003000

// Level from 0-4
#define ASYNC_HTTPS_DEBUG_PORT      Serial

#define _ASYNC_TCP_SSL_LOGLEVEL_    1
#define _ASYNC_HTTPS_LOGLEVEL_      1

// 300s = 5 minutes to not flooding
#define HTTPS_REQUEST_INTERVAL      60  //300

// 10s
#define HEARTBEAT_INTERVAL          10

int status;     // the Wifi radio's status

const char* ssid        = "******";
const char* password    = "*******";
byte reqCount = 3;
bool readySend = true;
const char* addresesOK[] = {"https://worldtimeapi.org/api/timezone/Europe/Prague.txt", "https://worldtimeapi.org/api/timezone/America/Toronto.txt", "https://worldtimeapi.org/api/timezone/Europe/London.txt"};
const char* addreses[] =   {"https://worldtimeapi.org/api/timezone/America/Toronto.txt", "https://worldtimeapi.org/api/timezone/Europe/Prague.txt", "https://www.myexternalip.com/raw"};

#if (ESP8266)
#include <ESP8266WiFi.h>
#elif (ESP32)
#include <WiFi.h>
#endif

// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include <AsyncHTTPSRequest_Generic.h>            // https://github.com/khoih-prog/AsyncHTTPSRequest_Generic

#include <Ticker.h>

AsyncHTTPSRequest request;
Ticker ticker;
Ticker ticker1;

void heartBeatPrint()
{
  static int num = 1;

  if (WiFi.status() == WL_CONNECTED)
    Serial.print(F("H"));        // H means connected to WiFi
  else
    Serial.print(F("F"));        // F means not connected to WiFi

  if (num == 80)
  {
    Serial.println();
    num = 1;
  }
  else if (num++ % 10 == 0)
  {
    Serial.print(F(" "));
  }
}

void sendRequest()
{
  static bool requestOpenResult;

  if (request.readyState() == readyStateUnsent || request.readyState() == readyStateDone)
  {
    reqCount--;
    readySend = false;
    //requestOpenResult = request.open("GET", "https://worldtimeapi.org/api/timezone/Europe/London.txt");
    //requestOpenResult = request.open("GET", "https://worldtimeapi.org/api/timezone/America/Toronto.txt");
    requestOpenResult = request.open("GET", addreses[reqCount]);

    if (requestOpenResult)
    {
      // Only send() if open() returns true, or crash
      Serial.print("sending request: "); Serial.println(addreses[reqCount]);
      request.send();
    }
    else
    {
      Serial.println("Can't send bad request");
    }
  }
  else
  {
    Serial.println("Can't send request");
  }
}
void sendRequests()
{
  reqCount = 3;

}

void requestCB(void* optParm, AsyncHTTPSRequest* request, int readyState)
{
  (void) optParm;

  if (readyState == readyStateDone)
  {
    Serial.println("\n**************************************");
    Serial.println(request->responseText());
    Serial.println("**************************************");

    request->setDebug(false);
    readySend = true;

  }
}

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(115200);
  while (!Serial);

  Serial.println("\nStarting AsyncHTTPSRequest_ESP using " + String(ARDUINO_BOARD));

#if defined(ESP32)
  Serial.println(ASYNC_TCP_SSL_VERSION);
#else
  //Serial.println(ESPASYNC_TCP_SSL_VERSION);
#endif

  Serial.println(ASYNC_HTTPS_REQUEST_GENERIC_VERSION);

#if defined(ASYNC_HTTPS_REQUEST_GENERIC_VERSION_MIN)
  if (ASYNC_HTTPS_REQUEST_GENERIC_VERSION_INT < ASYNC_HTTPS_REQUEST_GENERIC_VERSION_MIN)
  {
    Serial.print("Warning. Must use this example on Version equal or later than : ");
    Serial.println(ASYNC_HTTPS_REQUEST_GENERIC_VERSION_MIN_TARGET);
  }
#endif

  WiFi.mode(WIFI_STA);

  WiFi.begin(ssid, password);

  Serial.println("Connecting to WiFi SSID: " + String(ssid));

  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }

  Serial.print(F("\nAsyncHTTPSRequest @ IP : "));
  Serial.println(WiFi.localIP());

  request.setDebug(false);

  request.onReadyStateChange(requestCB);

  ticker.attach(HTTPS_REQUEST_INTERVAL, sendRequests);

  ticker1.attach(HEARTBEAT_INTERVAL, heartBeatPrint);

  // Send first request now
}

void loop()
{
  //delay(1);
  if ((reqCount > 0) && readySend) sendRequest();
}
@khoih-prog
Copy link
Owner

Hi @DavidAntonin

I'm currently have no time to spend on this issue yet.

Can you try by

  1. Using ESP32 core v2.0.1 (not v2.0.2). Some HTTPS was reportedly causing issue in Connection problem via https ESP32S2 #6117

then post your test result here.

@khoih-prog
Copy link
Owner

More to try and digest

  1. WiFiClientSecure handshake fails after client.stop(). Regression in 2.0.2 #60770

As a workaround for the issue, one can add client.setHandshakeTimeout(30); before every connection attempt.

  1. ESP32 core 2.0.2 does not work (2.0.1 does) #270

A temporary fix that worked for me was to change line 266 in the ssl_client.cpp (in the WiFiClientSecure library) file from:

if((millis()-handshake_start_time)>ssl_client->handshake_timeout)

to:

if((millis()-handshake_start_time)>(ssl_client->handshake_timeout != 0?ssl_client->handshake_timeout:120000))

(So I manually set a timeout if the handshake_timeout is zero.)

@DavidAntonin
Copy link
Author

I downgraded to 2.0.1 without success
I tried to restore handshake_timeout without success
I also tried manually update WiFiClientSecure library to last fixed version all without susccess

@khoih-prog
Copy link
Owner

Hi @DavidAntonin

Thanks for testing using those hypotheses, it'll definitely save a lot of my time when I spend time to investigate the issue.

Any more tests or info will help.

Regards,

@DavidAntonin
Copy link
Author

DavidAntonin commented Feb 15, 2022

I am trying to debug a simpler async HTTP library, because of the same problem. I foud I can successfully open request if I previously get message on terminal "_onDisconnect handler". If I try to open request before seeing "_onDisconnect handler
" I get:

[AHTTP] open( GET , url = http://alma.ch/myip.cgi
[AHTTP] _parseURL(): scheme+host HTTP:// alma.ch
[AHTTP] _parseURL(): port+path+query 80 /myip.cgi 
[AHTTP] open: not connected
Can't send bad request
[AHTTP] HTTPCODE_NOT_CONNECTED
[AHTTP] _HTTPcode =  -4
[AHTTP] _setReadyState : 4

**************************************
[AHTTP] responseText()
[AHTTP] responseText() no data

@DavidAntonin
Copy link
Author

I have now discovered that there might be a problem with the headers. All my requests end with "[AHTTP] *all data received - no disconnect". Shouldn't it be "[AHTTP] *all data received - closing TCP"? I never get it

@khoih-prog
Copy link
Owner

Could not send requests to different addresses in quick succession - to the same address works.

Check your related issue Pushover https post request #21

@khoih-prog
Copy link
Owner

Check AsyncHTTPRequest_Generic issue Pushover https post request #21.

I'll write a new example and publish a new release to demonstrate how to send requests to multiple addresses and receive responses from them.

@khoih-prog
Copy link
Owner

Hi @DavidAntonin

The new AsyncHTTPSRequest_Generic releases v1.4.1 has just been published. Your contribution is noted in Contributions and Thanks

Please try the new example AsyncHTTPSRequest_ESP_Multi which demonstrates how to send requests to multiple addresses and receive responses from them.

Best Regards,


Releases v1.4.1

  1. Add example AsyncHTTPSRequest_ESP_Multi to demonstrate how to send requests to multiple addresses and receive responses from them.

@khoih-prog
Copy link
Owner

Hi @DavidAntonin

The new AsyncHTTPSRequest_Generic releases v2.0.0 has just been published. Your contribution is noted in Contributions and Thanks

Please try the new example AsyncHTTP_HTTPSRequest_ESP which demonstrates how to send HTTP and HTTPS requests to multiple addresses and receive responses from them.

Best Regards,


Releases v2.0.0

  1. Breaking change to permit coexisting with AsyncHTTPRequest library to send and receive both HTTP and HTTPS.
  2. Add example AsyncHTTP_HTTPSRequest_ESP to demonstrate how to send HTTP and HTTPS requests to multiple addresses and receive responses from them.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants