diff --git a/include/libwebsockets/lws-client.h b/include/libwebsockets/lws-client.h index 232b883a6..a0c390d2a 100644 --- a/include/libwebsockets/lws-client.h +++ b/include/libwebsockets/lws-client.h @@ -165,6 +165,9 @@ struct lws_client_connect_info { const char *iface; /**< NULL to allow routing on any interface, or interface name or IP * to bind the socket to */ + int local_port; + /**< 0 to pick an ephemeral port, or a specific local port + * to bind the socket to */ const char *local_protocol_name; /**< NULL: .protocol is used both to select the local protocol handler * to bind to and as the list of remote ws protocols we could diff --git a/include/libwebsockets/lws-http.h b/include/libwebsockets/lws-http.h index 2c5bd64dc..ad80056a3 100644 --- a/include/libwebsockets/lws-http.h +++ b/include/libwebsockets/lws-http.h @@ -350,6 +350,7 @@ enum lws_token_indexes { _WSI_TOKEN_CLIENT_ORIGIN, _WSI_TOKEN_CLIENT_METHOD, _WSI_TOKEN_CLIENT_IFACE, + _WSI_TOKEN_CLIENT_LOCALPORT, _WSI_TOKEN_CLIENT_ALPN, /* always last real token index*/ diff --git a/lib/core-net/client/connect.c b/lib/core-net/client/connect.c index ac44f02dc..f5ac2dcec 100644 --- a/lib/core-net/client/connect.c +++ b/lib/core-net/client/connect.c @@ -131,6 +131,7 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) struct lws *wsi, *safe = NULL; const struct lws_protocols *p; const char *cisin[CIS_COUNT]; + char buf_localport[8]; struct lws_vhost *vh; int tsi; @@ -357,6 +358,8 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) cisin[CIS_PROTOCOL] = i->protocol; cisin[CIS_METHOD] = i->method; cisin[CIS_IFACE] = i->iface; + lws_snprintf(buf_localport, sizeof(buf_localport), "%u", i->local_port); + cisin[CIS_LOCALPORT] = buf_localport; cisin[CIS_ALPN] = i->alpn; if (lws_client_stash_create(wsi, cisin)) diff --git a/lib/core-net/client/connect3.c b/lib/core-net/client/connect3.c index 572252795..7b7be5f7a 100644 --- a/lib/core-net/client/connect3.c +++ b/lib/core-net/client/connect3.c @@ -153,7 +153,7 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, struct sockaddr_un sau; #endif struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; - const char *cce = "Unable to connect", *iface; + const char *cce = "Unable to connect", *iface, *local_port; const struct sockaddr *psa = NULL; uint16_t port = wsi->conn_port; char dcce[48], t16[16]; @@ -435,9 +435,12 @@ ads_known: iface = lws_wsi_client_stash_item(wsi, CIS_IFACE, _WSI_TOKEN_CLIENT_IFACE); - if (iface && *iface) { + local_port = lws_wsi_client_stash_item(wsi, CIS_LOCALPORT, + _WSI_TOKEN_CLIENT_LOCALPORT); + + if ((iface && *iface) || (local_port && atoi(local_port))) { m = lws_socket_bind(wsi->a.vhost, wsi, wsi->desc.sockfd, - 0, iface, af); + (local_port ? atoi(local_port) : 0), iface, af); if (m < 0) { lws_snprintf(dcce, sizeof(dcce), "conn fail: socket bind"); diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index 67d45a65f..ff558957a 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -221,6 +221,7 @@ enum { CIS_METHOD, CIS_IFACE, CIS_ALPN, + CIS_LOCALPORT, CIS_COUNT