From 449eec9b54b4c929926e395b305d0b1c5296d86f Mon Sep 17 00:00:00 2001
From: Andy Green <andy@warmcat.com>
Date: Wed, 14 Jun 2017 09:45:30 +0800
Subject: [PATCH] client: add iface in connection info, dont use vhost iface

---
 lib/client-handshake.c      | 34 ++++++++++++++++++++++++++++------
 lib/libwebsockets.h         |  4 ++++
 lib/private-libwebsockets.h |  1 +
 3 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/lib/client-handshake.c b/lib/client-handshake.c
index e335cc71..dc6de916 100644
--- a/lib/client-handshake.c
+++ b/lib/client-handshake.c
@@ -12,7 +12,7 @@ lws_client_connect_2(struct lws *wsi)
 	struct sockaddr_in server_addr4;
 	struct lws_pollfd pfd;
 	struct sockaddr *v;
-	const char *cce = "";
+	const char *cce = "", *iface;
 	int n, plen = 0;
 	const char *ads;
 
@@ -240,10 +240,14 @@ lws_client_connect_2(struct lws *wsi)
 		lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE,
 				AWAITING_TIMEOUT);
 
-		n = lws_socket_bind(wsi->vhost, wsi->desc.sockfd, 0, wsi->vhost->iface);
-		if (n < 0) {
-			cce = "unable to bind socket";
-			goto failed;
+		iface = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_IFACE);
+
+		if (iface) {
+			n = lws_socket_bind(wsi->vhost, wsi->desc.sockfd, 0, iface);
+			if (n < 0) {
+				cce = "unable to bind socket";
+				goto failed;
+			}
 		}
 	}
 
@@ -420,7 +424,7 @@ LWS_VISIBLE struct lws *
 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;
+	char origin[300] = "", protocol[300] = "", method[32] = "", iface[16] = "", *p;
 	struct lws *wsi = *pwsi;
 
 	if (wsi->redirects == 3) {
@@ -450,6 +454,10 @@ lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port,
 	if (p)
 		strncpy(method, p, sizeof(method) - 1);
 
+	p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_IFACE);
+	if (p)
+		strncpy(method, p, sizeof(iface) - 1);
+
 	lwsl_debug("redirect ads='%s', port=%d, path='%s', ssl = %d\n",
 		   address, port, path, ssl);
 
@@ -485,6 +493,11 @@ lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port,
 					  method))
 			return NULL;
 
+	if (iface[0])
+		if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_IFACE,
+					  iface))
+			return NULL;
+
 	origin[0] = '/';
 	strncpy(&origin[1], path, sizeof(origin) - 2);
 	if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, origin))
@@ -691,6 +704,7 @@ lws_client_connect_via_info(struct lws_client_connect_info *i)
 	wsi->u.hdr.stash->origin[0] = '\0';
 	wsi->u.hdr.stash->protocol[0] = '\0';
 	wsi->u.hdr.stash->method[0] = '\0';
+	wsi->u.hdr.stash->iface[0] = '\0';
 
 	strncpy(wsi->u.hdr.stash->address, i->address,
 		sizeof(wsi->u.hdr.stash->address) - 1);
@@ -707,6 +721,9 @@ lws_client_connect_via_info(struct lws_client_connect_info *i)
 	if (i->method)
 		strncpy(wsi->u.hdr.stash->method, i->method,
 			sizeof(wsi->u.hdr.stash->method) - 1);
+	if (i->iface)
+		strncpy(wsi->u.hdr.stash->iface, i->iface,
+			sizeof(wsi->u.hdr.stash->iface) - 1);
 
 	wsi->u.hdr.stash->address[sizeof(wsi->u.hdr.stash->address) - 1] = '\0';
 	wsi->u.hdr.stash->path[sizeof(wsi->u.hdr.stash->path) - 1] = '\0';
@@ -714,6 +731,7 @@ lws_client_connect_via_info(struct lws_client_connect_info *i)
 	wsi->u.hdr.stash->origin[sizeof(wsi->u.hdr.stash->origin) - 1] = '\0';
 	wsi->u.hdr.stash->protocol[sizeof(wsi->u.hdr.stash->protocol) - 1] = '\0';
 	wsi->u.hdr.stash->method[sizeof(wsi->u.hdr.stash->method) - 1] = '\0';
+	wsi->u.hdr.stash->iface[sizeof(wsi->u.hdr.stash->iface) - 1] = '\0';
 
 	if (i->pwsi)
 		*i->pwsi = wsi;
@@ -796,6 +814,10 @@ lws_client_connect_via_info2(struct lws *wsi)
 		if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_METHOD,
 					  stash->method))
 			goto bail1;
+	if (stash->iface[0])
+		if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_IFACE,
+					  stash->iface))
+			goto bail1;
 
 #if defined(LWS_WITH_SOCKS5)
 	if (!wsi->vhost->socks_proxy_port)
diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h
index 690a7f22..2db2fc68 100644
--- a/lib/libwebsockets.h
+++ b/lib/libwebsockets.h
@@ -2423,6 +2423,9 @@ struct lws_client_connect_info {
 	 * even before the new wsi is returned and even if ultimately no wsi
 	 * is returned.
 	 */
+	const char *iface;
+	/**< NULL to allow routing on any interface, or interface name or IP
+	 * to bind the socket to */
 
 	/* Add new things just above here ---^
 	 * This is part of the ABI, don't needlessly break compatibility
@@ -3020,6 +3023,7 @@ enum lws_token_indexes {
 	_WSI_TOKEN_CLIENT_HOST,
 	_WSI_TOKEN_CLIENT_ORIGIN,
 	_WSI_TOKEN_CLIENT_METHOD,
+	_WSI_TOKEN_CLIENT_IFACE,
 
 	/* always last real token index*/
 	WSI_TOKEN_COUNT,
diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h
index be5a4c56..845d4a5f 100644
--- a/lib/private-libwebsockets.h
+++ b/lib/private-libwebsockets.h
@@ -1192,6 +1192,7 @@ struct client_info_stash {
 	char origin[256];
 	char protocol[256];
 	char method[16];
+	char iface[16];
 };
 #endif
 
-- 
GitLab