mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2026-03-14 05:36:34 +03:00
WIP: ESP-IDF Core 3 migration - mbedtls SSL, module library, board configs, MQTT and network updates
This commit is contained in:
@@ -6,66 +6,154 @@ For a copy, see <https://opensource.org/licenses/MIT> or
|
||||
the LICENSE file.
|
||||
*/
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
|
||||
|
||||
#include "ClientSecureSync.h"
|
||||
#include <lwip/sockets.h> // socket options
|
||||
#include "mbedtls_ssl.h" // triggers compilation of mbedtls SSL module (stripped from Tasmota libmbedtls.a)
|
||||
|
||||
#include <cstring>
|
||||
#include <lwip/sockets.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
namespace espMqttClientInternals {
|
||||
|
||||
ClientSecureSync::ClientSecureSync()
|
||||
: client() {
|
||||
// empty
|
||||
: _tls(nullptr)
|
||||
, _cfg{}
|
||||
, _connected(false) {
|
||||
}
|
||||
|
||||
ClientSecureSync::~ClientSecureSync() {
|
||||
stop();
|
||||
}
|
||||
|
||||
bool ClientSecureSync::connect(IPAddress ip, uint16_t port) {
|
||||
bool ret = client.connect(ip, port); // implicit conversion of return code int --> bool
|
||||
if (ret) {
|
||||
#if defined(ARDUINO_ARCH_ESP8266)
|
||||
client.setNoDelay(true);
|
||||
#elif defined(ARDUINO_ARCH_ESP32)
|
||||
// Set TCP option directly to bypass lack of working setNoDelay for WiFiClientSecure
|
||||
int val = true;
|
||||
client.setSocketOption(IPPROTO_TCP, TCP_NODELAY, &val, sizeof(int));
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
char host[16];
|
||||
sprintf(host, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
|
||||
return connect(host, port);
|
||||
}
|
||||
|
||||
bool ClientSecureSync::connect(const char* host, uint16_t port) {
|
||||
bool ret = client.connect(host, port); // implicit conversion of return code int --> bool
|
||||
if (ret) {
|
||||
#if defined(ARDUINO_ARCH_ESP8266)
|
||||
client.setNoDelay(true);
|
||||
#elif defined(ARDUINO_ARCH_ESP32)
|
||||
// Set TCP option directly to bypass lack of working setNoDelay for WiFiClientSecure
|
||||
int val = true;
|
||||
client.setSocketOption(IPPROTO_TCP, TCP_NODELAY, &val, sizeof(int));
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
bool ClientSecureSync::connect(const char * host, uint16_t port) {
|
||||
stop(); // clean up any previous connection
|
||||
|
||||
_tls = esp_tls_init();
|
||||
if (!_tls) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (esp_tls_conn_new_sync(host, strlen(host), port, &_cfg, _tls) <= 0) {
|
||||
esp_tls_conn_destroy(_tls);
|
||||
_tls = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
_connected = true;
|
||||
|
||||
// Set TCP_NODELAY and non-blocking mode on the underlying socket
|
||||
int fd = -1;
|
||||
if (esp_tls_get_conn_sockfd(_tls, &fd) == ESP_OK && fd >= 0) {
|
||||
int val = 1;
|
||||
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
|
||||
// Make socket non-blocking so reads don't stall the MQTT event loop
|
||||
int flags = fcntl(fd, F_GETFL, 0);
|
||||
if (flags >= 0) {
|
||||
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t ClientSecureSync::write(const uint8_t* buf, size_t size) {
|
||||
return client.write(buf, size);
|
||||
size_t ClientSecureSync::write(const uint8_t * buf, size_t size) {
|
||||
if (!_tls || !_connected) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Write all data, retrying on WANT_WRITE (non-blocking socket)
|
||||
size_t written = 0;
|
||||
while (written < size) {
|
||||
int ret = esp_tls_conn_write(_tls, buf + written, size - written);
|
||||
if (ret > 0) {
|
||||
written += ret;
|
||||
} else if (ret == ESP_TLS_ERR_SSL_WANT_WRITE || ret == ESP_TLS_ERR_SSL_WANT_READ) {
|
||||
continue; // retry
|
||||
} else {
|
||||
_connected = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
int ClientSecureSync::read(uint8_t* buf, size_t size) {
|
||||
return client.read(buf, size);
|
||||
int ClientSecureSync::read(uint8_t * buf, size_t size) {
|
||||
if (!_tls || !_connected) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = esp_tls_conn_read(_tls, buf, size);
|
||||
if (ret > 0) {
|
||||
return ret;
|
||||
}
|
||||
if (ret == ESP_TLS_ERR_SSL_WANT_READ || ret == ESP_TLS_ERR_SSL_WANT_WRITE) {
|
||||
return -1; // no data available yet, still connected
|
||||
}
|
||||
// Connection closed or error
|
||||
_connected = false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ClientSecureSync::stop() {
|
||||
client.stop();
|
||||
if (_tls) {
|
||||
esp_tls_conn_destroy(_tls);
|
||||
_tls = nullptr;
|
||||
}
|
||||
_connected = false;
|
||||
}
|
||||
|
||||
bool ClientSecureSync::connected() {
|
||||
return client.connected();
|
||||
return _connected && _tls != nullptr;
|
||||
}
|
||||
|
||||
bool ClientSecureSync::disconnected() {
|
||||
return !client.connected();
|
||||
return !connected();
|
||||
}
|
||||
|
||||
} // namespace espMqttClientInternals
|
||||
void ClientSecureSync::setCACert(const char * rootCA) {
|
||||
_cfg.cacert_pem_buf = reinterpret_cast<const unsigned char *>(rootCA);
|
||||
_cfg.cacert_pem_bytes = strlen(rootCA) + 1;
|
||||
}
|
||||
|
||||
void ClientSecureSync::setCertificate(const char * clientCert) {
|
||||
_cfg.clientcert_pem_buf = reinterpret_cast<const unsigned char *>(clientCert);
|
||||
_cfg.clientcert_pem_bytes = strlen(clientCert) + 1;
|
||||
}
|
||||
|
||||
void ClientSecureSync::setPrivateKey(const char * privateKey) {
|
||||
_cfg.clientkey_pem_buf = reinterpret_cast<const unsigned char *>(privateKey);
|
||||
_cfg.clientkey_pem_bytes = strlen(privateKey) + 1;
|
||||
}
|
||||
|
||||
void ClientSecureSync::setPreSharedKey(const char * pskIdent, const char * psKey) {
|
||||
#if defined(CONFIG_ESP_TLS_PSK_VERIFICATION)
|
||||
_psk.hint = pskIdent;
|
||||
size_t key_len = strlen(psKey) / 2;
|
||||
if (key_len > sizeof(_psk_key)) {
|
||||
key_len = sizeof(_psk_key);
|
||||
}
|
||||
for (size_t i = 0; i < key_len; i++) {
|
||||
sscanf(psKey + 2 * i, "%2hhx", &_psk_key[i]);
|
||||
}
|
||||
_psk.key = _psk_key;
|
||||
_psk.key_size = key_len;
|
||||
_cfg.psk_hint_key = &_psk;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ClientSecureSync::setInsecure() {
|
||||
_cfg.cacert_pem_buf = nullptr;
|
||||
_cfg.cacert_pem_bytes = 0;
|
||||
_cfg.crt_bundle_attach = nullptr;
|
||||
_cfg.use_global_ca_store = false;
|
||||
_cfg.skip_common_name = true;
|
||||
}
|
||||
|
||||
} // namespace espMqttClientInternals
|
||||
|
||||
|
||||
Reference in New Issue
Block a user