SSLClient error SSL_CLIENT_WRITE_FAIL and timeout

I have a MKR1000 board and been getting some kind of timeout error SSL_CLIENT_WRITE_FAIL with SSL each time the MQTT client publishes to the broker. The sketch seems to work otherwise. That is to say it connects to the MQTT broker and publishes and other clients can subscribe and receive the sent messages, all over TLS. However, after publishing a message to the broker the sketch seems to hang for about 22 seconds before producing some warning messages and then moving on while producing some additional warning messages. I can't figure out how to prevent the delay. I'd like to get rid of both the delay and the errors or, failing that, just get rid of the delay.

Below is the output sent by the script to the Serial Monitor, and in that the epoch is shown before each debugging message. Below that is the sketch itself. What should I be looking at to correct the mistake and at least avoid the timeout if not also the error messages? As mentioned, the broker is receiving the encrypted messages from the MKR1000.

Setup: Attempting to connect to WPA SSID: xxxxx
SSID: xxxxx
BSSID: xx:xx:xx:xx:xx:xx
192.168.xxx.xxx
signal strength (RSSI): -67
Encryption Type: 2

--------------------------------------------------
Setup is done
Reconnect() attempting MQTT connection...
(SSLClient)(SSL_WARN)(connect): Using a raw IP Address for an SSL connection bypasses some important verification steps. You should use a domain name (www.google.com) whenever possible.
1611241426+connected...
1611241426+published...
(SSLClient)(SSL_ERROR)(m_update_engine): Error writing to m_client
(SSLClient)(SSL_ERROR)(m_update_engine): 1
(SSLClient)(SSL_ERROR)(connected): Socket was unexpectedly interrupted. m_client error: 
(SSLClient)(SSL_ERROR)(connected): 1
(SSLClient)(SSL_ERROR)(connected): Not connected because write error is set
(SSLClient)(SSL_ERROR)(m_print_ssl_error): SSL_CLIENT_WRITE_FAIL
(SSLClient)(SSL_WARN)(m_run_until): Terminating with write error: 
(SSLClient)(SSL_WARN)(m_run_until): 4
(SSLClient)(SSL_ERROR)(flush): Could not flush write buffer!
(SSLClient)(SSL_ERROR)(m_print_ssl_error): SSL_CLIENT_WRITE_FAIL
1611241448+flushed...
(SSLClient)(SSL_ERROR)(write): Cannot operate if the write error is not reset: 
(SSLClient)(SSL_ERROR)(m_print_ssl_error): SSL_CLIENT_WRITE_FAIL
(SSLClient)(SSL_ERROR)(connected): Not connected because write error is set
(SSLClient)(SSL_ERROR)(m_print_ssl_error): SSL_CLIENT_WRITE_FAIL
1611241449+disconnected...
(SSLClient)(SSL_ERROR)(connected): Not connected because write error is set
(SSLClient)(SSL_ERROR)(m_print_ssl_error): SSL_CLIENT_WRITE_FAIL
Reconnect() attempting MQTT connection...
(SSLClient)(SSL_ERROR)(connected): Not connected because write error is set
(SSLClient)(SSL_ERROR)(m_print_ssl_error): SSL_CLIENT_WRITE_FAIL
(SSLClient)(SSL_ERROR)(connected): Not connected because write error is set
(SSLClient)(SSL_ERROR)(m_print_ssl_error): SSL_CLIENT_WRITE_FAIL
(SSLClient)(SSL_WARN)(connect): Using a raw IP Address for an SSL connection bypasses some important verification steps. You should use a domain name (www.google.com) whenever possible.
1611241449+connected...
1611241449+published...

Here is the sketch:

/*
   This connects but gives an SSL Error
*/

#include <SPI.h>                  // built-in WiFi shield uses SPI
#include <WiFi101.h>              // WiFi support       https://www.arduino.cc/en/Reference/WiFi101
#include <WiFiUdp.h>

#include <SSLClient.h>            // https://github.com/OPEnSLab-OSU/SSLClient 
#include <PubSubClient.h>         // https://pubsubclient.knolleary.net/ 
#include <RTCZero.h>              // https://www.arduino.cc/en/Reference/RTC


RTCZero rtc;

#include "certificates.h"         // 
#include "wifi-secrets.h"         // 

char ssid[] = SECRET_SSID;        // network SSID
char pass[] = SECRET_PASS;        // network password
int status  = WL_IDLE_STATUS;     // the WiFi radio's status

SSLClientParameters mTLS = SSLClientParameters::fromPEM(my_cert, sizeof my_cert, my_key, sizeof my_key);

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

