Compare commits

..

18 Commits

Author SHA1 Message Date
85a8dac42d Merge pull request #750 from david-cermak/bump/ws_client
[websocket]:  Bump 1.3.0 -> 1.4.0
2025-01-30 08:48:45 +01:00
39866116f5 bump(websocket): 1.3.0 -> 1.4.0
1.4.0
Features
- Support DS peripheral for mutual TLS (55385ec3)
Bug Fixes
- wait for task on destroy (42674b49)
- Fix pytest to verify client correctly (9046af8f)
- propagate error type (eeeb9006)
- fix example buffer leak (5219c39d)
Updated
- chore(websocket): align structure members (beb6e57e)
- chore(websocket): remove unused client variable (15d3a01e)
2025-01-30 07:16:24 +01:00
7740b591b6 Merge pull request #749 from david-cermak/fix/ws_client_test
[websocket]: Fix pytest to verify client correctly
2025-01-30 07:09:34 +01:00
b57979d967 Merge pull request #751 from johanstokking/fix/await-task-on-destroy
fix(websocket): wait for task on destroy (IDFGH-14533)
2025-01-29 15:27:38 +01:00
42674b49f9 fix(websocket): wait for task on destroy 2025-01-29 14:30:32 +01:00
e069ae7762 Merge pull request #520 from johanstokking/feature/websocket/client_ds_data
feat(websocket): Support DS peripheral for mutual TLS (IDFGH-12285)
2025-01-28 16:59:34 +01:00
44d476fc50 docs(websocket): fix minor readability issues 2025-01-28 14:59:24 +01:00
55385ec312 feat(websocket): Support DS peripheral for mutual TLS 2025-01-28 14:58:54 +01:00
a3c2bbed9e Merge pull request #748 from david-cermak/fix/mdns_coverity
[mdns]: Bump v1.5.2
2025-01-28 10:23:24 +01:00
84c47c37f1 bump(mdns): 1.5.1 -> 1.5.2
1.5.2
Bug Fixes
- Fix potential NULL deref when sending sub-buy (e7273c46)
- Fix _mdns_append_fqdn excessive stack usage (bd23c233)
2025-01-28 09:54:54 +01:00
e7273c46ec fix(mdns): Fix potential NULL deref when sending sub-buy
Closes coverity reported issue: 473829 Dereference null return value
2025-01-28 09:54:16 +01:00
2e7d240abd Merge pull request #744 from andrew-lifx/fix/mdns_append_fqdn
fix(mdns): Fix _mdns_append_fqdn excessive stack usage (IDFGH-14506)
2025-01-28 07:28:00 +01:00
d4a004b5b4 Merge pull request #694 from johanstokking/fix/websocket-esp-tls-errors
fix(websocket): propagate error type (IDFGH-14518)
2025-01-27 15:50:32 +01:00
9046af8f8d fix(websocket): Fix pytest to verify client correctly 2025-01-27 15:34:49 +01:00
eeeb9006eb fix(websocket): propagate error type 2025-01-25 21:52:06 +01:00
b167aa315f Merge pull request #747 from david-cermak/fix/publish_asio_1.32
bump(asio): Publish 1.32.0 to component manager
2025-01-24 15:53:54 +01:00
72ba24470d bump(asio): Publish 1.32.0 to component manager
Related to the bump-commit: ac6a388cdd
but missed to update idf_component.yml
This publishes ASIO-1.32-0~0
2025-01-24 14:32:20 +01:00
bd23c233a4 fix(mdns): Fix _mdns_append_fqdn excessive stack usage
Move "mdns_name_t name" declaration inside loop to move it out of scope and reclain stack space before recursion call.
2025-01-24 17:39:04 +10:30
12 changed files with 110 additions and 31 deletions

View File

@ -1,4 +1,4 @@
version: "1.28.2~0"
version: "1.32.0"
description: Cross-platform C++ library for network and I/O programming
url: https://github.com/espressif/esp-protocols/tree/master/components/asio
issues: https://github.com/espressif/esp-protocols/issues

