Merge branch 'bugfix/ws_client_fix_wait_forever_timeout' into 'master'

ws_client: fix handling timeouts by websocket client.

Closes IDFGH-2161

See merge request espressif/esp-idf!6683
This commit is contained in:
Angus Gratton 2019-11-20 07:44:25 +08:00
commit 412b202741
8 changed files with 38 additions and 31 deletions

View file

@ -606,14 +606,14 @@ static int esp_websocket_client_send_with_opcode(esp_websocket_client_handle_t c
goto unlock_and_return;
}
while (widx < len) {
if (need_write > client->buffer_size) {
need_write = client->buffer_size;
}
memcpy(client->tx_buffer, data + widx, need_write);
// send with ws specific way and specific opcode
wlen = esp_transport_ws_send_raw(client->transport, opcode, (char *)client->tx_buffer, need_write, timeout);
wlen = esp_transport_ws_send_raw(client->transport, opcode, (char *)client->tx_buffer, need_write,
(timeout==portMAX_DELAY)? -1 : timeout * portTICK_PERIOD_MS);
if (wlen <= 0) {
ret = wlen;
ESP_LOGE(TAG, "Network error: esp_transport_write() returned %d, errno=%d", ret, errno);

View file

@ -155,7 +155,7 @@ esp_err_t esp_websocket_client_destroy(esp_websocket_client_handle_t client);
* @param[in] client The client
* @param[in] data The data
* @param[in] len The length
* @param[in] timeout Write data timeout
* @param[in] timeout Write data timeout in RTOS ticks
*
* @return
* - Number of data was sent
@ -169,7 +169,7 @@ int esp_websocket_client_send(esp_websocket_client_handle_t client, const char *
* @param[in] client The client
* @param[in] data The data
* @param[in] len The length
* @param[in] timeout Write data timeout
* @param[in] timeout Write data timeout in RTOS ticks
*
* @return
* - Number of data was sent
@ -183,7 +183,7 @@ int esp_websocket_client_send_bin(esp_websocket_client_handle_t client, const ch
* @param[in] client The client
* @param[in] data The data
* @param[in] len The length
* @param[in] timeout Write data timeout
* @param[in] timeout Write data timeout in RTOS ticks
*
* @return
* - Number of data was sent

View file

@ -133,7 +133,7 @@ esp_err_t esp_transport_set_default_port(esp_transport_handle_t t, int port);
* @param t The transport handle
* @param[in] host Hostname
* @param[in] port Port
* @param[in] timeout_ms The timeout milliseconds
* @param[in] timeout_ms The timeout milliseconds (-1 indicates wait forever)
*
* @return
* - socket for will use by this transport
@ -147,7 +147,7 @@ int esp_transport_connect(esp_transport_handle_t t, const char *host, int port,
* @param t The transport handle
* @param[in] host Hostname
* @param[in] port Port
* @param[in] timeout_ms The timeout milliseconds
* @param[in] timeout_ms The timeout milliseconds (-1 indicates wait forever)
*
* @return
* - socket for will use by this transport
@ -161,7 +161,7 @@ int esp_transport_connect_async(esp_transport_handle_t t, const char *host, int
* @param t The transport handle
* @param buffer The buffer
* @param[in] len The length
* @param[in] timeout_ms The timeout milliseconds
* @param[in] timeout_ms The timeout milliseconds (-1 indicates wait forever)
*
* @return
* - Number of bytes was read
@ -173,7 +173,7 @@ int esp_transport_read(esp_transport_handle_t t, char *buffer, int len, int time
* @brief Poll the transport until readable or timeout
*
* @param[in] t The transport handle
* @param[in] timeout_ms The timeout milliseconds
* @param[in] timeout_ms The timeout milliseconds (-1 indicates wait forever)
*
* @return
* - 0 Timeout
@ -188,7 +188,7 @@ int esp_transport_poll_read(esp_transport_handle_t t, int timeout_ms);
* @param t The transport handle
* @param buffer The buffer
* @param[in] len The length
* @param[in] timeout_ms The timeout milliseconds
* @param[in] timeout_ms The timeout milliseconds (-1 indicates wait forever)
*
* @return
* - Number of bytes was written
@ -200,7 +200,7 @@ int esp_transport_write(esp_transport_handle_t t, const char *buffer, int len, i
* @brief Poll the transport until writeable or timeout
*
* @param[in] t The transport handle
* @param[in] timeout_ms The timeout milliseconds
* @param[in] timeout_ms The timeout milliseconds (-1 indicates wait forever)
*
* @return
* - 0 Timeout

View file

@ -63,7 +63,7 @@ esp_err_t esp_transport_ws_set_subprotocol(esp_transport_handle_t t, const char
* @param[in] opcode ws operation code
* @param[in] buffer The buffer
* @param[in] len The length
* @param[in] timeout_ms The timeout milliseconds
* @param[in] timeout_ms The timeout milliseconds (-1 indicates block forever)
*
* @return
* - Number of bytes was written

View file

@ -30,12 +30,17 @@ extern "C" {
}
/**
* @brief Convert milliseconds to timeval struct
* @brief Convert milliseconds to timeval struct for valid timeouts, otherwise
* (if "wait forever" requested by timeout_ms=-1) timeval structure is not updated and NULL returned
*
* @param[in] timeout_ms The timeout milliseconds
* @param[out] tv Timeval struct
* @param[in] timeout_ms The timeout value in milliseconds or -1 to waiting forever
* @param[out] tv Pointer to timeval struct
*
* @return
* - NULL if timeout_ms=-1 (wait forever)
* - pointer to the updated timeval structure (provided as "tv" argument) with recalculated timeout value
*/
void esp_transport_utils_ms_to_timeval(int timeout_ms, struct timeval *tv);
struct timeval* esp_transport_utils_ms_to_timeval(int timeout_ms, struct timeval *tv);
#ifdef __cplusplus

View file

@ -86,16 +86,15 @@ static int ssl_poll_read(esp_transport_handle_t t, int timeout_ms)
{
transport_ssl_t *ssl = esp_transport_get_context_data(t);
int ret = -1;
struct timeval timeout;
fd_set readset;
fd_set errset;
FD_ZERO(&readset);
FD_ZERO(&errset);
FD_SET(ssl->tls->sockfd, &readset);
FD_SET(ssl->tls->sockfd, &errset);
struct timeval timeout;
esp_transport_utils_ms_to_timeval(timeout_ms, &timeout);
ret = select(ssl->tls->sockfd + 1, &readset, NULL, &errset, &timeout);
ret = select(ssl->tls->sockfd + 1, &readset, NULL, &errset, esp_transport_utils_ms_to_timeval(timeout_ms, &timeout));
if (ret > 0 && FD_ISSET(ssl->tls->sockfd, &errset)) {
int sock_errno = 0;
uint32_t optlen = sizeof(sock_errno);
@ -110,15 +109,14 @@ static int ssl_poll_write(esp_transport_handle_t t, int timeout_ms)
{
transport_ssl_t *ssl = esp_transport_get_context_data(t);
int ret = -1;
struct timeval timeout;
fd_set writeset;
fd_set errset;
FD_ZERO(&writeset);
FD_ZERO(&errset);
FD_SET(ssl->tls->sockfd, &writeset);
FD_SET(ssl->tls->sockfd, &errset);
struct timeval timeout;
esp_transport_utils_ms_to_timeval(timeout_ms, &timeout);
ret = select(ssl->tls->sockfd + 1, NULL, &writeset, &errset, &timeout);
ret = select(ssl->tls->sockfd + 1, NULL, &writeset, &errset, esp_transport_utils_ms_to_timeval(timeout_ms, &timeout));
if (ret > 0 && FD_ISSET(ssl->tls->sockfd, &errset)) {
int sock_errno = 0;
uint32_t optlen = sizeof(sock_errno);

View file

@ -52,7 +52,7 @@ static int resolve_dns(const char *host, struct sockaddr_in *ip) {
static int tcp_connect(esp_transport_handle_t t, const char *host, int port, int timeout_ms)
{
struct sockaddr_in remote_ip;
struct timeval tv;
struct timeval tv = { 0 };
transport_tcp_t *tcp = esp_transport_get_context_data(t);
bzero(&remote_ip, sizeof(struct sockaddr_in));
@ -74,7 +74,7 @@ static int tcp_connect(esp_transport_handle_t t, const char *host, int port, int
remote_ip.sin_family = AF_INET;
remote_ip.sin_port = htons(port);
esp_transport_utils_ms_to_timeval(timeout_ms, &tv);
esp_transport_utils_ms_to_timeval(timeout_ms, &tv); // if timeout=-1, tv is unchanged, 0, i.e. waits forever
setsockopt(tcp->sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
setsockopt(tcp->sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
@ -117,15 +117,15 @@ static int tcp_poll_read(esp_transport_handle_t t, int timeout_ms)
{
transport_tcp_t *tcp = esp_transport_get_context_data(t);
int ret = -1;
struct timeval timeout;
fd_set readset;
fd_set errset;
FD_ZERO(&readset);
FD_ZERO(&errset);
FD_SET(tcp->sock, &readset);
FD_SET(tcp->sock, &errset);
struct timeval timeout;
esp_transport_utils_ms_to_timeval(timeout_ms, &timeout);
ret = select(tcp->sock + 1, &readset, NULL, &errset, &timeout);
ret = select(tcp->sock + 1, &readset, NULL, &errset, esp_transport_utils_ms_to_timeval(timeout_ms, &timeout));
if (ret > 0 && FD_ISSET(tcp->sock, &errset)) {
int sock_errno = 0;
uint32_t optlen = sizeof(sock_errno);
@ -140,15 +140,15 @@ static int tcp_poll_write(esp_transport_handle_t t, int timeout_ms)
{
transport_tcp_t *tcp = esp_transport_get_context_data(t);
int ret = -1;
struct timeval timeout;
fd_set writeset;
fd_set errset;
FD_ZERO(&writeset);
FD_ZERO(&errset);
FD_SET(tcp->sock, &writeset);
FD_SET(tcp->sock, &errset);
struct timeval timeout;
esp_transport_utils_ms_to_timeval(timeout_ms, &timeout);
ret = select(tcp->sock + 1, NULL, &writeset, &errset, &timeout);
ret = select(tcp->sock + 1, NULL, &writeset, &errset, esp_transport_utils_ms_to_timeval(timeout_ms, &timeout));
if (ret > 0 && FD_ISSET(tcp->sock, &errset)) {
int sock_errno = 0;
uint32_t optlen = sizeof(sock_errno);

View file

@ -6,8 +6,12 @@
#include "esp_transport_utils.h"
void esp_transport_utils_ms_to_timeval(int timeout_ms, struct timeval *tv)
struct timeval* esp_transport_utils_ms_to_timeval(int timeout_ms, struct timeval *tv)
{
if (timeout_ms == -1) {
return NULL;
}
tv->tv_sec = timeout_ms / 1000;
tv->tv_usec = (timeout_ms - (tv->tv_sec * 1000)) * 1000;
return tv;
}