Google iot core library and ethernet shield

Hi community…

I am working on esp32 with the arduino framework,
I was able to make it work this lib for sending data to the cloud

Instead of using the wifi to carry out the data i would like to use the ethernet cable…

I was able to run an ethernet test by using this lib…

The point is how to change the code in the google lib…

Do you have some tips for doing this?

Thanks a lot

The WiFi specific part is always done in the examples. For example, in this ESP32 example:

the object can however be constructed with any object that is inheriting Client

(which is this).

Since the ethernet library already gives you objects inheriting from this type

You should be able to write a firmware that uses an instance of an EthernetClient here without modifying the library.

1 Like

Max as usual you are a genius…
So Let me see if I understood correclty…
In this part of the code

For sure I have to remove the setupwifi and substitute with the call at the ethernetenc library and then
I have to create a new netClient object based on the EthernetClient class ?
Is it correct ?

The starnge point is the following part…

netClient = new WiFiClientSecure();

where

class WiFiClientSecure : public WiFiClient
{
protected:
    sslclient_context *sslclient;
 
    int _lastError = 0;
	int _peek = -1;
    int _timeout = 0;
    bool _use_insecure;
    const char *_CA_cert;
    const char *_cert;
    const char *_private_key;
    const char *_pskIdent; // identity for PSK cipher suites
    const char *_psKey; // key in hex for PSK cipher suites

public:
    WiFiClientSecure *next;
    WiFiClientSecure();
    WiFiClientSecure(int socket);
    ~WiFiClientSecure();
    int connect(IPAddress ip, uint16_t port);
    int connect(IPAddress ip, uint16_t port, int32_t timeout);
    int connect(const char *host, uint16_t port);
    int connect(const char *host, uint16_t port, int32_t timeout);
    int connect(IPAddress ip, uint16_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key);
    int connect(const char *host, uint16_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key);
    int connect(IPAddress ip, uint16_t port, const char *pskIdent, const char *psKey);
    int connect(const char *host, uint16_t port, const char *pskIdent, const char *psKey);
	int peek();
    size_t write(uint8_t data);
    size_t write(const uint8_t *buf, size_t size);
    int available();
    int read();
    int read(uint8_t *buf, size_t size);
    void flush() {}
    void stop();
    uint8_t connected();
    int lastError(char *buf, const size_t size);
    void setInsecure(); // Don't validate the chain, just accept whatever is given.  VERY INSECURE!
    void setPreSharedKey(const char *pskIdent, const char *psKey); // psKey in Hex
    void setCACert(const char *rootCA);
    void setCertificate(const char *client_ca);
    void setPrivateKey (const char *private_key);
    bool loadCACert(Stream& stream, size_t size);
    bool loadCertificate(Stream& stream, size_t size);
    bool loadPrivateKey(Stream& stream, size_t size);
    bool verify(const char* fingerprint, const char* domain_name);
    void setHandshakeTimeout(unsigned long handshake_timeout);

    int setTimeout(uint32_t seconds){ return 0; }

    operator bool()
    {
        return connected();
    }
    WiFiClientSecure &operator=(const WiFiClientSecure &other);
    bool operator==(const bool value)
    {
        return bool() == value;
    }
    bool operator!=(const bool value)
    {
        return bool() != value;
    }
    bool operator==(const WiFiClientSecure &);
    bool operator!=(const WiFiClientSecure &rhs)
    {
        return !this->operator==(rhs);
    };

    int socket()
    {
        return sslclient->socket = -1;
    }

private:
    char *_streamLoad(Stream& stream, size_t size);

    //friend class WiFiServer;
    using Print::write;
};

#endif /* _WIFICLIENT_H_ */

Shoud I create a new EthernetClientsecure class based on this ?

Mhm you’re right, I just thought about using an EthernetClient instead of a WiFiClientSecure, but that of course doesn’t include the TLS/SSL.

Someone already seemed to create a library for that at GitHub - stevenlianyi/EthernetClientSecure: EthernetClientSecure class based on WiFiClientSecure 1.0 by Evandro Luis Copercini, modified by Steven Lian to support ESP32 Ethernet upgrade. that includes Ethernet.h, which is supplied by jandrassy/EthernetENC. Can you try that library first on its own to see if it can make secure connections via Ethernet?

1 Like

Yes… First I will try the library as you suggested an then we will come back to the integration ,

1 Like

Hi Max…
I am back on the problem of ethernet lib for google iot cloud.
I changed the example in this way …

#include "main.h"
#include <machine.h>
#include <EthernetClientSecure.h>

const char *server = "www.howsmyssl.com"; // Server URL
EthernetClientSecure client;

// www.howsmyssl.com root certificate authority, to verify the server
// change it to your server root CA
// SHA1 fingerprint is broken now!

const char *test_root_ca =
    "-----BEGIN CERTIFICATE-----\n"
    "MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\n"
    "MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n"
    "DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\n"
    "SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\n"
    "GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\n"
    "AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\n"
    "q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\n"
    "SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\n"
    "Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\n"
    "a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\n"
    "/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\n"
    "AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\n"
    "CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\n"
    "bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\n"
    "c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\n"
    "VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\n"
    "ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\n"
    "MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\n"
    "Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\n"
    "AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\n"
    "uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\n"
    "wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\n"
    "X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\n"
    "PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\n"
    "KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\n"
    "-----END CERTIFICATE-----\n";

/**
 * @brief  Function to execute the setup generated by the arduino framework
 * @param  None
 * @retval None
 */
void setup(void)
{
  // Initialize serial and wait for port to open:
  Serial.begin(115200);
  delay(100);

  client.setCACert(test_root_ca);
  // client.setCertificate(test_client_key); // for client verification
  // client.setPrivateKey(test_client_cert);	// for client verification

  Serial.println("\nStarting connection to server...");
  if (!client.connect(server, 443))
    Serial.println("Connection failed!");
  else
  {
    Serial.println("Connected to server!");
    // Make a HTTP request:
    client.println("GET https://www.howsmyssl.com/a/check HTTP/1.0");
    client.println("Host: www.howsmyssl.com");
    client.println("Connection: close");
    client.println();

    while (client.connected())
    {
      String line = client.readStringUntil('\n');
      if (line == "\r")
      {
        Serial.println("headers received");
        break;
      }
    }
    // if there are incoming bytes available
    // from the server, read them and print them:
    while (client.available())
    {
      char c = client.read();
      Serial.write(c);
    }

    client.stop();
  }
}
/**
 * @brief  Function to execute in loop generated by the arduino framework
 * @param  None
 * @retval None
 */
void loop(void)
{
}

it is compiling but not working… then I remember that I had to modify my ethernet lib because i am using the shield Enc28J with spi…
And The following code it worked modifying the following lib GitHub - JAndrassy/EthernetENC: Ethernet library for ENC28J60. This is a modern version of the UIPEthernet library. EthernetENC library is compatible with all Arduino architectures with Arduino SPI library with transactions support. Only include EthernetENC.h instead of Ethernet.h

#include "ethernet_module.h"

/* Mac address of the IOT board*/
byte mac[] = {
    0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};

/* Creation of the webserver object (port 80 is default for HTTP) */
EthernetServer server_ethernet(80);

/* Creation of SPIClass */
SPIClass ethernetSPI(ETH_SPI_BUS);

/**
  * @brief  Function to init the Ethernet Task which for the moment it will be a webserver example with DHCP
  * @param  none
  * @retval none
  */
void Ethernet_Init(void)
{
    /*Init of the SPI with the right SPI PINS*/
    Ethernet.init(ETH_CS, &ethernetSPI, ETH_SCLK, ETH_MISO, ETH_MOSI);

    /*Serial comm for debug*/
    Serial.begin(115200);

    while (!Serial)
    {
        ; // wait for serial port to connect. Needed for native USB port only
    }
    Serial.println("Ethernet WebServer Example");

    /*start the Ethernet connection (DHCP) and the server*/
    Serial.println("Trying to recognize hardware and join via DHCP...");
    int ret = Ethernet.begin(mac);
    Serial.println("Got out of Ethernet.begin with ret = " + String(ret));

    /*If ret is 0 i start several check for searching issues*/
    if (ret == 0) 
    {
        // Check for Ethernet hardware present
        if (Ethernet.hardwareStatus() == EthernetNoHardware)
        {
            Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
            while (true)
            {
                delay(1); // do nothing, no point running without Ethernet hardware
            }
        }
        if (Ethernet.linkStatus() == LinkOFF)
        {
            Serial.println("Ethernet cable is not connected.");
        }
        while(Ethernet.linkStatus() == LinkOFF) {}

        Serial.println("Ethernet cable got connected, retrying.");

        if(Ethernet.begin(mac) == 0) 
        {
            Serial.println("Ethernet.begin() failed.");
        } 
        else 
        {
            Serial.println("Ethernet.begin() ok.");
        }
    }

    /*starting the server and print in debug local IP*/
    server_ethernet.begin();
    Serial.print("server is at ");
    Serial.println(Ethernet.localIP());

}
/**
  * @brief  Function to handle the Ethernet Task and responding at the HTTP request 
  * @param  none
  * @retval none
  */
