Finally found the culprit!
So first I had this weird bug described above with the MQTTConnect() return value of 255… I went on and completely upgraded the MQTT library supplied with Wiznet’s ioLibrary with the latest paho-embedded-c library. I replaced the MQTTClient.c and .h files, and the content of the MQTTPacket/src folder and I kept the mqtt_interface.c and .h that are part of Wiznet’ ioLibrary.
Then I had this second bug where I received fragmented data that didn’t make any sense. It seemed when I called recv(), I received the previous packet missing the first byte, plus the first byte of the current packet. (MQTT packets that is)
I found out, in the file mqtt_interface.c from Wiznet’s ioLibrary, the following code:
int w5x00_read(Network* n, unsigned char* buffer, int len, long time)
{
if((getSn_SR(n->my_socket) == SOCK_ESTABLISHED) && (getSn_RX_RSR(n->my_socket)>0))
return recv(n->my_socket, buffer, len);
return SOCK_ERROR;
}
This works flawlessly when you don’t use TLS. The function first checks if the W5x00 has a socket open, and if there’s data in the RX buffer of the W5x00 chip and calls recv() accordingly. I modified the code to use TLS like so:
int w5x00_read(Network* n, unsigned char* buffer, int len, long time)
{
if((getSn_SR(n->my_socket) == SOCK_ESTABLISHED) && (getSn_RX_RSR(n->my_socket)>0))
return wiz_tls_read(&tlsContext, buffer, len);
return SOCK_ERROR;
}
The wiz_tls_read() function comes from the W5x00 TLS example linked previously in this post. It’s basically just a wrapper to call mbedtls_ssl_read(). The problem is, the MQTT library starts by reading the received data byte per byte as each byte will determine the next action to take. But when reading the first byte through TLS, mbedtls reads a whole chunk of data from the W5x00 chip to fill it’s own SSL Rx buffer. When the second byte is read, the w5x00_read() function checks if there’s data in the chip but the chip is empty, all the data is now in the TLS buffer! So the recv() is not called until more data comes in to fill the W5x00 buffer, so I get the first byte of the buffer only, and I get the rest of the buffer only if the W5x00 receives new data.
So I simply removed the check to see if there’s data in the W5x00 chip like so:
int w5x00_read(Network* n, unsigned char* buffer, int len, long time)
{
if(getSn_SR(n->my_socket) == SOCK_ESTABLISHED)
return wiz_tls_read(&tlsContext, buffer, len);
return SOCK_ERROR;
}
And magically everything started to work. Unfortunately I didn’t find a way with mbedtls to check how much data is in the SSL Context Rx Buffer. If someone has insights on this, please let me know. But for now with this code above, mbedtls keeps feeding data from its own buffer on each single byte read from the mqtt library, and refills this buffer as needed from the W5x00 chip.