Skip to content

Commit b0dd3ba

Browse files
kvp1703Amit Sheth
authored and
Amit Sheth
committed
Network Transport: APIs to set timeouts for MQTT connect, send and receive.
1 parent ed73104 commit b0dd3ba

File tree

2 files changed

+119
-46
lines changed

2 files changed

+119
-46
lines changed

libraries/coreMQTT/port/network_transport/network_transport.c

+95-45
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,23 @@
1111

1212
#define TAG "network_transport"
1313

14+
Timeouts_t timeouts = { .connectionTimeoutMs = 4000, .sendTimeoutMs = 10000, .recvTimeoutMs = 2000 };
15+
16+
void vTlsSetConnectTimeout( uint16_t connectionTimeoutMs )
17+
{
18+
timeouts.connectionTimeoutMs = connectionTimeoutMs;
19+
}
20+
21+
void vTlsSetSendTimeout( uint16_t sendTimeoutMs )
22+
{
23+
timeouts.sendTimeoutMs = sendTimeoutMs;
24+
}
25+
26+
void vTlsSetRecvTimeout( uint16_t recvTimeoutMs )
27+
{
28+
timeouts.recvTimeoutMs = recvTimeoutMs;
29+
}
30+
1431
TlsTransportStatus_t xTlsConnect( NetworkContext_t* pxNetworkContext )
1532
{
1633
TlsTransportStatus_t xResult = TLS_TRANSPORT_CONNECT_FAILURE;
@@ -26,11 +43,11 @@ TlsTransportStatus_t xTlsConnect( NetworkContext_t* pxNetworkContext )
2643
.ds_data = pxNetworkContext->ds_data,
2744
.clientkey_buf = ( const unsigned char* )( pxNetworkContext->pcClientKey ),
2845
.clientkey_bytes = pxNetworkContext->pcClientKeySize,
29-
.timeout_ms = 2000,
46+
.timeout_ms = timeouts.connectionTimeoutMs,
3047
.non_block = false,
3148
};
3249