void Ethernet_Task(void)
{   
   // listen for incoming clients
    EthernetClient client = server_ethernet.available();
    if (client)
    {
        Serial.println("new client");
        // an HTTP request ends with a blank line
        bool currentLineIsBlank = true;
        
        if (client.available())
        {
                char c = client.read();
                Serial.write(c);
                // if you've gotten to the end of the line (received a newline
                // character) and the line is blank, the HTTP request has ended,
                // so you can send a reply
                if (c == '\n' && currentLineIsBlank)
                {
                    // send a standard HTTP response header
                    client.println("HTTP/1.1 200 OK");
                    client.println("Content-Type: text/html");
                    client.println("Connection: close"); // the connection will be closed after completion of the response
                    client.println("Refresh: 5");        // refresh the page automatically every 5 sec
                    client.println();
                    client.println("<!DOCTYPE HTML>");
                    client.println("<html>");
                    client.println("</html>");
                }
                if (c == '\n')
                {
                    // you're starting a new line
                    currentLineIsBlank = true;
                }
                else if (c != '\r')
                {
                    // you've gotten a character on the current line
                    currentLineIsBlank = false;
                }
        }
     }
        // give the web browser time to receive the data
        delay(1);
}

i guess the point now it is combine my example working with the example of the new class for ethernet secure…
I really have no idea how to combine everything…
Only you can save me

Can you enable any debug logs in the ethernet library or in the ethernet client secure library? Or in the ESP32 core via Espressif 32 — PlatformIO latest documentation? If you have a better description of what exactly fails and what works, maybe you can solve the problem better.

Another way would be to use a debugger like an FTDI as in https://medium.com/@manuel.bl/low-cost-esp32-in-circuit-debugging-dbbee39e508b to get line-by-line debugging working, then issues very often become visible very quickly.

hi max… this is the result of the test code of the example reported as forst on the previous message

Starting connection to server...
assertion "Invalid mbox" failed: file "/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/lwip/lwip/src/api/tcpip.c", line 374, function: tcpip_send_msg_wait_sem
abort() was called at PC 0x400d7ee7 on core 1

But i need to use the ethernet shield with the spi otherwise the ethernet connectivity wont workk… but this is just the first point… the problem is how to merge the example not working with my ethernet lib working with the ethernet shield via spi

the followin example is working for my ethernet shield Enc28J60

#include "main.h"
#include <machine.h>
#include <EthernetClientSecure.h>
#include <ethernet_module.h>

const char *server = "www.howsmyssl.com"; // Server URL
EthernetClientSecure client;

// www.howsmyssl.com root certificate authority, to verify the server
// change it to your server root CA
// SHA1 fingerprint is broken now!

const char *test_root_ca =
    "-----BEGIN CERTIFICATE-----\n"
    "MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\n"
    "MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n"
    "DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\n"
    "SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\n"
    "GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\n"
    "AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\n"
    "q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\n"
    "SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\n"
    "Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\n"
    "a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\n"
    "/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\n"
    "AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\n"
    "CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\n"
    "bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\n"
    "c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\n"
    "VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\n"
    "ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\n"
    "MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\n"
    "Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\n"
    "AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\n"
    "uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\n"
    "wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\n"
    "X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\n"
    "PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\n"
    "KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\n"
    "-----END CERTIFICATE-----\n";

/**
 * @brief  Function to execute the setup generated by the arduino framework
 * @param  None
 * @retval None
 */
