tcp_transport: Implement connect timeout
Merges
Closes
@@ -81,15 +81,61 @@ static int tcp_connect(esp_transport_handle_t t, const char *host, int port, int
setsockopt(tcp->sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
setsockopt(tcp->sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
- ESP_LOGD(TAG, "[sock=%d],connecting to server IP:%s,Port:%d...",
+ // Set socket to non-blocking
+ int flags;
+ if ((flags = fcntl(tcp->sock, F_GETFL, NULL)) < 0 || fcntl(tcp->sock, F_SETFL, flags |= O_NONBLOCK) < 0) {
+ ESP_LOGE(TAG, "[sock=%d] set nonblocking error: %s", tcp->sock, strerror(errno));
+ goto error;
+ }
+
+ ESP_LOGD(TAG, "[sock=%d] Connecting to server. IP: %s, Port: %d",
tcp->sock, ipaddr_ntoa((const ip_addr_t*)&remote_ip.sin_addr.s_addr), port);
- if (connect(tcp->sock, (struct sockaddr *)(&remote_ip), sizeof(struct sockaddr)) != 0) {
+
+ if (connect(tcp->sock, (struct sockaddr *)(&remote_ip), sizeof(struct sockaddr)) < 0) {
+ if (errno == EINPROGRESS) {
+ fd_set fdset;
+
+ esp_transport_utils_ms_to_timeval(timeout_ms, &tv);
+ FD_ZERO(&fdset);
+ FD_SET(tcp->sock, &fdset);
+
+ int res = select(tcp->sock+1, NULL, &fdset, NULL, &tv);
+ if (res < 0) {
+ ESP_LOGE(TAG, "[sock=%d] select() error: %s", tcp->sock, strerror(errno));
+ goto error;
+ }
+ else if (res == 0) {
+ ESP_LOGE(TAG, "[sock=%d] select() timeout", tcp->sock);
+ goto error;
+ } else {
+ int sockerr;
+ socklen_t len = (socklen_t)sizeof(int);
+
+ if (getsockopt(tcp->sock, SOL_SOCKET, SO_ERROR, (void*)(&sockerr), &len) < 0) {
+ ESP_LOGE(TAG, "[sock=%d] getsockopt() error: %s", tcp->sock, strerror(errno));
+ goto error;
+ }
+ else if (sockerr) {
+ ESP_LOGE(TAG, "[sock=%d] delayed connect error: %s", tcp->sock, strerror(sockerr));
+ goto error;
+ }
+ }
+ } else {
+ ESP_LOGE(TAG, "[sock=%d] connect() error: %s", tcp->sock, strerror(errno));
+ goto error;
+ }
+ }
+ // Reset socket to blocking
+ if ((flags = fcntl(tcp->sock, F_GETFL, NULL)) < 0 || fcntl(tcp->sock, F_SETFL, flags & ~O_NONBLOCK) < 0) {
+ ESP_LOGE(TAG, "[sock=%d] reset blocking error: %s", tcp->sock, strerror(errno));
+ goto error;
+ }
+ return tcp->sock;
+error:
close(tcp->sock);
tcp->sock = -1;
return -1;
}
- return tcp->sock;
-}
static int tcp_write(esp_transport_handle_t t, const char *buffer, int len, int timeout_ms)
{
