diff --git a/README.coding b/README.coding index a34211ec40..d26c21dbb3 100644 --- a/README.coding +++ b/README.coding @@ -231,23 +231,3 @@ is too computationally expensive. To use it, point it to a string like if left NULL, then the "DEFAULT" set of ciphers are all possible to select. - -Async nature of client connections ----------------------------------- - -When you call libwebsocket_client_connect(..) and get a wsi back, it does not -mean your connection is active. It just mean it started trying to connect. - -Your client connection is actually active only when you receive -LWS_CALLBACK_CLIENT_ESTABLISHED for it. - -There's a 5 second timeout for the connection, and it may give up or die for -other reasons, if any of that happens you'll get a -LWS_CALLBACK_CLIENT_CONNECTION_ERROR callback on protocol 0 instead for the -wsi. - -After attempting the connection and getting back a non-NULL wsi you should -loop calling libwebsocket_service() until one of the above callbacks occurs. - -As usual, see test-client.c for example code. - diff --git a/changelog b/changelog index 31cc570c7c..21ecb0560e 100644 --- a/changelog +++ b/changelog @@ -37,10 +37,6 @@ User api additions move the protocol name to the "in" parameter. The docs for this callback are also updated to reflect how to check headers in there. - - libwebsocket_client_connect() is now properly nonblocking and async. See - README.coding and test-client.c for information on the callbacks you - can rely on controlling the async connection period with. - User api changes ---------------- diff --git a/lib/client-handshake.c b/lib/client-handshake.c index a501565690..2dd810c561 100644 --- a/lib/client-handshake.c +++ b/lib/client-handshake.c @@ -52,28 +52,11 @@ struct libwebsocket *__libwebsocket_client_connect_2( goto oom4; } - if (wsi->sock < 0) { - - 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 (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); + if (wsi->sock < 0) { + lwsl_warn("Unable to open socket\n"); + goto oom4; } server_addr.sin_family = AF_INET; @@ -83,30 +66,20 @@ struct libwebsocket *__libwebsocket_client_connect_2( 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_client("connected\n"); - lwsl_debug("Connect failed errno=%d\n", errno); - goto failed; + if (lws_set_socket_options(context, wsi->sock)) { + lwsl_err("Failed to set wsi socket options\n"); + compatible_close(wsi->sock); + goto oom4; } - lwsl_client("connected\n"); + insert_wsi_socket_into_fds(context, wsi); /* we are connected to server, or proxy */ @@ -114,8 +87,9 @@ struct libwebsocket *__libwebsocket_client_connect_2( 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 failed; + goto oom4; } libwebsocket_set_timeout(wsi, @@ -147,7 +121,7 @@ struct libwebsocket *__libwebsocket_client_connect_2( n = libwebsocket_service_fd(context, &pfd); if (n < 0) - goto failed; + goto oom4; if (n) /* returns 1 on failure after closing wsi */ return NULL; @@ -157,11 +131,7 @@ struct libwebsocket *__libwebsocket_client_connect_2( oom4: free(wsi->u.hdr.ah); free(wsi); - return NULL; -failed: - libwebsocket_close_and_free_session(context, wsi, - LWS_CLOSE_STATUS_NOSTATUS); return NULL; } @@ -215,7 +185,6 @@ libwebsocket_client_connect(struct libwebsocket_context *context, goto bail; memset(wsi, 0, sizeof(*wsi)); - wsi->sock = -1; /* -1 means just use latest supported */ diff --git a/lib/client.c b/lib/client.c index 73809b0078..68b04824ef 100644 --- a/lib/client.c +++ b/lib/client.c @@ -45,22 +45,6 @@ int lws_client_socket_service(struct libwebsocket_context *context, switch (wsi->mode) { - case LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT: - - /* - * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE - * timeout protection set in client-handshake.c - */ - - if (__libwebsocket_client_connect_2(context, wsi) == NULL) { - /* closed */ - lwsl_client("closed\n"); - return -1; - } - - /* either still pending connection, or changed mode */ - return 0; - case LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY: /* handle proxy hung up on us */ diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index d4fa58cf7c..82cd99da02 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -206,17 +206,6 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *context, wsi->u.ws.close_reason = reason; - if (wsi->mode == LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT || - wsi->mode == LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE) { - - context->protocols[0].callback(context, wsi, - LWS_CALLBACK_CLIENT_CONNECTION_ERROR, NULL, NULL, 0); - - free(wsi->u.hdr.ah); - goto just_kill_connection; - } - - if (wsi->mode == LWS_CONNMODE_HTTP_SERVING_ACCEPTED && wsi->u.http.fd) { lwsl_debug("closing http fd %d\n", wsi->u.http.fd); close(wsi->u.http.fd); @@ -915,10 +904,12 @@ libwebsocket_service_fd(struct libwebsocket_context *context, return 0; /* just here for timeout management? */ + if (pollfd == NULL) return 0; /* no, here to service a socket descriptor */ + wsi = context->lws_lookup[pollfd->fd]; if (wsi == NULL) /* not lws connection ... leave revents alone and return */ @@ -1295,10 +1286,8 @@ libwebsocket_service(struct libwebsocket_context *context, int timeout_ms) /* wait for something to need service */ n = poll(context->fds, context->fds_count, timeout_ms); - if (n == 0) /* poll timeout */ { - libwebsocket_service_fd(context, NULL); + if (n == 0) /* poll timeout */ return 0; - } if (n < 0) return -1; diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 2d62107f60..b3cfa154f9 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -838,7 +838,6 @@ libwebsocket_context_user(struct libwebsocket_context *context); enum pending_timeout { NO_PENDING_TIMEOUT = 0, PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE, - PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE, PENDING_TIMEOUT_ESTABLISH_WITH_SERVER, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, PENDING_TIMEOUT_AWAITING_PING, diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 2e25e3454c..d7b6d0b813 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -221,7 +221,6 @@ enum connection_mode { LWS_CONNMODE_SSL_ACK_PENDING, /* transient modes */ - LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT, LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY, LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE, LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY, diff --git a/test-server/test-client.c b/test-server/test-client.c index 949d398815..7b32cb1f67 100644 --- a/test-server/test-client.c +++ b/test-server/test-client.c @@ -39,7 +39,6 @@ static int deny_mux; static struct libwebsocket *wsi_mirror; static int mirror_lifetime = 0; static int force_exit = 0; -static int longlived = 0; /* * This demo shows how to connect multiple websockets simultaneously to a @@ -74,15 +73,6 @@ callback_dumb_increment(struct libwebsocket_context *this, { switch (reason) { - case LWS_CALLBACK_CLIENT_ESTABLISHED: - fprintf(stderr, "callback_dumb_increment: LWS_CALLBACK_CLIENT_ESTABLISHED\n"); - break; - - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - fprintf(stderr, "LWS_CALLBACK_CLIENT_CONNECTION_ERROR\n"); - was_closed = 1; - break; - case LWS_CALLBACK_CLOSED: fprintf(stderr, "LWS_CALLBACK_CLOSED\n"); was_closed = 1; @@ -135,24 +125,12 @@ callback_lws_mirror(struct libwebsocket_context *context, switch (reason) { - case LWS_CALLBACK_CLIENT_ESTABLISHED: - - fprintf(stderr, "callback_lws_mirror: LWS_CALLBACK_CLIENT_ESTABLISHED\n"); - - mirror_lifetime = 10 + (random() & 1023); - /* useful to test single connection stability */ - if (longlived) - mirror_lifetime += 50000; - - fprintf(stderr, "opened mirror connection with " - "%d lifetime\n", mirror_lifetime); + case LWS_CALLBACK_CLOSED: + fprintf(stderr, "mirror: LWS_CALLBACK_CLOSED mirror_lifetime=%d\n", mirror_lifetime); + wsi_mirror = NULL; + break; - /* - * mirror_lifetime is decremented each send, when it reaches - * zero the connection is closed in the send callback. - * When the close callback comes, wsi_mirror is set to NULL - * so a new connection will be opened - */ + case LWS_CALLBACK_CLIENT_ESTABLISHED: /* * start the ball rolling, @@ -162,11 +140,6 @@ callback_lws_mirror(struct libwebsocket_context *context, libwebsocket_callback_on_writable(context, wsi); break; - case LWS_CALLBACK_CLOSED: - fprintf(stderr, "mirror: LWS_CALLBACK_CLOSED mirror_lifetime=%d\n", mirror_lifetime); - wsi_mirror = NULL; - break; - case LWS_CALLBACK_CLIENT_RECEIVE: /* fprintf(stderr, "rx %d '%s'\n", (int)len, (char *)in); */ break; @@ -254,6 +227,7 @@ int main(int argc, char **argv) const char *address; struct libwebsocket *wsi_dumb; int ietf_version = -1; /* latest */ + int longlived = 0; struct lws_context_creation_info info; memset(&info, 0, sizeof info); @@ -332,18 +306,16 @@ int main(int argc, char **argv) protocols[PROTOCOL_DUMB_INCREMENT].name, ietf_version); if (wsi_dumb == NULL) { - fprintf(stderr, "libwebsocket connect failed\n"); + fprintf(stderr, "libwebsocket dumb connect failed\n"); ret = 1; goto bail; } - fprintf(stderr, "Waiting for connect...\n"); + fprintf(stderr, "Websocket connections opened\n"); /* * sit there servicing the websocket context to handle incoming * packets, and drawing random circles on the mirror protocol websocket - * nothing happens until the client websocket connection is - * asynchronously established */ n = 0; @@ -365,10 +337,25 @@ int main(int argc, char **argv) if (wsi_mirror == NULL) { fprintf(stderr, "libwebsocket " - "mirror connect failed\n"); + "dumb connect failed\n"); ret = 1; goto bail; } + + mirror_lifetime = 10 + (random() & 1023); + /* useful to test single connection stability */ + if (longlived) + mirror_lifetime += 50000; + + fprintf(stderr, "opened mirror connection with " + "%d lifetime\n", mirror_lifetime); + + /* + * mirror_lifetime is decremented each send, when it reaches + * zero the connection is closed in the send callback. + * When the close callback comes, wsi_mirror is set to NULL + * so a new connection will be opened + */ } bail: diff --git a/test-server/test-ping.c b/test-server/test-ping.c index 155ac7dd30..098981cf7a 100644 --- a/test-server/test-ping.c +++ b/test-server/test-ping.c @@ -338,7 +338,7 @@ int main(int argc, char **argv) char ip[30]; #ifndef WIN32 struct sigaction sa; - // struct winsize w; + struct winsize w; #endif struct timeval tv; unsigned long oldus = 0; @@ -420,10 +420,10 @@ int main(int argc, char **argv) } #ifndef WIN32 - // if (isatty(STDOUT_FILENO)) - // if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) - // if (w.ws_col > 0) - // screen_width = w.ws_col; + if (isatty(STDOUT_FILENO)) + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) + if (w.ws_col > 0) + screen_width = w.ws_col; #endif info.port = CONTEXT_PORT_NO_LISTEN;