From 0db9b9f34624eca12a000e595afb18df42f8f1a4 Mon Sep 17 00:00:00 2001
From: Andy Green <andy@warmcat.com>
Date: Tue, 21 Feb 2017 22:59:00 +0800
Subject: [PATCH] client redirect: choose correct error path after resetting
 client connection

https://github.com/warmcat/libwebsockets/issues/810
---
 lib/client-handshake.c      |  7 +++++--
 lib/client.c                | 13 +++++++++++--
 lib/private-libwebsockets.h |  2 +-
 3 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/lib/client-handshake.c b/lib/client-handshake.c
index 4ccf73b4..a4ccc6c0 100644
--- a/lib/client-handshake.c
+++ b/lib/client-handshake.c
@@ -372,10 +372,11 @@ failed1:
  * host:	host header to send to the new server
  */
 LWS_VISIBLE struct lws *
-lws_client_reset(struct lws *wsi, int ssl, const char *address, int port,
+lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port,
 		 const char *path, const char *host)
 {
 	char origin[300] = "", protocol[300] = "", method[32] = "", *p;
+	struct lws *wsi = *pwsi;
 
 	if (wsi->u.hdr.redirects == 3) {
 		lwsl_err("%s: Too many redirects\n", __func__);
@@ -444,7 +445,9 @@ lws_client_reset(struct lws *wsi, int ssl, const char *address, int port,
 	if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, origin))
 		return NULL;
 
-	return lws_client_connect_2(wsi);
+	*pwsi = lws_client_connect_2(wsi);
+
+	return *pwsi;
 }
 
 #ifdef LWS_WITH_HTTP_PROXY
diff --git a/lib/client.c b/lib/client.c
index b5d8614a..fa162170 100755
--- a/lib/client.c
+++ b/lib/client.c
@@ -483,10 +483,19 @@ lws_client_interpret_server_handshake(struct lws *wsi)
 		if (!strcmp(prot, "wss") || !strcmp(prot, "https"))
 			ssl = 1;
 
-		if (!lws_client_reset(wsi, ssl, ads, port, path, ads)) {
+		if (!lws_client_reset(&wsi, ssl, ads, port, path, ads)) {
+			/* there are two ways to fail out with NULL return...
+			 * simple, early problem where the wsi is intact, or
+			 * we went through with the reconnect attempt and the
+			 * wsi is already closed.  In the latter case, the wsi
+			 * has beet set to NULL additionally.
+			 */
 			lwsl_err("Redirect failed\n");
 			cce = "HS: Redirect failed";
-			goto bail3;
+			if (wsi)
+				goto bail3;
+
+			return 1;
 		}
 		return 0;
 	}
diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h
index 21ffc3ab..a2abb2b6 100644
--- a/lib/private-libwebsockets.h
+++ b/lib/private-libwebsockets.h
@@ -1616,7 +1616,7 @@ LWS_EXTERN struct lws * LWS_WARN_UNUSED_RESULT
 lws_client_connect_2(struct lws *wsi);
 
 LWS_VISIBLE struct lws * LWS_WARN_UNUSED_RESULT
-lws_client_reset(struct lws *wsi, int ssl, const char *address, int port,
+lws_client_reset(struct lws **wsi, int ssl, const char *address, int port,
 		 const char *path, const char *host);
 
 LWS_EXTERN struct lws * LWS_WARN_UNUSED_RESULT
-- 
GitLab