Skip to content

Commit 552a3fd

Browse files
committed
lightningd: allow --bind=ws:
Changelog-Added: Config: `bind=ws:...` to explicitly listen on a websocket. Signed-off-by: Rusty Russell <[email protected]>
1 parent f62e766 commit 552a3fd

File tree

3 files changed

+65
-3
lines changed

3 files changed

+65
-3
lines changed

common/test/run-wireaddr.c

+44
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,50 @@ int main(int argc, char *argv[])
226226
strcpy(expect->u.sockname, "/tmp/foo.sock");
227227
assert(wireaddr_internal_eq(&addr, expect));
228228

229+
/* Websocket (only for IP addresses) */
230+
assert(parse_wireaddr_internal(tmpctx, "ws:/tmp/foo.sock", DEFAULT_PORT, false, &addr) != NULL);
231+
232+
assert(parse_wireaddr_internal(tmpctx, "ws:127.0.0.1", DEFAULT_PORT, false, &addr) == NULL);
233+
expect->itype = ADDR_INTERNAL_WIREADDR;
234+
expect->u.wireaddr.is_websocket = true;
235+
assert(parse_wireaddr(tmpctx, "127.0.0.1:9735", 0, NULL, &expect->u.wireaddr.wireaddr) == NULL);
236+
assert(wireaddr_internal_eq(&addr, expect));
237+
238+
/* Websocket: IPv4 address with port. */
239+
assert(parse_wireaddr_internal(tmpctx, "ws:127.0.0.1:1", DEFAULT_PORT, false, &addr) == NULL);
240+
expect->itype = ADDR_INTERNAL_WIREADDR;
241+
expect->u.wireaddr.is_websocket = true;
242+
assert(parse_wireaddr(tmpctx, "127.0.0.1:1", 0, NULL, &expect->u.wireaddr.wireaddr) == NULL);
243+
assert(wireaddr_internal_eq(&addr, expect));
244+
245+
/* Websocket: Simple IPv6 address. */
246+
assert(parse_wireaddr_internal(tmpctx, "ws:::1", DEFAULT_PORT, false, &addr) == NULL);
247+
expect->itype = ADDR_INTERNAL_WIREADDR;
248+
expect->u.wireaddr.is_websocket = true;
249+
assert(parse_wireaddr(tmpctx, "::1", DEFAULT_PORT, NULL, &expect->u.wireaddr.wireaddr) == NULL);
250+
assert(wireaddr_internal_eq(&addr, expect));
251+
252+
/* Websocket: IPv6 address with port. */
253+
assert(parse_wireaddr_internal(tmpctx, "ws:[::1]:1", DEFAULT_PORT, false, &addr) == NULL);
254+
expect->itype = ADDR_INTERNAL_WIREADDR;
255+
expect->u.wireaddr.is_websocket = true;
256+
assert(parse_wireaddr(tmpctx, "::1", 1, NULL, &expect->u.wireaddr.wireaddr) == NULL);
257+
assert(wireaddr_internal_eq(&addr, expect));
258+
259+
/* Websocket: IPv4 & v6 address. */
260+
assert(parse_wireaddr_internal(tmpctx, "ws:", DEFAULT_PORT, false, &addr) == NULL);
261+
expect->itype = ADDR_INTERNAL_ALLPROTO;
262+
expect->u.allproto.is_websocket = true;
263+
expect->u.allproto.port = DEFAULT_PORT;
264+
assert(wireaddr_internal_eq(&addr, expect));
265+
266+
/* Websocket: IPv4 & v6 address with port */
267+
assert(parse_wireaddr_internal(tmpctx, "ws::1", DEFAULT_PORT, false, &addr) == NULL);
268+
expect->itype = ADDR_INTERNAL_ALLPROTO;
269+
expect->u.allproto.is_websocket = true;
270+
expect->u.allproto.port = 1;
271+
assert(wireaddr_internal_eq(&addr, expect));
272+
229273
/* Unresolved */
230274
assert(parse_wireaddr_internal(tmpctx, "ozlabs.org", DEFAULT_PORT, false, &addr) == NULL);
231275
expect->itype = ADDR_INTERNAL_FORPROXY;

common/wireaddr.c

+14-3
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,7 @@ const char *parse_wireaddr_internal(const tal_t *ctx,
614614
char *ip;
615615
char *service_addr;
616616
const char *err;
617-
bool needed_dns;
617+
bool needed_dns, is_websocket;
618618

619619
/* Addresses starting with '/' are local socket paths */
620620
if (arg[0] == '/') {
@@ -697,6 +697,14 @@ const char *parse_wireaddr_internal(const tal_t *ctx,
697697
&addr->u.torservice.address);
698698
}
699699

700+
/* Do this before we get to separate_address_and_port! */
701+
if (strstarts(arg, "ws:")) {
702+
arg += 3;
703+
is_websocket = true;
704+
} else {
705+
is_websocket = false;
706+
}
707+
700708
/* This can fail, but that may be OK! */
701709
splitport = default_port;
702710
if (!separate_address_and_port(tmpctx, arg, &ip, &splitport))
@@ -706,7 +714,7 @@ const char *parse_wireaddr_internal(const tal_t *ctx,
706714
* means just IPv6, and IPv4 gets autobound). */
707715
if (ip && streq(ip, "")) {
708716
addr->itype = ADDR_INTERNAL_ALLPROTO;
709-
addr->u.allproto.is_websocket = false;
717+
addr->u.allproto.is_websocket = is_websocket;
710718
addr->u.allproto.port = splitport;
711719
return NULL;
712720
}
@@ -717,7 +725,7 @@ const char *parse_wireaddr_internal(const tal_t *ctx,
717725
&addr->u.wireaddr.wireaddr);
718726
if (!err) {
719727
addr->itype = ADDR_INTERNAL_WIREADDR;
720-
addr->u.wireaddr.is_websocket = false;
728+
addr->u.wireaddr.is_websocket = is_websocket;
721729
return NULL;
722730
}
723731

@@ -729,6 +737,9 @@ const char *parse_wireaddr_internal(const tal_t *ctx,
729737
if (!ip)
730738
return "Malformed port";
731739

740+
if (is_websocket)
741+
return "Could not resolve websocket address";
742+
732743
/* Keep unresolved. */
733744
tal_free(err);
734745
if (!wireaddr_from_unresolved(addr, ip, splitport))

lightningd/options.c

+7
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,9 @@ static char *opt_add_addr_withtype(const char *arg,
271271
switch (wi.u.wireaddr.wireaddr.type) {
272272
case ADDR_TYPE_IPV4:
273273
case ADDR_TYPE_IPV6:
274+
if ((ala & ADDR_ANNOUNCE) && wi.u.allproto.is_websocket)
275+
return tal_fmt(NULL,
276+
"Cannot announce websocket address, use --bind-addr=%s", arg);
274277
/* These can be either bind or announce */
275278
break;
276279
case ADDR_TYPE_TOR_V2_REMOVED:
@@ -363,6 +366,10 @@ static char *opt_add_addr_withtype(const char *arg,
363366
case ADDR_ANNOUNCE:
364367
return tal_fmt(NULL, "Cannot use wildcard address '%s'", arg);
365368
case ADDR_LISTEN_AND_ANNOUNCE:
369+
if (wi.u.allproto.is_websocket)
370+
return tal_fmt(NULL,
371+
"Cannot announce websocket address, use --bind-addr=%s", arg);
372+
/* fall thru */
366373
case ADDR_LISTEN:
367374
break;
368375
}

0 commit comments

Comments
 (0)