View File

@ -3,6 +3,6 @@ commitizen:
bump_message: 'bump(websocket): $current_version -> $new_version'
pre_bump_hooks: python ../../ci/changelog.py esp_websocket_client
tag_format: websocket-v$version
version: 1.3.0
version: 1.4.0
version_files:
- idf_component.yml

View File

@ -1,5 +1,23 @@
# Changelog
## [1.4.0](https://github.com/espressif/esp-protocols/commits/websocket-v1.4.0)
### Features
- Support DS peripheral for mutual TLS ([55385ec3](https://github.com/espressif/esp-protocols/commit/55385ec3))
### Bug Fixes
- wait for task on destroy ([42674b49](https://github.com/espressif/esp-protocols/commit/42674b49))
- Fix pytest to verify client correctly ([9046af8f](https://github.com/espressif/esp-protocols/commit/9046af8f))
- propagate error type ([eeeb9006](https://github.com/espressif/esp-protocols/commit/eeeb9006))
- fix example buffer leak ([5219c39d](https://github.com/espressif/esp-protocols/commit/5219c39d))
### Updated
- chore(websocket): align structure members ([beb6e57e](https://github.com/espressif/esp-protocols/commit/beb6e57e))
- chore(websocket): remove unused client variable ([15d3a01e](https://github.com/espressif/esp-protocols/commit/15d3a01e))
## [1.3.0](https://github.com/espressif/esp-protocols/commits/websocket-v1.3.0)
### Features

View File

@ -93,6 +93,9 @@ typedef struct {
size_t client_cert_len;
const char *client_key;
size_t client_key_len;
#if CONFIG_ESP_TLS_USE_DS_PERIPHERAL
void *client_ds_data;
#endif
bool use_global_ca_store;
bool skip_cert_common_name_check;
const char *cert_common_name;
@ -234,9 +237,9 @@ static esp_err_t esp_websocket_client_abort_connection(esp_websocket_client_hand
} else {
client->reconnect_tick_ms = _tick_get_ms();
ESP_LOGI(TAG, "Reconnect after %d ms", client->wait_timeout_ms);
client->error_handle.error_type = error_type;
client->state = WEBSOCKET_STATE_WAIT_TIMEOUT;
}
client->error_handle.error_type = error_type;
esp_websocket_client_dispatch_event(client, WEBSOCKET_EVENT_DISCONNECTED, NULL, 0);
return ESP_OK;
}
@ -446,6 +449,21 @@ static void destroy_and_free_resources(esp_websocket_client_handle_t client)
client = NULL;
}
static esp_err_t stop_wait_task(esp_websocket_client_handle_t client)
{
/* A running client cannot be stopped from the websocket task/event handler */
TaskHandle_t running_task = xTaskGetCurrentTaskHandle();
if (running_task == client->task_handle) {
ESP_LOGE(TAG, "Client cannot be stopped from websocket task");
return ESP_FAIL;
}
client->run = false;
xEventGroupWaitBits(client->status_bits, STOPPED_BIT, false, true, portMAX_DELAY);
client->state = WEBSOCKET_STATE_UNKNOW;
return ESP_OK;
}
static esp_err_t set_websocket_transport_optional_settings(esp_websocket_client_handle_t client, const char *scheme)
{
esp_transport_handle_t trans = esp_transport_list_get_transport(client->transport_list, scheme);
@ -531,6 +549,10 @@ static esp_err_t esp_websocket_client_create_transport(esp_websocket_client_hand
} else {
esp_transport_ssl_set_client_key_data_der(ssl, client->config->client_key, client->config->client_key_len);
}
#if CONFIG_ESP_TLS_USE_DS_PERIPHERAL
} else if (client->config->client_ds_data) {
esp_transport_ssl_set_ds_data(ssl, client->config->client_ds_data);
#endif
}
if (client->config->crt_bundle_attach) {
#ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
@ -696,6 +718,9 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie
client->config->client_cert_len = config->client_cert_len;
client->config->client_key = config->client_key;
client->config->client_key_len = config->client_key_len;
#if CONFIG_ESP_TLS_USE_DS_PERIPHERAL
client->config->client_ds_data = config->client_ds_data;
#endif
client->config->skip_cert_common_name_check = config->skip_cert_common_name_check;
client->config->cert_common_name = config->cert_common_name;
client->config->crt_bundle_attach = config->crt_bundle_attach;
@ -744,6 +769,7 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie
ESP_WS_CLIENT_MEM_CHECK(TAG, client->status_bits, {
goto _websocket_init_fail;
});
xEventGroupSetBits(client->status_bits, STOPPED_BIT);
client->buffer_size = buffer_size;
return client;
@ -758,9 +784,11 @@ esp_err_t esp_websocket_client_destroy(esp_websocket_client_handle_t client)
if (client == NULL) {
return ESP_ERR_INVALID_ARG;
}
if (client->run) {
esp_websocket_client_stop(client);
if (client->status_bits && (STOPPED_BIT & xEventGroupGetBits(client->status_bits)) == 0) {
stop_wait_task(client);
}
destroy_and_free_resources(client);
return ESP_OK;
}
@ -1149,23 +1177,13 @@ esp_err_t esp_websocket_client_stop(esp_websocket_client_handle_t client)
if (client == NULL) {
return ESP_ERR_INVALID_ARG;
}
if (!client->run) {
if (xEventGroupGetBits(client->status_bits) & STOPPED_BIT) {
ESP_LOGW(TAG, "Client was not started");
return ESP_FAIL;
}
/* A running client cannot be stopped from the websocket task/event handler */
TaskHandle_t running_task = xTaskGetCurrentTaskHandle();
if (running_task == client->task_handle) {
ESP_LOGE(TAG, "Client cannot be stopped from websocket task");
return ESP_FAIL;
}
client->run = false;
xEventGroupWaitBits(client->status_bits, STOPPED_BIT, false, true, portMAX_DELAY);
client->state = WEBSOCKET_STATE_UNKNOW;
return ESP_OK;
return stop_wait_task(client);
}
static int esp_websocket_client_send_close(esp_websocket_client_handle_t client, int code, const char *additional_data, int total_len, TickType_t timeout)

View File

@ -55,7 +55,7 @@ class Websocket(object):
ssl_context.load_cert_chain(certfile='main/certs/server/server_cert.pem', keyfile='main/certs/server/server_key.pem')
if self.client_verify is True:
ssl_context.load_verify_locations(cafile='main/certs/ca_cert.pem')
ssl_context.verify = ssl.CERT_REQUIRED
ssl_context.verify_mode = ssl.CERT_REQUIRED
ssl_context.check_hostname = False
self.server = SimpleSSLWebSocketServer('', self.port, WebsocketTestEcho, ssl_context=ssl_context)
else:

View File

@ -1,4 +1,4 @@
version: "1.3.0"
version: "1.4.0"
description: WebSocket protocol client for ESP-IDF
url: https://github.com/espressif/esp-protocols/tree/master/components/esp_websocket_client
dependencies:

View File

@ -108,10 +108,13 @@ typedef struct {
int buffer_size; /*!< Websocket buffer size */
const char *cert_pem; /*!< Pointer to certificate data in PEM or DER format for server verify (with SSL), default is NULL, not required to verify the server. PEM-format must have a terminating NULL-character. DER-format requires the length to be passed in cert_len. */
size_t cert_len; /*!< Length of the buffer pointed to by cert_pem. May be 0 for null-terminated pem */
const char *client_cert; /*!< Pointer to certificate data in PEM or DER format for SSL mutual authentication, default is NULL, not required if mutual authentication is not needed. If it is not NULL, also `client_key` has to be provided. PEM-format must have a terminating NULL-character. DER-format requires the length to be passed in client_cert_len. */
const char *client_cert; /*!< Pointer to certificate data in PEM or DER format for SSL mutual authentication, default is NULL, not required if mutual authentication is not needed. If it is not NULL, also `client_key` or `client_ds_data` (if supported) has to be provided. PEM-format must have a terminating NULL-character. DER-format requires the length to be passed in client_cert_len. */
size_t client_cert_len; /*!< Length of the buffer pointed to by client_cert. May be 0 for null-terminated pem */
const char *client_key; /*!< Pointer to private key data in PEM or DER format for SSL mutual authentication, default is NULL, not required if mutual authentication is not needed. If it is not NULL, also `client_cert` has to be provided. PEM-format must have a terminating NULL-character. DER-format requires the length to be passed in client_key_len */
const char *client_key; /*!< Pointer to private key data in PEM or DER format for SSL mutual authentication, default is NULL, not required if mutual authentication is not needed. If it is not NULL, also `client_cert` has to be provided and `client_ds_data` (if supported) gets ignored. PEM-format must have a terminating NULL-character. DER-format requires the length to be passed in client_key_len */
size_t client_key_len; /*!< Length of the buffer pointed to by client_key_pem. May be 0 for null-terminated pem */
#if CONFIG_ESP_TLS_USE_DS_PERIPHERAL
void *client_ds_data; /*!< Pointer to the encrypted private key data for SSL mutual authentication using the DS peripheral, default is NULL, not required if mutual authentication is not needed. If it is not NULL, also `client_cert` has to be provided. It is ignored if `client_key` is provided */
#endif
esp_websocket_transport_t transport; /*!< Websocket transport type, see `esp_websocket_transport_t */
const char *subprotocol; /*!< Websocket subprotocol */
const char *user_agent; /*!< Websocket user-agent */

View File

@ -3,6 +3,6 @@ commitizen:
bump_message: 'bump(mdns): $current_version -> $new_version'
pre_bump_hooks: python ../../ci/changelog.py mdns
tag_format: mdns-v$version
version: 1.5.1
version: 1.5.2
version_files:
- idf_component.yml

View File

@ -1,5 +1,12 @@
# Changelog
## [1.5.2](https://github.com/espressif/esp-protocols/commits/mdns-v1.5.2)
### Bug Fixes
- Fix potential NULL deref when sending sub-buy ([e7273c46](https://github.com/espressif/esp-protocols/commit/e7273c46))
- Fix _mdns_append_fqdn excessive stack usage ([bd23c233](https://github.com/espressif/esp-protocols/commit/bd23c233))
## [1.5.1](https://github.com/espressif/esp-protocols/commits/mdns-v1.5.1)
### Bug Fixes

View File

@ -1,4 +1,4 @@
version: "1.5.1"
version: "1.5.2"
description: "Multicast UDP service used to provide local network service and host discovery."
url: "https://github.com/espressif/esp-protocols/tree/master/components/mdns"
issues: "https://github.com/espressif/esp-protocols/issues"

View File

@ -751,12 +751,12 @@ static uint16_t _mdns_append_fqdn(uint8_t *packet, uint16_t *index, const char *
//empty string so terminate
return _mdns_append_u8(packet, index, 0);
}
mdns_name_t name;
static char buf[MDNS_NAME_BUF_LEN];
uint8_t len = strlen(strings[0]);
//try to find first the string length in the packet (if it exists)
uint8_t *len_location = (uint8_t *)memchr(packet, (char)len, *index);
while (len_location) {
mdns_name_t name;
//check if the string after len_location is the string that we are looking for
if (memcmp(len_location + 1, strings[0], len)) { //not continuing with our string
search_next:
@ -2399,6 +2399,9 @@ static void _mdns_send_bye_subtype(mdns_srv_item_t *service, const char *instanc
for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) {
if (mdns_is_netif_ready(i, j)) {
mdns_tx_packet_t *packet = _mdns_alloc_packet_default((mdns_if_t)i, (mdns_ip_protocol_t)j);
if (packet == NULL) {
return;
}
packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE;
if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, service->service, NULL, true, true)) {
_mdns_free_tx_packet(packet);

View File

@ -66,13 +66,43 @@ Configuration:
.. note:: If you want to verify the server, then you need to provide a certificate in PEM format, and provide to ``cert_pem`` in :cpp:type:`websocket_client_config_t`. If no certficate is provided then the TLS connection will default to not requiring verification.
PEM certificate for this example could be extracted from an openssl `s_client` command connecting to websocket.org.
In case a host operating system has `openssl` and `sed` packages installed, one could execute the following command to download and save the root or intermediate root certificate to a file (Note for Windows users: Both Linux like environment or Windows native packages may be used).
```
echo "" | openssl s_client -showcerts -connect websocket.org:443 | sed -n "1,/Root/d; /BEGIN/,/END/p" | openssl x509 -outform PEM >websocket_org.pem
```
In case a host operating system has `openssl` and `sed` packages installed, one could execute the following command to download and save the root or intermediate root certificate to a file (Note for Windows users: Both Linux like environment or Windows native packages may be used). ::
echo "" | openssl s_client -showcerts -connect websocket.org:443 \
| sed -n "1,/Root/d; /BEGIN/,/END/p" \
| openssl x509 -outform PEM \
> websocket_org.pem
This command will extract the second certificate in the chain and save it as a pem-file.
Mutual TLS with DS Peripheral
"""""""""""""""""""""""""""""
To leverage the Digital Signature (DS) peripheral on supported targets, use `esp_secure_cert_mgr <https://github.com/espressif/esp_secure_cert_mgr/>`_ to flash an encrypted client certificate. In your project, add the dependency: ::
idf.py add-dependency esp_secure_cert_mgr
Set ``client_cert`` and ``client_ds_data`` in the config struct:
.. code:: c
char *client_cert = NULL;
uint32_t client_cert_len = 0;
esp_err_t err = esp_secure_cert_get_device_cert(&client_cert, &client_cert_len);
assert(err == ESP_OK);
esp_ds_data_ctx_t *ds_data = esp_secure_cert_get_ds_ctx();
assert(ds_data != NULL);
esp_websocket_client_config_t config = {
.uri = "wss://echo.websocket.org",
.cert_pem = (const char *)websocket_org_pem_start,
.client_cert = client_cert,
.client_ds_data = ds_data,
};
.. note:: ``client_cert`` provided by `esp_secure_cert_mgr` is a null-terminated PEM; so ``client_cert_len`` (DER format) should not be set.
Subprotocol
^^^^^^^^^^^
@ -91,14 +121,14 @@ For more options on :cpp:type:`esp_websocket_client_config_t`, please refer to A
Events
------
* `WEBSOCKET_EVENT_BEGIN': The client thread is running.
* `WEBSOCKET_EVENT_BEGIN`: The client thread is running.
* `WEBSOCKET_EVENT_BEFORE_CONNECT`: The client is about to connect.
* `WEBSOCKET_EVENT_CONNECTED`: The client has successfully established a connection to the server. The client is now ready to send and receive data. Contains no event data.
* `WEBSOCKET_EVENT_DATA`: The client has successfully received and parsed a WebSocket frame. The event data contains a pointer to the payload data, the length of the payload data as well as the opcode of the received frame. A message may be fragmented into multiple events if the length exceeds the buffer size. This event will also be posted for non-payload frames, e.g. pong or connection close frames.
* `WEBSOCKET_EVENT_ERROR`: The client has experienced an error. Examples include transport write or read failures.
* `WEBSOCKET_EVENT_DISCONNECTED`: The client has aborted the connection due to the transport layer failing to read data, e.g. because the server is unavailable. Contains no event data.
* `WEBSOCKET_EVENT_CLOSED`: The connection has been closed cleanly.
* `WEBSOCKET_EVENT_FINISH': The client thread is about to exit.
* `WEBSOCKET_EVENT_FINISH`: The client thread is about to exit.
If the client handle is needed in the event handler it can be accessed through the pointer passed to the event handler: