SSL Socket errors



  • Greetings and thank-you for your time.

    I am trying to send camera images from my ESP32 (M5 Stack PoECAM) to my personal google drive.

    following this tutorial :
    https://hobby-it.com/m5timer_gdrive-2/

    I have setup SSLClient with the EthernetLarge library the jpgs arrive and but they are corrupted/incomplete. Any ideas why this might be happening, I have tried different chunk sizes no effect ?

    I don't believe its hardware as the example sketches all work as intended

    errors/warnings

    SSLClient)(SSL_WARN)(connected): Socket was dropped unexpectedly (this can be an alternative to closing the connection)
    
    (SSLClient)(SSL_ERROR)(m_print_ssl_error): SSL_CLIENT_WRITE_FAIL
    (SSLClient)(SSL_ERROR)(available): Cannot operate if the write error is not reset:
    

    The project is on github (https://gitlab.com/ArchNemsys/esp32-poe-cam) the code for the relevant function (sensitive data removed) is posted below apologies I was halfway through refactoring it to use char bufs rather than strings:

    #include <SSLClient.h>
    #include "gdrive_trust.h"
    
    
    #define WRITE_SIZE_MAX   1024 //
    
    
    //#define API_PORT    443
    //#define API_PATH_TOKEN   "/oauth2/v4/token"
    
    
    const char* refreshServer = "oauth2.googleapis.com";
    const char* refreshUri    = "/token";
    const char* apiServer     = "www.googleapis.com";
    const char* apiUri        = "/upload/drive/v3/files?uploadType=multipart";
    char accessToken[2048];   
    
    // ethClient is declared elsewhere but works perfectly outside this funciton
    SSLClient httpsClient(ethClient, gdriveTAs, 1, 25);
    //  SSLClient::write, is buffered does not actually write to the network. you must call SSLClient::available or SSLClient::flush, 
    
    
    int waitingTime      = 10000; // Wait 10 seconds to google response.
    
    
    // Send JPEG by Http POST
    void postGoogleDriveByAPI() {
      Serial.println("Connect to " + String(apiServer));
      if (httpsClient.connect(apiServer, 443)) {
        Serial.println("Connection successful");
    
        // Get Time for save file name
        struct tm timeinfo;
        if(!getLocalTime(&timeinfo)){
          Serial.println("Failed to obtain time 1");
          return;
        } 
        char saveFilename[64];
    
        /*
        char metadata[256];
    
        const char* startBoundry = "--foo_bar_baz\r\n"
                          "Content-Type:image/jpeg\r\n\r\n";
        const char* endBoundry = "\r\n--foo_bar_baz--";
        */
    
        strftime (saveFilename,64,"ALERT_%A_%B_%d_%Y_%Hh%Mm%Ss.jpg",&timeinfo);
    
        Serial.println(saveFilename);
    
    
        /*
        snprintf( metadata, 256, "--foo_bar_baz\r\n"
                          "Content-Type: application/json; charset=UTF-8\r\n\r\n"
                          "{\"name\":\"%s\",\"parents\":[\"%s\"]}\r\n\r\n" , saveFilename, PARENT_ID ); 
        
        unsigned long contentsLength = strlen(metadata) + strlen(startBoundry) + fb->len + strlen(endBoundry);
    
        snprintf(header,256, "POST %s HTTP/1.1\r\n" 
                        "HOST: %s \r\n" 
                        "Connection: close\r\n" 
                        "content-type: multipart/related; boundary=foo_bar_baz\r\n" 
                        "content-length: %u \r\n" 
                        "authorization: Bearer %s \r\n\r\n", apiUri, apiServer, contentsLength, accessToken);
        */
    
        String metadata = "--foo_bar_baz\r\n"
                          "Content-Type: application/json; charset=UTF-8\r\n\r\n"
                          "{\"name\":\"" + String(saveFilename) + "\",\"parents\":[\"" + String(PARENT_ID) + "\"]}\r\n\r\n"; // parents:save folder
                          //"{\"name\":\"" + saveFilename + "\"}\r\n\r\n"; // parerents is Optional
        String startBoundry = "--foo_bar_baz\r\n"
                              "Content-Type:image/jpeg\r\n\r\n";
        String endBoundry   = "\r\n--foo_bar_baz--";
    
        unsigned long contentsLength = metadata.length() + startBoundry.length() + fb->len + endBoundry.length();
        String header = "POST " + String(apiUri) + " HTTP/1.1\r\n" +
                        "HOST: " + String(apiServer) + "\r\n" +
                        "Connection: close\r\n" +
                        "content-type: multipart/related; boundary=foo_bar_baz\r\n" +
                        "content-length: " + String(contentsLength) + "\r\n" +
                        "authorization: Bearer " + accessToken + "\r\n\r\n";
        
        Serial.println("Send JPEG DATA by API");
        httpsClient.print(header);
        httpsClient.print(metadata);
        httpsClient.print(startBoundry);
        // JPEG data is separated into 1000 bytes and POST
    
    
        int chunk = 1000;
        unsigned long dataLength = fb->len;
        uint8_t*      bufAddr    = fb->buf;
        for(unsigned long i = 0; i < dataLength ;i=i+chunk) {
    
          if ( (i + chunk) < dataLength ) {
            httpsClient.write(( bufAddr + i ), chunk);
          } else if (dataLength%chunk != 0) {
            httpsClient.write(( bufAddr + i ), dataLength%chunk);
          }
        }
        httpsClient.print(endBoundry);
    
        Serial.println("Waiting for response.");
        long int StartTime=millis();
        while (!httpsClient.available()) {
          Serial.print(".");
          delay(100);
          if ((StartTime+waitingTime) < millis()) {
            Serial.println();
            Serial.println("No response.");
            break;
          }
        }
    
      } else {
        Serial.println("Connected to " + String(refreshServer) + " failed.");
      }
    
      httpsClient.stop();
    }
    


  • error found the Framebuffer fb was being freed before the SSLClient could finish writing hence the corrupted drive image.