ESP-IDF SSL example can only connect once

legidstyle
Posts: 1
Joined: Sat Aug 25, 2018 9:19 am

ESP-IDF SSL example can only connect once

Postby legidstyle » Sat Aug 25, 2018 9:32 am

I am quite new to c++ and developing for iot devices so i am going through the examples and using them in c++ classes. I seem to have problems with the http examples. I have gotten wifi to work just fine but doing an HTTP request seems to always be limited to one and i have to reset the esp32 to be able to do a second one. i changed the openssl one to loop and reconnect. my code is as follows:

Code: Select all

void Wifi_controller::openssl_example_task(void *p)
{

    for(;;)
    {
      int ret;
      SSL_CTX *ctx;
      SSL *ssl;
      int sockfd;
      struct sockaddr_in sock_addr;
      struct hostent *hp;
      struct ip4_addr *ip4_addr;

      int recv_bytes = 0;
      char recv_buf[OPENSSL_EXAMPLE_RECV_BUF_LEN];

      const char send_data[] = OPENSSL_EXAMPLE_REQUEST;
      const int send_bytes = sizeof(send_data);
      vTaskDelay(10000 / portTICK_PERIOD_MS);
      ESP_LOGI(TAG, "OpenSSL demo thread start OK");


      ESP_LOGI(TAG, "get target IP address");

      hp = gethostbyname(OPENSSL_EXAMPLE_TARGET_NAME);
      if (!hp) {
          ESP_LOGI(TAG, "failed");
          continue;
      }
      ESP_LOGI(TAG, "OK");

      ip4_addr = (struct ip4_addr *)hp->h_addr;
      ESP_LOGI(TAG, IPSTR, IP2STR(ip4_addr));

      ESP_LOGI(TAG, "create SSL context ......");
      ctx = SSL_CTX_new(TLSv1_1_client_method());
      if (!ctx) {
          ESP_LOGI(TAG, "failed");
          continue;
      }
      ESP_LOGI(TAG, "OK");

      ESP_LOGI(TAG, "create socket ......");
      sockfd = socket(AF_INET, SOCK_STREAM, 0);
      if (sockfd < 0) {
          ESP_LOGI(TAG, "failed");
          SSL_CTX_free(ctx);
          ctx = NULL;
          continue;
      }
      ESP_LOGI(TAG, "OK");

      ESP_LOGI(TAG, "bind socket ......");
      memset(&sock_addr, 0, sizeof(sock_addr));
      sock_addr.sin_family = AF_INET;
      sock_addr.sin_addr.s_addr = 0;
      sock_addr.sin_port = htons(OPENSSL_EXAMPLE_LOCAL_TCP_PORT);
      ret = bind(sockfd, (struct sockaddr*)&sock_addr, sizeof(sock_addr));
      if (ret) {
          ESP_LOGI(TAG, "failed");
          close(sockfd);
          sockfd = -1;
          continue;
      }
      ESP_LOGI(TAG, "OK");

      ESP_LOGI(TAG, "socket connect to remote %s ......", OPENSSL_EXAMPLE_TARGET_NAME);
      memset(&sock_addr, 0, sizeof(sock_addr));
      sock_addr.sin_family = AF_INET;
      sock_addr.sin_addr.s_addr = ip4_addr->addr;
      sock_addr.sin_port = htons(OPENSSL_EXAMPLE_TARGET_TCP_PORT);
      ret = connect(sockfd, (struct sockaddr*)&sock_addr, sizeof(sock_addr));
      if (ret) {
          ESP_LOGI(TAG, "failed");
          close(sockfd);
          sockfd = -1;
          continue;
      }
      ESP_LOGI(TAG, "OK");

      ESP_LOGI(TAG, "create SSL ......");
      ssl = SSL_new(ctx);
      if (!ssl) {
          ESP_LOGI(TAG, "failed");
          close(sockfd);
          sockfd = -1;
          continue;
      }
      ESP_LOGI(TAG, "OK");

      SSL_set_fd(ssl, sockfd);

      ESP_LOGI(TAG, "SSL connected to %s port %d ......",
          OPENSSL_EXAMPLE_TARGET_NAME, OPENSSL_EXAMPLE_TARGET_TCP_PORT);
      ret = SSL_connect(ssl);
      if (!ret) {
          ESP_LOGI(TAG, "failed " );
          SSL_free(ssl);
          ssl = NULL;
          continue;
      }
      ESP_LOGI(TAG, "OK");

      ESP_LOGI(TAG, "send https request to %s port %d ......",
          OPENSSL_EXAMPLE_TARGET_NAME, OPENSSL_EXAMPLE_TARGET_TCP_PORT);
      ret = SSL_write(ssl, send_data, send_bytes);
      if (ret <= 0) {
          ESP_LOGI(TAG, "failed");
          SSL_shutdown(ssl);
          continue;
      }
      ESP_LOGI(TAG, "OK");

      do {
          ret = SSL_read(ssl, recv_buf, OPENSSL_EXAMPLE_RECV_BUF_LEN - 1);
          if (ret <= 0) {
              break;
          }
          recv_buf[ret] = '\0';
          recv_bytes += ret;
          ESP_LOGI(TAG, "%s", recv_buf);
      } while (1);

      ESP_LOGI(TAG, "totaly read %d bytes data from %s ......", recv_bytes, OPENSSL_EXAMPLE_TARGET_NAME);
      SSL_shutdown(ssl);
    }


}

