diff --git a/lib/client-handshake.c b/lib/client-handshake.c index acce53a443649a0bca5b0b3beb70b2add2bddb65..5c0d356b9cf315b5604e3fdbb772965d21732394 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 85816951d86b86987e312a9a6bd6da5ee2bb6921..8e91c906116ec3a65f849ffdfbc5acf3257bd3ac 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 0551ad6597ddcc26f628e7d6272cd17e3ffc9766..248c2a6427e01fea815057ee1b0f4d60ebf465b8 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 cb5d2992237320576693e38a51a32da2cf984323..500f327be24e7818d7ead72975b5ba94c75c27f0 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 183f7810ac4d99a58f11332b6d0ef0b9524f3cc8..74569136ab0907290e94a290f5fd6c04615f5aec 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);