Skip to content

Commit

Permalink
lightningd: allow --bind=ws:
Browse files Browse the repository at this point in the history
Changelog-Added: Config: `bind=ws:...` to explicitly listen on a websocket.
Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell committed May 31, 2023
1 parent a6772e9 commit 3d53672
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 3 deletions.
44 changes: 44 additions & 0 deletions common/test/run-wireaddr.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,50 @@ int main(int argc, char *argv[])
strcpy(expect->u.sockname, "/tmp/foo.sock");
assert(wireaddr_internal_eq(&addr, expect));

/* Websocket (only for IP addresses) */
assert(parse_wireaddr_internal(tmpctx, "ws:/tmp/foo.sock", DEFAULT_PORT, false, &addr) != NULL);

assert(parse_wireaddr_internal(tmpctx, "ws:127.0.0.1", DEFAULT_PORT, false, &addr) == NULL);
expect->itype = ADDR_INTERNAL_WIREADDR;
expect->u.wireaddr.is_websocket = true;
assert(parse_wireaddr(tmpctx, "127.0.0.1:9735", 0, NULL, &expect->u.wireaddr.wireaddr) == NULL);
assert(wireaddr_internal_eq(&addr, expect));

/* Websocket: IPv4 address with port. */
assert(parse_wireaddr_internal(tmpctx, "ws:127.0.0.1:1", DEFAULT_PORT, false, &addr) == NULL);
expect->itype = ADDR_INTERNAL_WIREADDR;
expect->u.wireaddr.is_websocket = true;
assert(parse_wireaddr(tmpctx, "127.0.0.1:1", 0, NULL, &expect->u.wireaddr.wireaddr) == NULL);
assert(wireaddr_internal_eq(&addr, expect));

/* Websocket: Simple IPv6 address. */
assert(parse_wireaddr_internal(tmpctx, "ws:::1", DEFAULT_PORT, false, &addr) == NULL);
expect->itype = ADDR_INTERNAL_WIREADDR;
expect->u.wireaddr.is_websocket = true;
assert(parse_wireaddr(tmpctx, "::1", DEFAULT_PORT, NULL, &expect->u.wireaddr.wireaddr) == NULL);
assert(wireaddr_internal_eq(&addr, expect));

/* Websocket: IPv6 address with port. */
assert(parse_wireaddr_internal(tmpctx, "ws:[::1]:1", DEFAULT_PORT, false, &addr) == NULL);
expect->itype = ADDR_INTERNAL_WIREADDR;
expect->u.wireaddr.is_websocket = true;
assert(parse_wireaddr(tmpctx, "::1", 1, NULL, &expect->u.wireaddr.wireaddr) == NULL);
assert(wireaddr_internal_eq(&addr, expect));

/* Websocket: IPv4 & v6 address. */
assert(parse_wireaddr_internal(tmpctx, "ws:", DEFAULT_PORT, false, &addr) == NULL);
expect->itype = ADDR_INTERNAL_ALLPROTO;
expect->u.allproto.is_websocket = true;
expect->u.allproto.port = DEFAULT_PORT;
assert(wireaddr_internal_eq(&addr, expect));

/* Websocket: IPv4 & v6 address with port */
assert(parse_wireaddr_internal(tmpctx, "ws::1", DEFAULT_PORT, false, &addr) == NULL);
expect->itype = ADDR_INTERNAL_ALLPROTO;
expect->u.allproto.is_websocket = true;
expect->u.allproto.port = 1;
assert(wireaddr_internal_eq(&addr, expect));

/* Unresolved */
assert(parse_wireaddr_internal(tmpctx, "ozlabs.org", DEFAULT_PORT, false, &addr) == NULL);
expect->itype = ADDR_INTERNAL_FORPROXY;
Expand Down
17 changes: 14 additions & 3 deletions common/wireaddr.c
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ const char *parse_wireaddr_internal(const tal_t *ctx,
char *ip;
char *service_addr;
const char *err;
bool needed_dns;
bool needed_dns, is_websocket;

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

/* Do this before we get to separate_address_and_port! */
if (strstarts(arg, "ws:")) {
arg += 3;
is_websocket = true;
} else {
is_websocket = false;
}

/* This can fail, but that may be OK! */
splitport = default_port;
if (!separate_address_and_port(tmpctx, arg, &ip, &splitport))
Expand All @@ -706,7 +714,7 @@ const char *parse_wireaddr_internal(const tal_t *ctx,
* means just IPv6, and IPv4 gets autobound). */
if (ip && streq(ip, "")) {
addr->itype = ADDR_INTERNAL_ALLPROTO;
addr->u.allproto.is_websocket = false;
addr->u.allproto.is_websocket = is_websocket;
addr->u.allproto.port = splitport;
return NULL;
}
Expand All @@ -717,7 +725,7 @@ const char *parse_wireaddr_internal(const tal_t *ctx,
&addr->u.wireaddr.wireaddr);
if (!err) {
addr->itype = ADDR_INTERNAL_WIREADDR;
addr->u.wireaddr.is_websocket = false;
addr->u.wireaddr.is_websocket = is_websocket;
return NULL;
}

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

if (is_websocket)
return "Could not resolve websocket address";

/* Keep unresolved. */
tal_free(err);
if (!wireaddr_from_unresolved(addr, ip, splitport))
Expand Down
7 changes: 7 additions & 0 deletions lightningd/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,9 @@ static char *opt_add_addr_withtype(const char *arg,
switch (wi.u.wireaddr.wireaddr.type) {
case ADDR_TYPE_IPV4:
case ADDR_TYPE_IPV6:
if ((ala & ADDR_ANNOUNCE) && wi.u.allproto.is_websocket)
return tal_fmt(NULL,
"Cannot announce websocket address, use --bind-addr=%s", arg);
/* These can be either bind or announce */
break;
case ADDR_TYPE_TOR_V2_REMOVED:
Expand Down Expand Up @@ -363,6 +366,10 @@ static char *opt_add_addr_withtype(const char *arg,
case ADDR_ANNOUNCE:
return tal_fmt(NULL, "Cannot use wildcard address '%s'", arg);
case ADDR_LISTEN_AND_ANNOUNCE:
if (wi.u.allproto.is_websocket)
return tal_fmt(NULL,
"Cannot announce websocket address, use --bind-addr=%s", arg);
/* fall thru */
case ADDR_LISTEN:
break;
}
Expand Down

0 comments on commit 3d53672

Please sign in to comment.