trac 40 client connection properly nonblocking
As spotted by JM on Trac#40
http://libwebsockets.org/trac/libwebsockets/ticket/40
client connect didn't do anything about being truly nonblocking. This patch
should hopefully solve that.
Signed-off-by: Andy Green <andy.green@linaro.org>
diff --git a/lib/client-handshake.c b/lib/client-handshake.c
index 2dd810c..a501565 100644
--- a/lib/client-handshake.c
+++ b/lib/client-handshake.c
@@ -52,11 +52,28 @@
goto oom4;
}
- wsi->sock = socket(AF_INET, SOCK_STREAM, 0);
-
if (wsi->sock < 0) {
- lwsl_warn("Unable to open socket\n");
- goto oom4;
+
+ wsi->sock = socket(AF_INET, SOCK_STREAM, 0);
+
+ if (wsi->sock < 0) {
+ lwsl_warn("Unable to open socket\n");
+ goto oom4;
+ }
+
+ if (lws_set_socket_options(context, wsi->sock)) {
+ lwsl_err("Failed to set wsi socket options\n");
+ compatible_close(wsi->sock);
+ goto oom4;
+ }
+
+ wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT;
+
+ insert_wsi_socket_into_fds(context, wsi);
+
+ libwebsocket_set_timeout(wsi,
+ PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE,
+ AWAITING_TIMEOUT);
}
server_addr.sin_family = AF_INET;
@@ -66,30 +83,39 @@
if (connect(wsi->sock, (struct sockaddr *)&server_addr,
sizeof(struct sockaddr)) == -1) {
- lwsl_debug("Connect failed\n");
- compatible_close(wsi->sock);
- goto oom4;
+
+ if (errno == EALREADY || errno == EINPROGRESS) {
+ lwsl_client("nonblocking connect retry\n");
+
+ /*
+ * must do specifically a POLLOUT poll to hear
+ * about the connect completion
+ */
+
+ context->fds[wsi->position_in_fds_table].events |= POLLOUT;
+
+ /* external POLL support via protocol 0 */
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_SET_MODE_POLL_FD,
+ wsi->user_space, (void *)(long)wsi->sock, POLLOUT);
+
+ return wsi;
+ }
+
+ lwsl_debug("Connect failed errno=%d\n", errno);
+ goto failed;
}
lwsl_client("connected\n");
- if (lws_set_socket_options(context, wsi->sock)) {
- lwsl_err("Failed to set wsi socket options\n");
- compatible_close(wsi->sock);
- goto oom4;
- }
-
- insert_wsi_socket_into_fds(context, wsi);
-
/* we are connected to server, or proxy */
if (context->http_proxy_port) {
n = send(wsi->sock, context->service_buffer, plen, MSG_NOSIGNAL);
if (n < 0) {
- compatible_close(wsi->sock);
lwsl_debug("ERROR writing to proxy socket\n");
- goto oom4;
+ goto failed;
}
libwebsocket_set_timeout(wsi,
@@ -121,7 +147,7 @@
n = libwebsocket_service_fd(context, &pfd);
if (n < 0)
- goto oom4;
+ goto failed;
if (n) /* returns 1 on failure after closing wsi */
return NULL;
@@ -131,7 +157,11 @@
oom4:
free(wsi->u.hdr.ah);
free(wsi);
+ return NULL;
+failed:
+ libwebsocket_close_and_free_session(context, wsi,
+ LWS_CLOSE_STATUS_NOSTATUS);
return NULL;
}
@@ -185,6 +215,7 @@
goto bail;
memset(wsi, 0, sizeof(*wsi));
+ wsi->sock = -1;
/* -1 means just use latest supported */