diff --git a/lib/client-handshake.c b/lib/client-handshake.c index acce53a4..5c0d356b 100644 --- a/lib/client-handshake.c +++ b/lib/client-handshake.c @@ -207,7 +207,11 @@ lws_client_connect_2(struct lws *wsi) || LWS_ERRNO == WSAEINVAL #endif ) { - lwsl_client("nonblocking connect retry\n"); + lwsl_client("nonblocking connect retry (errno = %d)\n", + LWS_ERRNO); + + if (lws_plat_check_connection_error(wsi)) + goto failed; /* * must do specifically a POLLOUT poll to hear diff --git a/lib/lws-plat-mbed3.cpp b/lib/lws-plat-mbed3.cpp index 85816951..8e91c906 100644 --- a/lib/lws-plat-mbed3.cpp +++ b/lib/lws-plat-mbed3.cpp @@ -81,6 +81,12 @@ lws_plat_change_pollfd(struct lws_context *context, return 0; } +extern "C" LWS_VISIBLE int +lws_plat_check_connection_error(struct lws *wsi) +{ + return 0; +} + extern "C" LWS_VISIBLE int lws_ssl_capable_read_no_ssl(struct lws *wsi, unsigned char *buf, int len) { diff --git a/lib/lws-plat-unix.c b/lib/lws-plat-unix.c index 0551ad65..248c2a64 100644 --- a/lib/lws-plat-unix.c +++ b/lib/lws-plat-unix.c @@ -180,6 +180,12 @@ faked_service: return 0; } +LWS_VISIBLE int +lws_plat_check_connection_error(struct lws *wsi) +{ + return 0; +} + LWS_VISIBLE int lws_plat_service(struct lws_context *context, int timeout_ms) { diff --git a/lib/lws-plat-win.c b/lib/lws-plat-win.c index cb5d2992..500f327b 100644 --- a/lib/lws-plat-win.c +++ b/lib/lws-plat-win.c @@ -285,7 +285,17 @@ lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) return -1; } - pfd->revents = (short)networkevents.lNetworkEvents; + if ((networkevents.lNetworkEvents & FD_CONNECT) && + networkevents.iErrorCode[FD_CONNECT_BIT] && + networkevents.iErrorCode[FD_CONNECT_BIT] != LWS_EALREADY && + networkevents.iErrorCode[FD_CONNECT_BIT] != LWS_EINPROGRESS && + networkevents.iErrorCode[FD_CONNECT_BIT] != LWS_EWOULDBLOCK && + networkevents.iErrorCode[FD_CONNECT_BIT] != WSAEINVAL) { + lwsl_debug("Unable to connect errno=%d\n", + networkevents.iErrorCode[FD_CONNECT_BIT]); + pfd->revents = LWS_POLLHUP; + } else + pfd->revents = (short)networkevents.lNetworkEvents; if (pfd->revents & LWS_POLLOUT) { wsi = wsi_from_fd(context, pfd->fd); @@ -460,7 +470,7 @@ lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi) pt->fds[pt->fds_count++].revents = 0; pt->events[pt->fds_count] = WSACreateEvent(); WSAEventSelect(wsi->sock, pt->events[pt->fds_count], - LWS_POLLIN | LWS_POLLHUP); + LWS_POLLIN | LWS_POLLHUP | FD_CONNECT); } LWS_VISIBLE void @@ -478,12 +488,29 @@ lws_plat_service_periodic(struct lws_context *context) { } +LWS_VISIBLE int +lws_plat_check_connection_error(struct lws *wsi) +{ + int optVal; + int optLen = sizeof(int); + + if (getsockopt(wsi->sock, SOL_SOCKET, SO_ERROR, + (char*)&optVal, &optLen) != SOCKET_ERROR && optVal && + optVal != LWS_EALREADY && optVal != LWS_EINPROGRESS && + optVal != LWS_EWOULDBLOCK && optVal != WSAEINVAL) { + lwsl_debug("Connect failed SO_ERROR=%d\n", optVal); + return 1; + } + + return 0; +} + LWS_VISIBLE int lws_plat_change_pollfd(struct lws_context *context, struct lws *wsi, struct lws_pollfd *pfd) { struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; - long networkevents = LWS_POLLHUP; + long networkevents = LWS_POLLHUP | FD_CONNECT; if ((pfd->events & LWS_POLLIN)) networkevents |= LWS_POLLIN; diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 183f7810..74569136 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -1494,6 +1494,9 @@ void lws_http2_configure_if_upgraded(struct lws *wsi); LWS_EXTERN int lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd); +LWS_EXTERN int +lws_plat_check_connection_error(struct lws *wsi); + LWS_EXTERN int LWS_WARN_UNUSED_RESULT lws_header_table_attach(struct lws *wsi, int autoservice);