void Wifi_controller::openssl_example_client_init(void)
{
    int ret;
    xTaskHandle openssl_handle;

    ret = xTaskCreate(openssl_example_task,
                      OPENSSL_EXAMPLE_TASK_NAME,
                      OPENSSL_EXAMPLE_TASK_STACK_WORDS,
                      NULL,
                      OPENSSL_EXAMPLE_TASK_PRIORITY,
                      &openssl_handle);

    if (ret != pdPASS)  {
        ESP_LOGI(TAG, "create thread %s failed", OPENSSL_EXAMPLE_TASK_NAME);
    }

}
as you can see i am just looping through the exammple indefinetly. waiting 10 seconds every time to retry

the definitions for the variables look as follows

Code: Select all

#define OPENSSL_EXAMPLE_TARGET_NAME        "www.example.com"
#define OPENSSL_EXAMPLE_TARGET_TCP_PORT    443

#define OPENSSL_EXAMPLE_REQUEST            "GET https://www.example.com/ HTTP/1.0\r\nHost: www.example.com\r\nUser-Agent: esp-idf/1.0 esp32\r\nContent-Type: text/plain\r\n\r\n"

#define OPENSSL_EXAMPLE_TASK_NAME        "openssl_example"
#define OPENSSL_EXAMPLE_TASK_STACK_WORDS 20480
#define OPENSSL_EXAMPLE_TASK_PRIORITY    8

#define OPENSSL_EXAMPLE_RECV_BUF_LEN       2048

#define OPENSSL_EXAMPLE_LOCAL_TCP_PORT     443
the console output looks as follows

Code: Select all

