-
Notifications
You must be signed in to change notification settings - Fork 7.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
tls transport StoreProhibited exception when connection closed by server (IDFGH-7307) #8895
Comments
Hi @MarcGeh Thanks for the report! esp-idf/components/esp_websocket_client/esp_websocket_client.c Lines 332 to 339 in 8c8f700
Sorry for the inconvenience, will fix it soon (similar issue has been fixed recently in e794786, again partly initialized transport, using one layer separately) |
Hi @david-cermak thanks for the fast response. I need to use websockets in the future anyways, so I might switch over to use the websocket client right away to avoid this issue. |
Is there a workaround for this issue. Alle esp32 examples seems to be based on the same initialization using TLS. I am not sure how to fix this. |
@tmaltesen for now you should use all transports from a |
Thanks a lot for the info. |
Look into Cermak 's answer for an example. You may also open a new issue with the description of the problem you are facing, presenting a short example on how you are using |
Thanks again :-) |
@tmaltesen Unfortunately you will not make this work unless you are willing to make some minor changes to the transport_tls_esp32.c file. If this is an option for you I can guide you through this. |
This is an option, absolutely 😊
Fra: Marc Geh ***@***.***>
Sendt: 23. juni 2022 17:34
Til: espressif/esp-idf ***@***.***>
Cc: Thomas Maltesen ***@***.***>; Mention ***@***.***>
Emne: Re: [espressif/esp-idf] tls transport StoreProhibited exception when connection closed by server (IDFGH-7307) (Issue #8895)
@tmaltesen<https://github.com/tmaltesen> Unfortunately you will not make this work unless you are willing to make some minor changes to the transport_tls_esp32.c<https://github.com/Azure-Samples/iot-middleware-freertos-samples/blob/main/demos/projects/ESPRESSIF/esp32/components/sample-azure-iot/transport_tls_esp32.c> file. If this is an option for you I can guide you through this.
—
Reply to this email directly, view it on GitHub<#8895 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AEBLZUO4VNU57YIY6NNB5KTVQR7XZANCNFSM5VBVLNSQ>.
You are receiving this because you were mentioned.Message ID: ***@***.******@***.***>>
|
Very much appreciated if you have a workaround that I am able to implement.
The esp-idf is completely new to me but I’m experienced C/C++ embedded programmer.
But still struggling a bit to learn the build environment.
/Thomas
Fra: Marc Geh ***@***.***>
Sendt: 23. juni 2022 17:34
Til: espressif/esp-idf ***@***.***>
Cc: Thomas Maltesen ***@***.***>; Mention ***@***.***>
Emne: Re: [espressif/esp-idf] tls transport StoreProhibited exception when connection closed by server (IDFGH-7307) (Issue #8895)
@tmaltesen<https://github.com/tmaltesen> Unfortunately you will not make this work unless you are willing to make some minor changes to the transport_tls_esp32.c<https://github.com/Azure-Samples/iot-middleware-freertos-samples/blob/main/demos/projects/ESPRESSIF/esp32/components/sample-azure-iot/transport_tls_esp32.c> file. If this is an option for you I can guide you through this.
—
Reply to this email directly, view it on GitHub<#8895 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AEBLZUO4VNU57YIY6NNB5KTVQR7XZANCNFSM5VBVLNSQ>.
You are receiving this because you were mentioned.Message ID: ***@***.******@***.***>>
|
Change the NetworkContext definition to have an esp_transport_list_handle_t and a scheme name instead of the esp_transport_handle_t so it looks like this: struct NetworkContext {
const char* scheme;
esp_transport_list_handle_t xTransportList;
uint32_t ulReceiveTimeoutMs;
uint32_t ulSendTimeoutMs;
}; Now in each function where pNetworkContext->xTransport is used, replace it by a local variable initialized like this: esp_transport_handle_t xTransport = esp_transport_list_get_transport(pNetworkContext->xTransportList, pNetworkContext->scheme);
if (xTransport == NULL) {
ESP_LOGE(TAG, "Failed to get transport handle for scheme %s", pNetworkContext->scheme);
return eTLSTransportInvalidParameter;
} You still have to properly initialize the network struct and hand it over to the IoT client as part of the AzureIoTTransportInterface_t. E.g. my initialization of it looks like this: memset(&network_context_, 0, sizeof(NetworkContext_t));
network_context_.xTransportList = esp_transport_list_init();
network_context_.scheme = "_mqtt";
if (network_context_.xTransportList == NULL) {
ESP_LOGE(TAG, "Failed to create transport list");
} else {
esp_transport_handle_t mqtt = esp_transport_ssl_init();
if (mqtt == NULL) {
ESP_LOGE(TAG, "Failed to create transport handle");
} else {
esp_transport_list_add(network_context_.xTransportList, mqtt, network_context_.scheme);
}
} Keep in mind that in the original example the call to esp_transport_ssl_init() was inside the TLS_Socket_Connect function. Now the initialization is handled outside of that module, so you have to take care to also tear it down once you are done with it. /*-----------------------------------------------------------*/
TlsTransportStatus_t TLS_Socket_Connect(NetworkContext_t *pNetworkContext, const char *pHostName, uint16_t usPort,
const NetworkCredentials_t *pNetworkCredentials, uint32_t ulReceiveTimeoutMs, uint32_t ulSendTimeoutMs) {
TlsTransportStatus_t xReturnStatus = eTLSTransportSuccess;
if ((pNetworkContext == NULL) || (pHostName == NULL) || (pNetworkCredentials == NULL)) {
ESP_LOGE(TAG,
"Invalid input parameter(s): Arguments cannot be NULL. pNetworkContext=%p, "
"pHostName=%p, pNetworkCredentials=%p.",
pNetworkContext, pHostName, pNetworkCredentials);
return eTLSTransportInvalidParameter;
}
esp_transport_handle_t xTransport = esp_transport_list_get_transport(pNetworkContext->xTransportList, pNetworkContext->scheme);
if (xTransport == NULL) {
ESP_LOGE(TAG, "Failed to get transport handle for scheme %s", pNetworkContext->scheme);
return eTLSTransportInvalidParameter;
}
pNetworkContext->ulReceiveTimeoutMs = ulReceiveTimeoutMs;
pNetworkContext->ulSendTimeoutMs = ulSendTimeoutMs;
if (pNetworkCredentials->ppcAlpnProtos) {
esp_transport_ssl_set_alpn_protocol(xTransport, pNetworkCredentials->ppcAlpnProtos);
}
if (pNetworkCredentials->xDisableSni) {
esp_transport_ssl_skip_common_name_check(xTransport);
}
if (pNetworkCredentials->pucRootCa) {
esp_transport_ssl_set_cert_data(xTransport, pNetworkCredentials->pucRootCa, strlen(pNetworkCredentials->pucRootCa));
}
if (pNetworkCredentials->pucClientCert) {
esp_transport_ssl_set_client_cert_data(xTransport, pNetworkCredentials->pucClientCert, strlen(pNetworkCredentials->pucClientCert));
}
if (pNetworkCredentials->pucPrivateKey) {
esp_transport_ssl_set_client_key_data(xTransport, pNetworkCredentials->pucPrivateKey, strlen(pNetworkCredentials->pucPrivateKey));
}
if (esp_transport_connect(xTransport, pHostName, usPort, 10000) < 0) {
ESP_LOGE(TAG, "Failed establishing TLS connection (esp_transport_connect failed)");
xReturnStatus = eTLSTransportConnectFailure;
} else {
xReturnStatus = eTLSTransportSuccess;
}
/* Clean up on failure. */
if (xReturnStatus != eTLSTransportSuccess) {
if (pNetworkContext != NULL) {
esp_transport_close(xTransport);
}
} else {
ESP_LOGI(TAG, "(Network connection %p) Connection to %s established.", pNetworkContext, pHostName);
}
return xReturnStatus;
}
/*-----------------------------------------------------------*/
void TLS_Socket_Disconnect(NetworkContext_t *pNetworkContext) {
if ((pNetworkContext == NULL)) {
ESP_LOGE(TAG, "Invalid input parameter(s): Arguments cannot be NULL. pNetworkContext=%p.", pNetworkContext);
return;
}
esp_transport_handle_t xTransport = esp_transport_list_get_transport(pNetworkContext->xTransportList, pNetworkContext->scheme);
if (xTransport == NULL) {
ESP_LOGE(TAG, "Failed to get transport handle for scheme %s", pNetworkContext->scheme);
return;
}
/* Attempting to terminate TLS connection. */
esp_transport_close(xTransport);
}
/*-----------------------------------------------------------*/
int32_t TLS_Socket_Recv(NetworkContext_t *pNetworkContext, void *pBuffer, size_t xBytesToRecv) {
int32_t tlsStatus = 0;
if ((pNetworkContext == NULL) || (pBuffer == NULL) || (xBytesToRecv == 0)) {
ESP_LOGE(TAG,
"Invalid input parameter(s): Arguments cannot be NULL. pNetworkContext=%p, "
"pBuffer=%p, xBytesToRecv=%d.",
pNetworkContext, pBuffer, xBytesToRecv);
return eTLSTransportInvalidParameter;
}
esp_transport_handle_t xTransport = esp_transport_list_get_transport(pNetworkContext->xTransportList, pNetworkContext->scheme);
if (xTransport == NULL) {
ESP_LOGE(TAG, "Failed to get transport handle for scheme %s", pNetworkContext->scheme);
return eTLSTransportInvalidParameter;
}
tlsStatus = esp_transport_read(xTransport, pBuffer, xBytesToRecv, pNetworkContext->ulReceiveTimeoutMs);
if (tlsStatus < 0) {
ESP_LOGE(TAG, "Reading failed, errno= %d", errno);
return ESP_FAIL;
}
return tlsStatus;
}
/*-----------------------------------------------------------*/
int32_t TLS_Socket_Send(NetworkContext_t *pNetworkContext, const void *pBuffer, size_t xBytesToSend) {
int32_t tlsStatus = 0;
if ((pNetworkContext == NULL) || (pBuffer == NULL) || (xBytesToSend == 0)) {
ESP_LOGE(TAG,
"Invalid input parameter(s): Arguments cannot be NULL. pNetworkContext=%p, "
"pBuffer=%p, xBytesToSend=%d.",
pNetworkContext, pBuffer, xBytesToSend);
return eTLSTransportInvalidParameter;
}
esp_transport_handle_t xTransport = esp_transport_list_get_transport(pNetworkContext->xTransportList, pNetworkContext->scheme);
if (xTransport == NULL) {
ESP_LOGE(TAG, "Failed to get transport handle for scheme %s", pNetworkContext->scheme);
return eTLSTransportInvalidParameter;
}
tlsStatus = esp_transport_write(xTransport, pBuffer, xBytesToSend, pNetworkContext->ulSendTimeoutMs);
if (tlsStatus < 0) {
ESP_LOGE(TAG, "Writing failed, errno= %d", errno);
return ESP_FAIL;
}
return tlsStatus;
}
/*-----------------------------------------------------------*/ |
So great, a single clearifcations about initialization and cleanup.
The initialization code:
memset(&network_context_, 0, sizeof(NetworkContext_t));
network_context_.xTransportList = esp_transport_list_init();
network_context_.scheme = "_mqtt";
…..
Did you put that in the prvConnectToServerWithBackoffRetries or even higher into the prvAzureTask. It makes sense in the main AzureTask since the destroy of the transport list can be done when /if the task loop is exited.
/Thomas
Fra: Marc Geh ***@***.***>
Sendt: 23. juni 2022 18:05
Til: espressif/esp-idf ***@***.***>
Cc: Thomas Maltesen ***@***.***>; Mention ***@***.***>
Emne: Re: [espressif/esp-idf] tls transport StoreProhibited exception when connection closed by server (IDFGH-7307) (Issue #8895)
Change the NetworkContext definition to have an esp_transport_list_handle_t and a scheme name instead of the esp_transport_handle_t<https://github.com/Azure-Samples/iot-middleware-freertos-samples/blob/154ba9fbd280b855c6e49e6e9c9ee34c35705c0f/demos/projects/ESPRESSIF/esp32/components/sample-azure-iot/transport_tls_esp32.c#L47> so it looks like this:
struct NetworkContext {
const char* scheme;
esp_transport_list_handle_t xTransportList;
uint32_t ulReceiveTimeoutMs;
uint32_t ulSendTimeoutMs;
};
Now in each function where pNetworkContext->xTransport is used, replace it by a local variable initialized like this:
esp_transport_handle_t xTransport = esp_transport_list_get_transport(pNetworkContext->xTransportList, pNetworkContext->scheme);
if (xTransport == NULL) {
ESP_LOGE(TAG, "Failed to get transport handle for scheme %s", pNetworkContext->scheme);
return eTLSTransportInvalidParameter;
}
You still have to properly initialize the network struct and hand it over to the IoT client as part of the AzureIoTTransportInterface_t. My initialization of it looks e.g. like this:
memset(&network_context_, 0, sizeof(NetworkContext_t));
network_context_.xTransportList = esp_transport_list_init();
network_context_.scheme = "_mqtt";
if (network_context_.xTransportList == NULL) {
ESP_LOGE(TAG, "Failed to create transport list");
} else {
esp_transport_handle_t mqtt = esp_transport_ssl_init();
if (mqtt == NULL) {
ESP_LOGE(TAG, "Failed to create transport handle");
} else {
esp_transport_list_add(network_context_.xTransportList, mqtt, network_context_.scheme);
}
}
Keep in mind that in the original example the call to esp_transport_ssl_init() was inside the TLS_Socket_Connect function. Now the initialization is handled outside of that module, so you have to take care to also tear it down once you are done with it.
For completeness, this is how your functions inside transport_tls_esp32.c should look like:
/*-----------------------------------------------------------*/
TlsTransportStatus_t TLS_Socket_Connect(NetworkContext_t *pNetworkContext, const char *pHostName, uint16_t usPort,
const NetworkCredentials_t *pNetworkCredentials, uint32_t ulReceiveTimeoutMs, uint32_t ulSendTimeoutMs) {
TlsTransportStatus_t xReturnStatus = eTLSTransportSuccess;
if ((pNetworkContext == NULL) || (pHostName == NULL) || (pNetworkCredentials == NULL)) {
ESP_LOGE(TAG,
"Invalid input parameter(s): Arguments cannot be NULL. pNetworkContext=%p, "
"pHostName=%p, pNetworkCredentials=%p.",
pNetworkContext, pHostName, pNetworkCredentials);
return eTLSTransportInvalidParameter;
}
esp_transport_handle_t xTransport = esp_transport_list_get_transport(pNetworkContext->xTransportList, pNetworkContext->scheme);
if (xTransport == NULL) {
ESP_LOGE(TAG, "Failed to get transport handle for scheme %s", pNetworkContext->scheme);
return eTLSTransportInvalidParameter;
}
pNetworkContext->ulReceiveTimeoutMs = ulReceiveTimeoutMs;
pNetworkContext->ulSendTimeoutMs = ulSendTimeoutMs;
if (pNetworkCredentials->ppcAlpnProtos) {
esp_transport_ssl_set_alpn_protocol(xTransport, pNetworkCredentials->ppcAlpnProtos);
}
if (pNetworkCredentials->xDisableSni) {
esp_transport_ssl_skip_common_name_check(xTransport);
}
if (pNetworkCredentials->pucRootCa) {
esp_transport_ssl_set_cert_data(xTransport, pNetworkCredentials->pucRootCa, strlen(pNetworkCredentials->pucRootCa));
}
if (pNetworkCredentials->pucClientCert) {
esp_transport_ssl_set_client_cert_data(xTransport, pNetworkCredentials->pucClientCert, strlen(pNetworkCredentials->pucClientCert));
}
if (pNetworkCredentials->pucPrivateKey) {
esp_transport_ssl_set_client_key_data(xTransport, pNetworkCredentials->pucPrivateKey, strlen(pNetworkCredentials->pucPrivateKey));
}
if (esp_transport_connect(xTransport, pHostName, usPort, 10000) < 0) {
ESP_LOGE(TAG, "Failed establishing TLS connection (esp_transport_connect failed)");
xReturnStatus = eTLSTransportConnectFailure;
} else {
xReturnStatus = eTLSTransportSuccess;
}
/* Clean up on failure. */
if (xReturnStatus != eTLSTransportSuccess) {
if (pNetworkContext != NULL) {
esp_transport_close(xTransport);
}
} else {
ESP_LOGI(TAG, "(Network connection %p) Connection to %s established.", pNetworkContext, pHostName);
}
return xReturnStatus;
}
/*-----------------------------------------------------------*/
void TLS_Socket_Disconnect(NetworkContext_t *pNetworkContext) {
if ((pNetworkContext == NULL)) {
ESP_LOGE(TAG, "Invalid input parameter(s): Arguments cannot be NULL. pNetworkContext=%p.", pNetworkContext);
return;
}
esp_transport_handle_t xTransport = esp_transport_list_get_transport(pNetworkContext->xTransportList, pNetworkContext->scheme);
if (xTransport == NULL) {
ESP_LOGE(TAG, "Failed to get transport handle for scheme %s", pNetworkContext->scheme);
return;
}
/* Attempting to terminate TLS connection. */
esp_transport_close(xTransport);
}
/*-----------------------------------------------------------*/
int32_t TLS_Socket_Recv(NetworkContext_t *pNetworkContext, void *pBuffer, size_t xBytesToRecv) {
int32_t tlsStatus = 0;
if ((pNetworkContext == NULL) || (pBuffer == NULL) || (xBytesToRecv == 0)) {
ESP_LOGE(TAG,
"Invalid input parameter(s): Arguments cannot be NULL. pNetworkContext=%p, "
"pBuffer=%p, xBytesToRecv=%d.",
pNetworkContext, pBuffer, xBytesToRecv);
return eTLSTransportInvalidParameter;
}
esp_transport_handle_t xTransport = esp_transport_list_get_transport(pNetworkContext->xTransportList, pNetworkContext->scheme);
if (xTransport == NULL) {
ESP_LOGE(TAG, "Failed to get transport handle for scheme %s", pNetworkContext->scheme);
return eTLSTransportInvalidParameter;
}
tlsStatus = esp_transport_read(xTransport, pBuffer, xBytesToRecv, pNetworkContext->ulReceiveTimeoutMs);
if (tlsStatus < 0) {
ESP_LOGE(TAG, "Reading failed, errno= %d", errno);
return ESP_FAIL;
}
return tlsStatus;
}
/*-----------------------------------------------------------*/
int32_t TLS_Socket_Send(NetworkContext_t *pNetworkContext, const void *pBuffer, size_t xBytesToSend) {
int32_t tlsStatus = 0;
if ((pNetworkContext == NULL) || (pBuffer == NULL) || (xBytesToSend == 0)) {
ESP_LOGE(TAG,
"Invalid input parameter(s): Arguments cannot be NULL. pNetworkContext=%p, "
"pBuffer=%p, xBytesToSend=%d.",
pNetworkContext, pBuffer, xBytesToSend);
return eTLSTransportInvalidParameter;
}
esp_transport_handle_t xTransport = esp_transport_list_get_transport(pNetworkContext->xTransportList, pNetworkContext->scheme);
if (xTransport == NULL) {
ESP_LOGE(TAG, "Failed to get transport handle for scheme %s", pNetworkContext->scheme);
return eTLSTransportInvalidParameter;
}
tlsStatus = esp_transport_write(xTransport, pBuffer, xBytesToSend, pNetworkContext->ulSendTimeoutMs);
if (tlsStatus < 0) {
ESP_LOGE(TAG, "Writing failed, errno= %d", errno);
return ESP_FAIL;
}
return tlsStatus;
}
/*-----------------------------------------------------------*/
—
Reply to this email directly, view it on GitHub<#8895 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AEBLZUIMENYIAUCQ5PEZHGTVQSDLLANCNFSM5VBVLNSQ>.
You are receiving this because you were mentioned.Message ID: ***@***.******@***.***>>
|
Make it on a as high as possible layer, since it is actually encouraged to reuse the same handle for as long as possible. |
Great so much thank you – it seems to work.
Now the IoT loop iteration in the demo is continuing to run.
So it disconnects and connects again without crashing.
/Thomas
Fra: Marc Geh ***@***.***>
Sendt: 23. juni 2022 18:41
Til: espressif/esp-idf ***@***.***>
Cc: Thomas Maltesen ***@***.***>; Mention ***@***.***>
Emne: Re: [espressif/esp-idf] tls transport StoreProhibited exception when connection closed by server (IDFGH-7307) (Issue #8895)
Make it on a as high as possible layer, since it is actually encouraged to reuse the same handle for as long as possible.
—
Reply to this email directly, view it on GitHub<#8895 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AEBLZUPRICBDMDUVUDKTS6LVQSHSRANCNFSM5VBVLNSQ>.
You are receiving this because you were mentioned.Message ID: ***@***.******@***.***>>
|
Environment
Problem Description
Hi guys, I'm currently trying to bring up the azure-iot-middleware-freertos to connect the ESP32 to azure. I'm using tls sockets for the communication based on the esp32 example iot-middleware-freertos-samples
Once the server is closing the connection, the firmware crashes with the unhandled exception "StoreProhibited".
I'm using esp_transport_ssl_init() to initialize the context for the transaction.
esp_transport_connect and subsequent calls to esp_transport_read/esp_transport_write are successful as well, until the server closes the connection, then I get the exception on a call of esp_transport_read.
I've been tracing the issue back to transport.c, where in the function capture_tcp_transport_error the err_handle from the esp_transport_handle_t is used to save the error code of the transaction. However, the err_handle was never initialized and thus a write into a memory region referenced by a NULL pointer is attempted, which causes the problem. I'm writing this issue since it makes the impression onto me, that esp_transport_ssl_init does not initialize the context properly, since the esp_transport_init function called by the esp_transport_ssl_init function never initializes the underlying transport foundation which is referenced by the capture_tcp_transport_error function.
Steps to reproduce
You can try to run the example from iot-middleware-freertos-samples repository, but setting it up is quite a hassle.
Debug Logs
The text was updated successfully, but these errors were encountered: