Skip to content

Commit

Permalink
roll back commit "trac 40 client connection properly nonblocking", th…
Browse files Browse the repository at this point in the history
…is commit can't connect to golang websocket server.
  • Loading branch information
u0u0 committed Sep 22, 2013
1 parent 18cfbcc commit cbe79de
Show file tree
Hide file tree
Showing 9 changed files with 49 additions and 146 deletions.
20 changes: 0 additions & 20 deletions README.coding
Original file line number Diff line number Diff line change
Expand Up @@ -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.

4 changes: 0 additions & 4 deletions changelog
Original file line number Diff line number Diff line change
Expand Up @@ -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
----------------
Expand Down
65 changes: 17 additions & 48 deletions lib/client-handshake.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -83,39 +66,30 @@ 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 */

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 failed;
goto oom4;
}

libwebsocket_set_timeout(wsi,
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}

Expand Down Expand Up @@ -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 */

Expand Down
16 changes: 0 additions & 16 deletions lib/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
17 changes: 3 additions & 14 deletions lib/libwebsockets.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down
1 change: 0 additions & 1 deletion lib/libwebsockets.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 0 additions & 1 deletion lib/private-libwebsockets.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
61 changes: 24 additions & 37 deletions test-server/test-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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:
Expand Down
10 changes: 5 additions & 5 deletions test-server/test-ping.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit cbe79de

Please sign in to comment.