void setup(void)
{
  // // Initialize serial and wait for port to open:
  // Serial.begin(115200);
  // delay(100);

  // client.setCACert(test_root_ca);
  // // client.setCertificate(test_client_key); // for client verification
  // // client.setPrivateKey(test_client_cert);	// for client verification

  // Serial.println("\nStarting connection to server...");
  // if (!client.connect(server, 443))
  //   Serial.println("Connection failed!");
  // else
  // {
  //   Serial.println("Connected to server!");
  //   // Make a HTTP request:
  //   client.println("GET https://www.howsmyssl.com/a/check HTTP/1.0");
  //   client.println("Host: www.howsmyssl.com");
  //   client.println("Connection: close");
  //   client.println();

  //   while (client.connected())
  //   {
  //     String line = client.readStringUntil('\n');
  //     if (line == "\r")
  //     {
  //       Serial.println("headers received");
  //       break;
  //     }
  //   }
  //   // if there are incoming bytes available
  //   // from the server, read them and print them:
  //   while (client.available())
  //   {
  //     char c = client.read();
  //     Serial.write(c);
  //   }

  //   client.stop();
  // }

  Ethernet_Init();
}
/**
 * @brief  Function to execute in loop generated by the arduino framework
 * @param  None
 * @retval None
 */
void loop(void)
{

  Ethernet_Task();
}

where

void Ethernet_Init(void)
{
    /*Init of the SPI with the right SPI PINS*/
    Ethernet.init(ETH_CS, &ethernetSPI, ETH_SCLK, ETH_MISO, ETH_MOSI);

    /*Serial comm for debug*/
    Serial.begin(115200);

    while (!Serial)
    {
        ; // wait for serial port to connect. Needed for native USB port only
    }
    Serial.println("Ethernet WebServer Example");

    /*start the Ethernet connection (DHCP) and the server*/
    Serial.println("Trying to recognize hardware and join via DHCP...");
    int ret = Ethernet.begin(mac);
    Serial.println("Got out of Ethernet.begin with ret = " + String(ret));

    /*If ret is 0 i start several check for searching issues*/
    if (ret == 0) 
    {
        // Check for Ethernet hardware present
        if (Ethernet.hardwareStatus() == EthernetNoHardware)
        {
            Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
            while (true)
            {
                delay(1); // do nothing, no point running without Ethernet hardware
            }
        }
        if (Ethernet.linkStatus() == LinkOFF)
        {
            Serial.println("Ethernet cable is not connected.");
        }
        while(Ethernet.linkStatus() == LinkOFF) {}

        Serial.println("Ethernet cable got connected, retrying.");

        if(Ethernet.begin(mac) == 0) 
        {
            Serial.println("Ethernet.begin() failed.");
        } 
        else 
        {
            Serial.println("Ethernet.begin() ok.");
        }
    }

    /*starting the server and print in debug local IP*/
    server_ethernet.begin();
    Serial.print("server is at ");
    Serial.println(Ethernet.localIP());

}

�Ethernet WebServer Example
Trying to recognize hardware and join via DHCP…
Got out of Ethernet.begin with ret = 1
server is at 192.168.0.33

Hm message box? Looks like its still trying to call into the TCP/IP stack which is used by the WiFi stack, I will have to look at this…

1 Like

Max these are the include caled in the main cpp file of the new class EthernetClientSecure.cpp

#include "EthernetClientSecure.h"
#include <lwip/sockets.h>
#include <lwip/netdb.h>
#include <errno.h>

an this is the rest of the file

EthernetClientSecure::EthernetClientSecure()
{
    _connected = false;

    sslclient = new sslclient_context;
    ssl_init(sslclient);
    sslclient->socket = -1;
    sslclient->handshake_timeout = 120000;
    _CA_cert = NULL;
    _cert = NULL;
    _private_key = NULL;
    _pskIdent = NULL;
    _psKey = NULL;
    next = NULL;
}


EthernetClientSecure::EthernetClientSecure(int sock)
{
    _connected = false;
    _timeout = 0;

    sslclient = new sslclient_context;
    ssl_init(sslclient);
    sslclient->socket = sock;
    sslclient->handshake_timeout = 120000;

    if (sock >= 0) {
        _connected = true;
    }

    _CA_cert = NULL;
    _cert = NULL;
    _private_key = NULL;
    _pskIdent = NULL;
    _psKey = NULL;
    next = NULL;
}

EthernetClientSecure::~EthernetClientSecure()
{
    stop();
    delete sslclient;
}

EthernetClientSecure &EthernetClientSecure::operator=(const EthernetClientSecure &other)
{
    stop();
    sslclient->socket = other.sslclient->socket;
    _connected = other._connected;
    return *this;
}

void EthernetClientSecure::stop()
{
    if (sslclient->socket >= 0) {
        close(sslclient->socket);
        sslclient->socket = -1;
        _connected = false;
        _peek = -1;
    }
    stop_ssl_socket(sslclient, _CA_cert, _cert, _private_key);
}

int EthernetClientSecure::connect(IPAddress ip, uint16_t port)
{
    if (_pskIdent && _psKey)
        return connect(ip, port, _pskIdent, _psKey);
    return connect(ip, port, _CA_cert, _cert, _private_key);
}

int EthernetClientSecure::connect(IPAddress ip, uint16_t port, int32_t timeout){
    _timeout = timeout;
    return connect(ip, port);
}

int EthernetClientSecure::connect(const char *host, uint16_t port)
{
    if (_pskIdent && _psKey)
        return connect(host, port, _pskIdent, _psKey);
    return connect(host, port, _CA_cert, _cert, _private_key);
}

int EthernetClientSecure::connect(const char *host, uint16_t port, int32_t timeout){
    _timeout = timeout;
    return connect(host, port);
}

int EthernetClientSecure::connect(IPAddress ip, uint16_t port, const char *_CA_cert, const char *_cert, const char *_private_key)
{
    return connect(ip.toString().c_str(), port, _CA_cert, _cert, _private_key);
}

int EthernetClientSecure::connect(const char *host, uint16_t port, const char *_CA_cert, const char *_cert, const char *_private_key)
{
    if(_timeout > 0){
        sslclient->handshake_timeout = _timeout;
    }
    int ret = start_ssl_client(sslclient, host, port, _timeout, _CA_cert, _cert, _private_key, NULL, NULL);
    _lastError = ret;
    if (ret < 0) {
        log_e("start_ssl_client: %d", ret);
        stop();
        return 0;
    }
    _connected = true;
    return 1;
}

int EthernetClientSecure::connect(IPAddress ip, uint16_t port, const char *pskIdent, const char *psKey) {
    return connect(ip.toString().c_str(), port,_pskIdent, _psKey);
}

int EthernetClientSecure::connect(const char *host, uint16_t port, const char *pskIdent, const char *psKey) {
    log_v("start_ssl_client with PSK");
    if(_timeout > 0){
        sslclient->handshake_timeout = _timeout;
    }
    int ret = start_ssl_client(sslclient, host, port, _timeout, NULL, NULL, NULL, _pskIdent, _psKey);
    _lastError = ret;
    if (ret < 0) {
        log_e("start_ssl_client: %d", ret);
        stop();
        return 0;
    }
    _connected = true;
    return 1;
}

int EthernetClientSecure::peek(){
    if(_peek >= 0){
        return _peek;
    }
    _peek = timedRead();
    return _peek;
}

size_t EthernetClientSecure::write(uint8_t data)
{
    return write(&data, 1);
}

int EthernetClientSecure::read()
{
    uint8_t data = -1;
    int res = read(&data, 1);
    if (res < 0) {
        return res;
    }
    return data;
}

size_t EthernetClientSecure::write(const uint8_t *buf, size_t size)
{
    if (!_connected) {
        return 0;
    }
    int res = send_ssl_data(sslclient, buf, size);
    if (res < 0) {
        stop();
        res = 0;
    }
    return res;
}

int EthernetClientSecure::read(uint8_t *buf, size_t size)
{
    int peeked = 0;
    int avail = available();
    if ((!buf && size) || avail <= 0) {
        return -1;
    }
    if(!size){
        return 0;
    }
    if(_peek >= 0){
        buf[0] = _peek;
        _peek = -1;
        size--;
        avail--;
        if(!size || !avail){
            return 1;
        }
        buf++;
        peeked = 1;
    }
    
    int res = get_ssl_receive(sslclient, buf, size);
    if (res < 0) {
        stop();
        return peeked?peeked:res;
    }
    return res + peeked;
}

int EthernetClientSecure::available()
{
    int peeked = (_peek >= 0);
    if (!_connected) {
        return peeked;
    }
    int res = data_to_read(sslclient);
    if (res < 0) {
        stop();
        return peeked?peeked:res;
    }
    return res+peeked;
}

uint8_t EthernetClientSecure::connected()
{
    uint8_t dummy = 0;
    read(&dummy, 0);

    return _connected;
}

void EthernetClientSecure::setCACert (const char *rootCA)
{
    _CA_cert = rootCA;
}

void EthernetClientSecure::setCertificate (const char *client_ca)
{
    _cert = client_ca;
}

void EthernetClientSecure::setPrivateKey (const char *private_key)
{
    _private_key = private_key;
}

void EthernetClientSecure::setPreSharedKey(const char *pskIdent, const char *psKey) {
    _pskIdent = pskIdent;
    _psKey = psKey;
}

bool EthernetClientSecure::verify(const char* fp, const char* domain_name)
{
    if (!sslclient)
        return false;

    return verify_ssl_fingerprint(sslclient, fp, domain_name);
}

char *EthernetClientSecure::_streamLoad(Stream& stream, size_t size) {
  char *dest = (char*)malloc(size+1);
  if (!dest) {
    return nullptr;
  }
  if (size != stream.readBytes(dest, size)) {
    free(dest);
    dest = nullptr;
    return nullptr;
  }
  dest[size] = '\0';
  return dest;
}

bool EthernetClientSecure::loadCACert(Stream& stream, size_t size) {
  char *dest = _streamLoad(stream, size);
  bool ret = false;
  if (dest) {
    setCACert(dest);
    ret = true;
  }
  return ret;
}

bool EthernetClientSecure::loadCertificate(Stream& stream, size_t size) {
  char *dest = _streamLoad(stream, size);
  bool ret = false;
  if (dest) {
    setCertificate(dest);
    ret = true;
  }
  return ret;
}

bool EthernetClientSecure::loadPrivateKey(Stream& stream, size_t size) {
  char *dest = _streamLoad(stream, size);
  bool ret = false;
  if (dest) {
    setPrivateKey(dest);
    ret = true;
  }
  return ret;
}

int EthernetClientSecure::lastError(char *buf, const size_t size)
{
    if (!_lastError) {
        return 0;
    }
    char error_buf[100];
    mbedtls_strerror(_lastError, error_buf, 100);
    snprintf(buf, size, "%s", error_buf);
    return _lastError;
}

void EthernetClientSecure::setHandshakeTimeout(unsigned long handshake_timeout)
{
    sslclient->handshake_timeout = handshake_timeout * 1000;
}

I really have no idea what to do now or what to test…

Ok Max if you have time to figure out why it is calling the wifi tcp(ip stack for the wifi you will do a great thing…
As a reminder I put here the link at the 2 repo

and my working lib for the ethernet shield

Thanks again Max…

1 Like

@maxgerhardt maybe you can find useful also this discussion…

The point is to do the porting… It is not easy …
Which is your thought on it ?
Do you have some contacts for doing this task (for sure paid ) ?

Thanks again for you valuable time

I have to yet take a look at it and get an overview, maybe the complexity is overestimated, because in my chain of thought with compatible interfaces / base classes and a presumably working Ethernet SSL/TLS library that should not be too hard to do or might just need minor fixes… Hoping I can get a look at this today.

1 Like

As usual @maxgerhardt you are saving my life and job.
… Really Thanks if you have time to watch …

Max… After hours of search I found this

but I need your experience to understand if :

1-Can work with platformio and arduino framework
2-Can we extend the lib to the current EthernetENC lib you created
3-if you can think we can merge this lib with the google iot cloud lib…

Thanks again for your huge support

Try my library EthernetWebServer_SSL

If you are using ESP32, it’s better to use WT32_ETH01 board (ESP32 + LAN8720) and TLS/SSL Ethernet is supported by the core.

1 Like

Thanks @khoih-prog .
I am using this Ethernet Shield Enc28J60.
I cannot change the HW
it seems it is supported right ?
How do you see the integration between your library and this lib ?

Is it possible in your opinion and how to do it ?
Can you provide an example of integration if you have time?

Moreover once it works I have to use the following lib for the connection with google cloud iot

Do you think it is possible to create a kind of EthernetClientSecure ?

device = new CloudIoTCoreDevice(project_id, location, registry_id, device_id, private_key_str);
  setupWifi();
  netClient = new WiFiClientSecure();
  ((WiFiClientSecure *)netClient)->setCACert(root_cert);
  mqttClient = new MQTTClient(buffer_size);
  mqttClient->setOptions(keepAlive, true, timeout);
  mqtt = new CloudIoTCoreMqtt(mqttClient, netClient, device);
  mqtt->setUseLts(true);
  mqtt->startMQTT();

Thanks for your time and your help

@maxgerhardt or @khoih-prog Do you have time to confirm it ?
Thanks

I have such a module + ESP32 here and I’m going to take a look at that now.

1 Like

Thanks a lot @maxgerhardt