␛[0;32mI (372734) WIFI: OpenSSL demo thread start OK␛[0m
␛[0;32mI (372734) WIFI: get target IP address␛[0m
␛[0;32mI (372734) WIFI: OK␛[0m
␛[0;32mI (372734) WIFI: 93.184.216.34␛[0m
␛[0;32mI (372734) WIFI: create SSL context ......␛[0m
␛[0;32mI (372744) WIFI: OK␛[0m
␛[0;32mI (372744) WIFI: create socket ......␛[0m
␛[0;32mI (372744) WIFI: OK␛[0m
␛[0;32mI (372744) WIFI: bind socket ......␛[0m
␛[0;32mI (372754) WIFI: OK␛[0m
␛[0;32mI (372754) WIFI: socket connect to remote www.example.com ......␛[0m

␛[0;32mI (372864) WIFI: OK␛[0m
␛[0;32mI (372864) WIFI: create SSL ......␛[0m
␛[0;32mI (372874) WIFI: OK␛[0m
␛[0;32mI (372874) WIFI: SSL connected to www.example.com port 443 ......␛[0m
␛[0;32mI (373934) WIFI: OK␛[0m
␛[0;32mI (373934) WIFI: send https request to www.example.com port 443 ......␛[0m
␛[0;32mI (373944) WIFI: OK␛[0m
␛[0;32mI (374044) WIFI: HTTP/1.0 200 OK
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8
Date: Sat, 25 Aug 2018 09:15:07 GMT
Etag: "1541025663+ident"
Expires: Sat, 01 Sep 2018 09:15:07 GMT
Last-Modified: Fri, 09 Aug 2013 23:54:35 GMT
Server: ECS (dca/5327)
Vary: Accept-Encoding
X-Cache: HIT
Content-Length: 1270
Connection: close

␛[0m
␛[0;32mI (374074) WIFI: <!doctype html>
....................................
<div>
    <h1>Example Domain</h1>
    <p>This domain is established to be used for illustrative examples in documents. You may use this
    domain in examples without prior coordination or asking for permission.</p>
    <p><a href="http://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>
[0;32mI (374184) WIFI: totaly read 1611 bytes data from www.example.com ......␛[0m
␛[0;32mI (378194) WIFI: OpenSSL demo thread start OK␛[0m
␛[0;32mI (378194) WIFI: get target IP address␛[0m
␛[0;32mI (378194) WIFI: OK␛[0m
␛[0;32mI (378194) WIFI: 93.184.216.34␛[0m
␛[0;32mI (378194) WIFI: create SSL context ......␛[0m
␛[0;32mI (378204) WIFI: OK␛[0m

␛[0;32mI (378204) WIFI: create socket ......␛[0m
␛[0;32mI (378204) WIFI: OK␛[0m
␛[0;32mI (378204) WIFI: bind socket ......␛[0m
␛[0;32mI (378214) WIFI: failed␛[0m
␛[0;32mI (382214) WIFI: OpenSSL demo thread start OK␛[0m
␛[0;32mI (382214) WIFI: get target IP address␛[0m
␛[0;32mI (382214) WIFI: OK␛[0m
␛[0;32mI (382214) WIFI: 93.184.216.34␛[0m
␛[0;32mI (382214) WIFI: create SSL context ......␛[0m
␛[0;32mI (382224) WIFI: OK␛[0m
␛[0;32mI (382224) WIFI: create socket ......␛[0m
␛[0;32mI (382224) WIFI: OK␛[0m
␛[0;32mI (382224) WIFI: bind socket ......␛[0m
␛[0;32mI (382234) WIFI: failed␛[0m
␛[0;32mI (386234) WIFI: OpenSSL demo thread start OK␛[0m
␛[0;32mI (386234) WIFI: get target IP address␛[0m
␛[0;32mI (386234) WIFI: OK␛[0m
␛[0;32mI (386234) WIFI: 93.184.216.34␛[0m
␛[0;32mI (386234) WIFI: create SSL context ......␛[0m
␛[0;32mI (386244) WIFI: OK␛[0m
␛[0;32mI (386244) WIFI: create socket ......␛[0m
␛[0;32mI (386244) WIFI: OK␛[0m
␛[0;32mI (386244) WIFI: bind socket ......␛[0m
␛[0;32mI (386254) WIFI: failed␛[0m
␛[0;32mI (390254) WIFI: OpenSSL demo thread start OK␛[0m
␛[0;32mI (390254) WIFI: get target IP address␛[0m
␛[0;32mI (390254) WIFI: OK␛[0m
␛[0;32mI (390254) WIFI: 93.184.216.34␛[0m
␛[0;32mI (390254) WIFI: create SSL context ......␛[0m
␛[0;32mI (390264) WIFI: OK␛[0m
␛[0;32mI (390264) WIFI: create socket ......␛[0m
␛[0;32mI (390264) WIFI: OK␛[0m
Am i just doing something wrong or is there a bug somewhere else?

user4_esp32
Posts: 21
Joined: Sun Nov 26, 2017 4:48 pm

Re: ESP-IDF SSL example can only connect once

Postby user4_esp32 » Sat Aug 25, 2018 1:22 pm

Hello, are you developing in arduino-esp32?

Since you are coding for sockets, and the console output shows a failure to bind a new socket after successfully binding the socket for the first time, perhaps the code should destroy the socket each time it finishes the for loop.

You could also checkout the ESP32 TLS component: https://esp-idf.readthedocs.io/en/lates ... ls#esp-tls

Who is online

Users browsing this forum: maurizio.scian and 120 guests