33-
if( xSemaphoreTake(pxNetworkContext->xTlsContextSemaphore, portMAX_DELAY) == pdTRUE )
50+
if( xSemaphoreTake( pxNetworkContext->xTlsContextSemaphore, portMAX_DELAY ) == pdTRUE )
3451
{
3552
int lConnectResult = -1;
3653
esp_tls_t * pxTls = esp_tls_init();
@@ -46,13 +63,12 @@ TlsTransportStatus_t xTlsConnect( NetworkContext_t* pxNetworkContext )
4663

4764
if( lConnectResult == 1 )
4865
{
49-
5066
int lSockFd = -1;
51-
if( esp_tls_get_conn_sockfd(pxNetworkContext->pxTls, &lSockFd) == ESP_OK)
67+
if( esp_tls_get_conn_sockfd( pxNetworkContext->pxTls, &lSockFd ) == ESP_OK )
5268
{
53-
int flags = fcntl(lSockFd, F_GETFL);
69+
int flags = fcntl( lSockFd, F_GETFL );
5470

55-
if( fcntl(lSockFd, F_SETFL, flags | O_NONBLOCK ) != -1)
71+
if( fcntl( lSockFd, F_SETFL, flags | O_NONBLOCK ) != -1 )
5672
{
5773
xResult = TLS_TRANSPORT_SUCCESS;
5874
}
@@ -63,6 +79,8 @@ TlsTransportStatus_t xTlsConnect( NetworkContext_t* pxNetworkContext )
6379
{
6480
esp_tls_conn_destroy( pxNetworkContext->pxTls );
6581
pxNetworkContext->pxTls = NULL;
82+
} else
83+
{
6684
}
6785
}
6886
( void ) xSemaphoreGive( pxNetworkContext->xTlsContextSemaphore );
@@ -81,7 +99,7 @@ TlsTransportStatus_t xTlsDisconnect( NetworkContext_t* pxNetworkContext )
8199
{
82100
xResult = TLS_TRANSPORT_SUCCESS;
83101
}
84-
else if(esp_tls_conn_destroy(pxNetworkContext->pxTls ) == 0)
102+
else if( esp_tls_conn_destroy(pxNetworkContext->pxTls ) == 0)
85103
{
86104
xResult = TLS_TRANSPORT_SUCCESS;
87105
}
@@ -101,7 +119,7 @@ TlsTransportStatus_t xTlsDisconnect( NetworkContext_t* pxNetworkContext )
101119
}
102120

103121
int32_t espTlsTransportSend( NetworkContext_t* pxNetworkContext,
104-
const void* pvData, size_t uxDataLen)
122+
const void* pvData, size_t uxDataLen )
105123
{
106124
int32_t lBytesSent = -1;
107125

@@ -111,18 +129,19 @@ int32_t espTlsTransportSend( NetworkContext_t* pxNetworkContext,
111129
( pxNetworkContext->pxTls != NULL ) )
112130
{
113131
TimeOut_t xTimeout;
114-
TickType_t xTicksToWait = pdMS_TO_TICKS(10);
115-
116132
vTaskSetTimeOutState( &xTimeout );
117133

134+
struct timeval timeout = { .tv_usec = timeouts.sendTimeoutMs * 1000, .tv_sec = 0 };
135+
TickType_t xTicksToWait = pdMS_TO_TICKS( timeouts.sendTimeoutMs );
136+
TickType_t start_tick = xTaskGetTickCount();
137+
118138
if( xSemaphoreTake( pxNetworkContext->xTlsContextSemaphore, xTicksToWait ) == pdTRUE )
119139
{
120140
int lSockFd = -1;
121141
esp_err_t xError = esp_tls_get_conn_sockfd( pxNetworkContext->pxTls, &lSockFd );
122-
if( xError == ESP_OK)
142+
if( xError == ESP_OK )
123143
{
124144
unsigned char * pucData = ( unsigned char * ) pvData;
125-
struct timeval timeout = { .tv_usec = 10000, .tv_sec = 0 };
126145
lBytesSent = 0;
127146
do
128147
{
@@ -132,25 +151,25 @@ int32_t espTlsTransportSend( NetworkContext_t* pxNetworkContext,
132151

133152
FD_ZERO( &write_fds );
134153
FD_SET( lSockFd, &write_fds );
135-
136154
FD_ZERO( &error_fds );
137155
FD_SET( lSockFd, &error_fds );
138156

157+
suseconds_t elapsed_time_usec = ( xTaskGetTickCount() - start_tick ) * portTICK_PERIOD_MS * 1000;
158+
timeout.tv_usec = ( timeout.tv_usec - elapsed_time_usec >= 0 ) ? timeout.tv_usec - elapsed_time_usec : 0;
139159
lSelectResult = select( lSockFd + 1, NULL, &write_fds, &error_fds, &timeout );
140160

141161
if( lSelectResult < 0 )
142162
{
143163
lBytesSent = -1;
144-
ESP_LOGE(TAG, "Error during call to select.");
145-
break;
164+
ESP_LOGE( TAG, "Error during call to select." );
146165
}
147166
else if( ( lSelectResult > 0 ) && ( FD_ISSET( lSockFd, &write_fds ) != 0 ) )
148167
{
149168
ssize_t lResult = esp_tls_conn_write( pxNetworkContext->pxTls,
150-
&(pucData[lBytesSent]),
169+
&( pucData[lBytesSent] ),
151170
uxDataLen - lBytesSent );
152171

153-
if( lResult > 0 )
172+
if( lResult >= 0 )
154173
{
155174
lBytesSent += ( int32_t ) lResult;
156175
}
@@ -161,22 +180,17 @@ int32_t espTlsTransportSend( NetworkContext_t* pxNetworkContext,
161180
}
162181
else
163182
{
164-
/* Empty when lResult == 0 */
165-
}
166-
167-
if( ( lBytesSent < 0 ) ||
168-
( lBytesSent == uxDataLen ) )
169-
{
170-
break;
183+
/* Empty when MBEDTLS_ERR_SSL_WANT_READ || MBEDTLS_ERR_SSL_WANT_WRITE */
171184
}
172185
}
173-
174186
else
175187
{
176188
/* Empty when lSelectResult == 0 */
177189
}
178190
}
179-
while( xTaskCheckForTimeOut( &xTimeout, &xTicksToWait ) == pdFALSE );
191+
while( ( xTaskCheckForTimeOut( &xTimeout, &xTicksToWait ) == pdFALSE ) &&
192+
( lBytesSent < uxDataLen ) &&
193+
( lBytesSent >= 0 ) );
180194
}
181195
xSemaphoreGive(pxNetworkContext->xTlsContextSemaphore);
182196
}
@@ -186,38 +200,74 @@ int32_t espTlsTransportSend( NetworkContext_t* pxNetworkContext,
186200
}
187201

188202
int32_t espTlsTransportRecv( NetworkContext_t* pxNetworkContext,
189-
void* pvData, size_t uxDataLen)
203+
void* pvData, size_t uxDataLen )
190204
{
191-
int32_t lBytesRead = -1;
205+
int32_t lBytesRead = 0;
192206

193207
if( ( pvData != NULL ) &&
194208
( uxDataLen > 0 ) &&
195209
( pxNetworkContext != NULL ) &&
196210
( pxNetworkContext->pxTls != NULL ) )
197211
{
198-
if( xSemaphoreTake( pxNetworkContext->xTlsContextSemaphore, portMAX_DELAY ) == pdTRUE )
212+
TimeOut_t xTimeout;
213+
vTaskSetTimeOutState( &xTimeout );
214+
215+
TickType_t xTicksToWait = pdMS_TO_TICKS( timeouts.recvTimeoutMs );
216+
struct timeval timeout = {.tv_usec = timeouts.recvTimeoutMs * 1000, .tv_sec = 0};
217+
TickType_t start_tick = xTaskGetTickCount();
218+
219+
if( xSemaphoreTake( pxNetworkContext->xTlsContextSemaphore, xTicksToWait ) == pdTRUE )
199220
{
200-
ssize_t lResult = esp_tls_conn_read( pxNetworkContext->pxTls,
201-
pvData,
202-
( size_t ) uxDataLen );
221+
int lSockFd = -1;
222+
fd_set read_fds;
223+
fd_set error_fds;
203224

204-
if( lResult > 0 )
205-
{
206-
lBytesRead = ( int32_t ) lResult;
207-
}
208-
else if( ( lResult != MBEDTLS_ERR_SSL_WANT_WRITE ) &&
209-
( lResult != MBEDTLS_ERR_SSL_WANT_READ ) )
210-
{
211-
lBytesRead = ( int32_t ) lResult;
212-
}
213-
else
225+
esp_tls_get_conn_sockfd( pxNetworkContext->pxTls, &lSockFd );
226+
FD_ZERO( &read_fds );
227+
FD_SET( lSockFd, &read_fds );
228+
FD_ZERO( &error_fds );
229+
FD_SET( lSockFd, &error_fds );
230+
231+
do
214232
{
215-
lBytesRead = 0;
233+
// Fetch any buffered data
234+
ssize_t lResult = esp_tls_conn_read( pxNetworkContext->pxTls,
235+
pvData,
236+
( size_t ) uxDataLen );
237+
238+
if( lResult > 0 )
239+
{
240+
lBytesRead = ( int32_t ) lResult;
241+
}
242+
else if( ( lResult == MBEDTLS_ERR_SSL_WANT_WRITE ) ||
243+
( lResult == MBEDTLS_ERR_SSL_WANT_READ ) )
244+
{
245+
suseconds_t elapsed_time_usec = ( xTaskGetTickCount() - start_tick ) * portTICK_PERIOD_MS * 1000;
246+
timeout.tv_usec = ( timeout.tv_usec - elapsed_time_usec >= 0 ) ? timeout.tv_usec - elapsed_time_usec : 0;
247+
248+
int lSelectResult = select( lSockFd + 1, &read_fds, NULL, &error_fds, &timeout );
249+
if ( ( lSelectResult < 0 ) || FD_ISSET( lSockFd, &error_fds ) ) {
250+
ESP_LOGE( TAG, "Error reading the message" );
251+
lBytesRead = lResult = -1;
252+
}
253+
}
254+
else if( lResult == 0 )
255+
{
256+
ESP_LOGE( TAG, "Connection closed" );
257+
lBytesRead = -1;
258+
}
259+
else
260+
{
261+
ESP_LOGE( TAG, "Error reading: %d", ( int ) lResult );
262+
lBytesRead = ( int32_t ) lResult;
263+
}
216264
}
265+
while ( ( xTaskCheckForTimeOut( &xTimeout, &xTicksToWait ) == pdFALSE ) &&
266+
( lBytesRead == 0 ) );
217267

218-
( void ) xSemaphoreGive( pxNetworkContext->xTlsContextSemaphore);
268+
269+
( void ) xSemaphoreGive( pxNetworkContext->xTlsContextSemaphore );
219270
}
220271
}
221-
222272
return lBytesRead;
223273
}

libraries/coreMQTT/port/network_transport/network_transport.h

+24-1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,23 @@ struct NetworkContext
5757
BaseType_t disableSni;
5858
};
5959

60+
/**
61+
* @brief Structure to configure timeouts for individual TLS operations in milliseconds resolution.
62+
* Note that it uses FreeRTOS software timer internally and hence minimum resolution is the tick duration.
63+
* These timeouts can be specified before any receive or send operation. Timout of 0 will act as a non-blocking mode.
64+
*
65+
* Defaults are:
66+
* Connection timeout - 4 seconds
67+
* Send timeout - 10 seconds
68+
* Receive timeout - 2 seconds
69+
*/
70+
typedef struct Timeouts
71+
{
72+
uint16_t connectionTimeoutMs;
73+
uint16_t sendTimeoutMs;
74+
uint16_t recvTimeoutMs;
75+
} Timeouts_t;
76+
6077
TlsTransportStatus_t xTlsConnect(NetworkContext_t* pxNetworkContext );
6178

6279
TlsTransportStatus_t xTlsDisconnect( NetworkContext_t* pxNetworkContext );
@@ -67,10 +84,16 @@ int32_t espTlsTransportSend( NetworkContext_t* pxNetworkContext,
6784
int32_t espTlsTransportRecv( NetworkContext_t* pxNetworkContext,
6885
void* pvData, size_t uxDataLen );
6986

87+
void vTlsSetConnectTimeout( uint16_t connectionTimeoutMs );
88+
89+
void vTlsSetSendTimeout( uint16_t sendTimeoutMs );
90+
91+
void vTlsSetRecvTimeout( uint16_t recvTimeoutMs );
92+
7093
/* *INDENT-OFF* */
7194
#ifdef __cplusplus
7295
}
7396
#endif
7497
/* *INDENT-ON* */
7598

76-
#endif /* ESP_TLS_TRANSPORT_H */
99+
#endif /* ESP_TLS_TRANSPORT_H */

0 commit comments

Comments
 (0)