void printMacAddress(byte mac[]) {
  for (int i = 5; i >= 0; i--) {
    if (mac[i] < 16) {
      Serial.print("0");
    }
    Serial.print(mac[i], HEX);
    if (i > 0) {
      Serial.print(":");
    }
  }
  Serial.println();
}

void printCurrentNet() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print the MAC address of the router you're attached to:
  byte bssid[6];
  WiFi.BSSID(bssid);
  Serial.print("BSSID: ");
  printMacAddress(bssid);

  // IP Address
  ip = WiFi.localIP();
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI): ");
  Serial.println(rssi);

  // print the encryption type:
  byte encryption = WiFi.encryptionType();
  Serial.print("Encryption Type: ");
  Serial.println(encryption, HEX);
  Serial.println();
}

WiFiClient wifi;
SSLClient  tls(wifi, TAs, (size_t)TAs_NUM, A5);         // the last value is an Analog pin to draw random input from

PubSubClient mqttClient(mqttServer, mqttPort, callback, tls);

// mqttClient.setServer(mqttServer, mqttPort);

boolean reconnect() {
  int epoch = WiFi.getTime();

  //  mqttClient.setKeepAlive(90);
  /// mqttClient.setCallback(callback);
  // Loop until we're reconnected
  while (!mqttClient.connected()) {
    Serial.println("Reconnect() attempting MQTT connection...");
    // Attempt to connect
    if (mqttClient.connect("mkr1000", MQTT_ACCT, MQTT_PASS)) {
      epoch = WiFi.getTime();
      Serial.print(epoch);
      Serial.println("+connected...");
      // tls.flush();
      // Once connected, publish an announcement...
      mqttClient.publish("outTopic", "Hello World from MKR1000");
      epoch = WiFi.getTime();
      Serial.print(epoch);
      Serial.println("+published...");
      // This is a necessary workaround to partially address https://github.com/OPEnSLab-OSU/SSLClient/issues/9
      tls.flush();
      epoch = WiFi.getTime();
      Serial.print(epoch);
      Serial.println("+flushed...");
      // ... and resubscribe
      // mqttClient.subscribe("inTopic");
      // This is a workaround to address https://github.com/OPEnSLab-OSU/SSLClient/issues/9
      // tls.flush();
      mqttClient.disconnect ();
      epoch = WiFi.getTime();
      Serial.print(epoch);
      Serial.println("+disconnected...");
    } else {
      Serial.print("failed, rc=");
      Serial.print(mqttClient.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
  return mqttClient.connected();
}

void setup() {
  // Start Serial
  Serial.begin(115200);
  Serial.println("Starting");
  while (!Serial);
  WiFi.hostname("mkr1000");

  // Enable mutual TLS with SSLClient
  tls.setMutualAuthParams(mTLS);

  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("Setup: WiFi shield not present");
    // don't continue:
    while (true);
  }

  // attempt to connect to WiFi network:
  while ( WiFi.status() != WL_CONNECTED) {
    Serial.print("Setup: Attempting to connect to WPA SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network:
    status = WiFi.begin(ssid, pass);

    // wait 5 seconds for connection:
    delay(5000);
  }

  printCurrentNet();

  // Initialize RTC
  rtc.begin();

  Serial.println("--------------------------------------------------");
  Serial.println("Setup is done");
}

void loop() {
  if (!mqttClient.connected()) {
    reconnect();
  }
  Serial.println();
  mqttClient.loop();
}

Did you read the implementation details of your SSL library?

Board and Network Peripheral - Your board should have a lot of resources (>110kb flash and >7kb RAM), and your network peripheral should have a large internal buffer (>7kb). This library was tested with the Adafruit Feather M0 (256K flash, 32K RAM) and the Adafruit Ethernet Featherwing (16kb Buffer), and we still had to modify the Arduino Ethernet library to support larger internal buffers per socket (see the Implementation Gotchas).

Did you read the output you got?

(SSLClient)(SSL_WARN)(connect): Using a raw IP Address for an SSL connection bypasses some important verification steps. You should use a domain name (www.google.com) whenever possible.

Although this probably isn't responsible for the delay problem you shouldn't just ignore it. Why do you use SSL if you don't care about it?

pylon:
Did you read the implementation details of your SSL library?

Thanks. I had seen that but not understood. That's much deeper than I have skill to deal with but I will take a look anyway. The MKR1000 has >110kB flash and >7kB RAM at 256kB and 32kB respectively. However, what about the buffer? The implementation notes mention the Ethernet library. Would the same need to increase the buffer size apply to the WiFi101 library? The changes to the Ethernet library are quite small:

$ diff Ethernet.h EthernetLarge.h 
36,40c36
< #if defined(RAMEND) && defined(RAMSTART) && ((RAMEND - RAMSTART) <= 2048)
< #define MAX_SOCK_NUM 4
< #else
< #define MAX_SOCK_NUM 8
< #endif
---
> #define MAX_SOCK_NUM 2
48c44
< //#define ETHERNET_LARGE_BUFFERS
---
> #define ETHERNET_LARGE_BUFFERS

I've tried looking for what might or might not be the corresponding part in WiFI101, but without effect.

$ diff socket.h socket.h.orig 
119c119
< #define TCP_SOCK_MAX (8)
---
> #define TCP_SOCK_MAX (7)
124c124
< #define UDP_SOCK_MAX 8
---
> #define UDP_SOCK_MAX 4

Lacking proper skill or understanding, I am just guessing. The above modifications are obviously not right or insufficient on their own. Nor was reducing those values to 2 useful. Does the WiFi101 library have anything corresponding to the Ethernet library's ETHERNET_LARGE_BUFFERS option? Or will a lot more have to be rewritten first?

1611496194+connected...
1611496194+published...
(SSLClient)(SSL_ERROR)(m_update_engine): Error writing to m_client
(SSLClient)(SSL_ERROR)(m_update_engine): 1
(SSLClient)(SSL_ERROR)(connected): Socket was unexpectedly interrupted. m_client error: 
(SSLClient)(SSL_ERROR)(connected): 1
(SSLClient)(SSL_ERROR)(connected): Not connected because write error is set
(SSLClient)(SSL_ERROR)(m_print_ssl_error): SSL_CLIENT_WRITE_FAIL
(SSLClient)(SSL_WARN)(m_run_until): Terminating with write error: 
(SSLClient)(SSL_WARN)(m_run_until): 4
(SSLClient)(SSL_ERROR)(flush): Could not flush write buffer!
(SSLClient)(SSL_ERROR)(m_print_ssl_error): SSL_CLIENT_WRITE_FAIL
1611496217+flushed...
(SSLClient)(SSL_ERROR)(write): Cannot operate if the write error is not reset: 
(SSLClient)(SSL_ERROR)(m_print_ssl_error): SSL_CLIENT_WRITE_FAIL
(SSLClient)(SSL_ERROR)(connected): Not connected because write error is set
(SSLClient)(SSL_ERROR)(m_print_ssl_error): SSL_CLIENT_WRITE_FAIL
1611496217+disconnected...
(SSLClient)(SSL_ERROR)(connected): Not connected because write error is set
(SSLClient)(SSL_ERROR)(m_print_ssl_error): SSL_CLIENT_WRITE_FAIL
Reconnect() attempting MQTT connection...
(SSLClient)(SSL_ERROR)(connected): Not connected because write error is set
(SSLClient)(SSL_ERROR)(m_print_ssl_error): SSL_CLIENT_WRITE_FAIL
(SSLClient)(SSL_ERROR)(connected): Not connected because write error is set
(SSLClient)(SSL_ERROR)(m_print_ssl_error): SSL_CLIENT_WRITE_FAIL
(SSLClient)(SSL_WARN)(connect): Using a raw IP Address for an SSL connection bypasses some important verification steps. You should use a domain name (www.google.com) whenever possible.
1611496217+connected...
1611496217+published...

Pretty much every aspect is new to me and not a familiar at all, thus a learning process.

pylon:
Did you read the output you got?

Yes. It is set up that way on purpose so the warning is not relevant. It is not feasible to add DNS Sec to this system. Thus choosing an IPv4-only method changes nothing. However, next year when I redo that particular WLAN, I already plan to make it possible to use host names for the certificates.

That's much deeper than I have skill to deal with but I will take a look anyway. The MKR1000 has >110kB flash and >7kB RAM at 256kB and 32kB respectively. However, what about the buffer? The implementation notes mention the Ethernet library. Would the same need to increase the buffer size apply to the WiFi101 library?

I know that the MCU isn't the problem but I'm not sure if the WiFi module has a big enough buffer. I couldn't find that detail in the datasheet.

Why do you use the SSL library at all? The WiFi101 module supports TLS1.0 and 1.1 by itself.

It is not feasible to add DNS Sec to this system.

This is not related to DSN Sec. It simply means using the DNS name and not the IP. If that's a local network only application, why do you need SSL/TLS at all?

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.