common: add new internal type for websockets.

Now it's not a public type, we need a way to refer to it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2023-05-30 13:58:18 +09:30
parent 7b843e8e58
commit a6772e9dec
21 changed files with 285 additions and 126 deletions

View file

@ -63,7 +63,8 @@
"ipv6": 2,
"local socket": 0,
"torv2": 3,
"torv3": 4
"torv3": 4,
"websocket": 5
},
"GetrouteRouteStyle": {
"tlv": 0

View file

@ -113,6 +113,7 @@ message GetinfoBinding {
// Getinfo.binding[].type
enum GetinfoBindingType {
LOCAL_SOCKET = 0;
WEBSOCKET = 5;
IPV4 = 1;
IPV6 = 2;
TORV2 = 3;

11
cln-rpc/src/model.rs generated
View file

@ -1476,6 +1476,8 @@ pub mod responses {
pub enum GetinfoBindingType {
#[serde(rename = "local socket")]
LOCAL_SOCKET,
#[serde(rename = "websocket")]
WEBSOCKET,
#[serde(rename = "ipv4")]
IPV4,
#[serde(rename = "ipv6")]
@ -1491,10 +1493,11 @@ pub mod responses {
fn try_from(c: i32) -> Result<GetinfoBindingType, anyhow::Error> {
match c {
0 => Ok(GetinfoBindingType::LOCAL_SOCKET),
1 => Ok(GetinfoBindingType::IPV4),
2 => Ok(GetinfoBindingType::IPV6),
3 => Ok(GetinfoBindingType::TORV2),
4 => Ok(GetinfoBindingType::TORV3),
1 => Ok(GetinfoBindingType::WEBSOCKET),
2 => Ok(GetinfoBindingType::IPV4),
3 => Ok(GetinfoBindingType::IPV6),
4 => Ok(GetinfoBindingType::TORV2),
5 => Ok(GetinfoBindingType::TORV3),
o => Err(anyhow::anyhow!("Unknown variant {} for enum GetinfoBindingType", o)),
}
}

View file

@ -493,35 +493,54 @@ void json_add_short_channel_id(struct json_stream *response,
short_channel_id_outnum(scid));
}
static void json_add_address_fields(struct json_stream *response,
const struct wireaddr *addr,
const char *typefield)
{
switch (addr->type) {
case ADDR_TYPE_IPV4: {
char addrstr[INET_ADDRSTRLEN];
inet_ntop(AF_INET, addr->addr, addrstr, INET_ADDRSTRLEN);
json_add_string(response, typefield, "ipv4");
json_add_string(response, "address", addrstr);
json_add_num(response, "port", addr->port);
return;
}
case ADDR_TYPE_IPV6: {
char addrstr[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, addr->addr, addrstr, INET6_ADDRSTRLEN);
json_add_string(response, typefield, "ipv6");
json_add_string(response, "address", addrstr);
json_add_num(response, "port", addr->port);
return;
}
case ADDR_TYPE_TOR_V2_REMOVED: {
json_add_string(response, typefield, "torv2");
json_add_string(response, "address", fmt_wireaddr_without_port(tmpctx, addr));
json_add_num(response, "port", addr->port);
return;
}
case ADDR_TYPE_TOR_V3: {
json_add_string(response, typefield, "torv3");
json_add_string(response, "address", fmt_wireaddr_without_port(tmpctx, addr));
json_add_num(response, "port", addr->port);
return;
}
case ADDR_TYPE_DNS: {
json_add_string(response, typefield, "dns");
json_add_string(response, "address", fmt_wireaddr_without_port(tmpctx, addr));
json_add_num(response, "port", addr->port);
return;
}
}
abort();
}
void json_add_address(struct json_stream *response, const char *fieldname,
const struct wireaddr *addr)
{
json_object_start(response, fieldname);
if (addr->type == ADDR_TYPE_IPV4) {
char addrstr[INET_ADDRSTRLEN];
inet_ntop(AF_INET, addr->addr, addrstr, INET_ADDRSTRLEN);
json_add_string(response, "type", "ipv4");
json_add_string(response, "address", addrstr);
json_add_num(response, "port", addr->port);
} else if (addr->type == ADDR_TYPE_IPV6) {
char addrstr[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, addr->addr, addrstr, INET6_ADDRSTRLEN);
json_add_string(response, "type", "ipv6");
json_add_string(response, "address", addrstr);
json_add_num(response, "port", addr->port);
} else if (addr->type == ADDR_TYPE_TOR_V2_REMOVED) {
json_add_string(response, "type", "torv2");
json_add_string(response, "address", fmt_wireaddr_without_port(tmpctx, addr));
json_add_num(response, "port", addr->port);
} else if (addr->type == ADDR_TYPE_TOR_V3) {
json_add_string(response, "type", "torv3");
json_add_string(response, "address", fmt_wireaddr_without_port(tmpctx, addr));
json_add_num(response, "port", addr->port);
} else if (addr->type == ADDR_TYPE_DNS) {
json_add_string(response, "type", "dns");
json_add_string(response, "address", fmt_wireaddr_without_port(tmpctx, addr));
json_add_num(response, "port", addr->port);
}
json_add_address_fields(response, addr, "type");
json_object_end(response);
}
@ -538,8 +557,13 @@ void json_add_address_internal(struct json_stream *response,
return;
case ADDR_INTERNAL_ALLPROTO:
json_object_start(response, fieldname);
json_add_string(response, "type", "any protocol");
json_add_num(response, "port", addr->u.port);
if (addr->u.allproto.is_websocket) {
json_add_string(response, "type", "websocket");
json_add_string(response, "subtype", "any protocol");
} else {
json_add_string(response, "type", "any protocol");
}
json_add_num(response, "port", addr->u.allproto.port);
json_object_end(response);
return;
case ADDR_INTERNAL_AUTOTOR:
@ -562,7 +586,14 @@ void json_add_address_internal(struct json_stream *response,
json_object_end(response);
return;
case ADDR_INTERNAL_WIREADDR:
json_add_address(response, fieldname, &addr->u.wireaddr);
json_object_start(response, fieldname);
if (addr->u.wireaddr.is_websocket) {
json_add_string(response, "type", "websocket");
json_add_address_fields(response, &addr->u.wireaddr.wireaddr, "subtype");
} else {
json_add_address_fields(response, &addr->u.wireaddr.wireaddr, "type");
}
json_object_end(response);
return;
}
abort();

View file

@ -134,25 +134,29 @@ int main(int argc, char *argv[])
/* Simple IPv4 address. */
assert(parse_wireaddr_internal(tmpctx, "127.0.0.1", DEFAULT_PORT, false, &addr) == NULL);
expect->itype = ADDR_INTERNAL_WIREADDR;
assert(parse_wireaddr(tmpctx, "127.0.0.1:9735", 0, NULL, &expect->u.wireaddr) == NULL);
expect->u.wireaddr.is_websocket = false;
assert(parse_wireaddr(tmpctx, "127.0.0.1:9735", 0, NULL, &expect->u.wireaddr.wireaddr) == NULL);
assert(wireaddr_internal_eq(&addr, expect));
/* IPv4 address with port. */
assert(parse_wireaddr_internal(tmpctx, "127.0.0.1:1", DEFAULT_PORT, false, &addr) == NULL);
expect->itype = ADDR_INTERNAL_WIREADDR;
assert(parse_wireaddr(tmpctx, "127.0.0.1:1", 0, NULL, &expect->u.wireaddr) == NULL);
expect->u.wireaddr.is_websocket = false;
assert(parse_wireaddr(tmpctx, "127.0.0.1:1", 0, NULL, &expect->u.wireaddr.wireaddr) == NULL);
assert(wireaddr_internal_eq(&addr, expect));
/* Simple IPv6 address. */
assert(parse_wireaddr_internal(tmpctx, "::1", DEFAULT_PORT, false, &addr) == NULL);
expect->itype = ADDR_INTERNAL_WIREADDR;
assert(parse_wireaddr(tmpctx, "::1", DEFAULT_PORT, NULL, &expect->u.wireaddr) == NULL);
expect->u.wireaddr.is_websocket = false;
assert(parse_wireaddr(tmpctx, "::1", DEFAULT_PORT, NULL, &expect->u.wireaddr.wireaddr) == NULL);
assert(wireaddr_internal_eq(&addr, expect));
/* IPv6 address with port. */
assert(parse_wireaddr_internal(tmpctx, "[::1]:1", DEFAULT_PORT, false, &addr) == NULL);
expect->itype = ADDR_INTERNAL_WIREADDR;
assert(parse_wireaddr(tmpctx, "::1", 1, NULL, &expect->u.wireaddr) == NULL);
expect->u.wireaddr.is_websocket = false;
assert(parse_wireaddr(tmpctx, "::1", 1, NULL, &expect->u.wireaddr.wireaddr) == NULL);
assert(wireaddr_internal_eq(&addr, expect));
/* autotor address */

View file

@ -98,10 +98,12 @@ void towire_wireaddr_internal(u8 **pptr, const struct wireaddr_internal *addr)
towire_u16(pptr, addr->u.torservice.port);
return;
case ADDR_INTERNAL_ALLPROTO:
towire_u16(pptr, addr->u.port);
towire_bool(pptr, addr->u.allproto.is_websocket);
towire_u16(pptr, addr->u.allproto.port);
return;
case ADDR_INTERNAL_WIREADDR:
towire_wireaddr(pptr, &addr->u.wireaddr);
towire_bool(pptr, addr->u.wireaddr.is_websocket);
towire_wireaddr(pptr, &addr->u.wireaddr.wireaddr);
return;
case ADDR_INTERNAL_FORPROXY:
towire_u8_array(pptr, (const u8 *)addr->u.unresolved.name,
@ -125,7 +127,8 @@ bool fromwire_wireaddr_internal(const u8 **cursor, size_t *max,
fromwire_fail(cursor, max);
return *cursor != NULL;
case ADDR_INTERNAL_ALLPROTO:
addr->u.port = fromwire_u16(cursor, max);
addr->u.allproto.is_websocket = fromwire_bool(cursor, max);
addr->u.allproto.port = fromwire_u16(cursor, max);
return *cursor != NULL;
case ADDR_INTERNAL_AUTOTOR:
fromwire_wireaddr(cursor, max, &addr->u.torservice.address);
@ -138,7 +141,8 @@ bool fromwire_wireaddr_internal(const u8 **cursor, size_t *max,
addr->u.torservice.port = fromwire_u16(cursor, max);
return *cursor != NULL;
case ADDR_INTERNAL_WIREADDR:
return fromwire_wireaddr(cursor, max, &addr->u.wireaddr);
addr->u.wireaddr.is_websocket = fromwire_bool(cursor, max);
return fromwire_wireaddr(cursor, max, &addr->u.wireaddr.wireaddr);
case ADDR_INTERNAL_FORPROXY:
fromwire_u8_array(cursor, max, (u8 *)addr->u.unresolved.name,
sizeof(addr->u.unresolved.name));
@ -220,9 +224,13 @@ char *fmt_wireaddr_internal(const tal_t *ctx,
case ADDR_INTERNAL_SOCKNAME:
return tal_fmt(ctx, "%s", a->u.sockname);
case ADDR_INTERNAL_ALLPROTO:
return tal_fmt(ctx, ":%u", a->u.port);
return tal_fmt(ctx, "%s:%u", a->u.allproto.is_websocket ? "(ws)": "",
a->u.allproto.port);
case ADDR_INTERNAL_WIREADDR:
return fmt_wireaddr(ctx, &a->u.wireaddr);
if (a->u.wireaddr.is_websocket)
return tal_fmt(ctx, "(ws)%s",
fmt_wireaddr(tmpctx, &a->u.wireaddr.wireaddr));
return fmt_wireaddr(ctx, &a->u.wireaddr.wireaddr);
case ADDR_INTERNAL_FORPROXY:
return tal_fmt(ctx, "%s:%u",
a->u.unresolved.name, a->u.unresolved.port);
@ -573,7 +581,8 @@ bool wireaddr_internal_eq(const struct wireaddr_internal *a,
case ADDR_INTERNAL_SOCKNAME:
return streq(a->u.sockname, b->u.sockname);
case ADDR_INTERNAL_ALLPROTO:
return a->u.port == b->u.port;
return a->u.allproto.is_websocket == b->u.allproto.is_websocket
&& a->u.allproto.port == b->u.allproto.port;
case ADDR_INTERNAL_STATICTOR:
if (!memeq(a->u.torservice.blob, sizeof(a->u.torservice.blob),
b->u.torservice.blob, sizeof(b->u.torservice.blob)))
@ -589,7 +598,8 @@ bool wireaddr_internal_eq(const struct wireaddr_internal *a,
return false;
return a->u.unresolved.port == b->u.unresolved.port;
case ADDR_INTERNAL_WIREADDR:
return wireaddr_eq(&a->u.wireaddr, &b->u.wireaddr);
return a->u.wireaddr.is_websocket == b->u.wireaddr.is_websocket
&& wireaddr_eq(&a->u.wireaddr.wireaddr, &b->u.wireaddr.wireaddr);
}
abort();
}
@ -696,16 +706,18 @@ 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.port = splitport;
addr->u.allproto.is_websocket = false;
addr->u.allproto.port = splitport;
return NULL;
}
needed_dns = false;
err = parse_wireaddr(ctx, arg, default_port,
dns_lookup_ok ? NULL : &needed_dns,
&addr->u.wireaddr);
&addr->u.wireaddr.wireaddr);
if (!err) {
addr->itype = ADDR_INTERNAL_WIREADDR;
addr->u.wireaddr.is_websocket = false;
return NULL;
}
@ -779,7 +791,7 @@ struct addrinfo *wireaddr_internal_to_addrinfo(const tal_t *ctx,
case ADDR_INTERNAL_FORPROXY:
break;
case ADDR_INTERNAL_WIREADDR:
return wireaddr_to_addrinfo(ctx, &wireaddr->u.wireaddr);
return wireaddr_to_addrinfo(ctx, &wireaddr->u.wireaddr.wireaddr);
}
abort();
}
@ -859,7 +871,7 @@ bool all_tor_addresses(const struct wireaddr_internal *wireaddr)
case ADDR_INTERNAL_STATICTOR:
continue;
case ADDR_INTERNAL_WIREADDR:
switch (wireaddr[i].u.wireaddr.type) {
switch (wireaddr[i].u.wireaddr.wireaddr.type) {
case ADDR_TYPE_IPV4:
case ADDR_TYPE_IPV6:
case ADDR_TYPE_DNS:

View file

@ -127,9 +127,15 @@ struct wireaddr_internal {
enum wireaddr_internal_type itype;
union {
/* ADDR_INTERNAL_WIREADDR */
struct wireaddr wireaddr;
struct waddr {
struct wireaddr wireaddr;
bool is_websocket;
} wireaddr;
/* ADDR_INTERNAL_ALLPROTO */
u16 port;
struct allproto {
u16 port;
bool is_websocket;
} allproto;
/* ADDR_INTERNAL_AUTOTOR
* ADDR_INTERNAL_STATICTOR */
struct torservice {

View file

@ -410,12 +410,12 @@ static bool get_remote_address(struct io_conn *conn,
if (s.ss_family == AF_INET6) {
struct sockaddr_in6 *s6 = (void *)&s;
addr->itype = ADDR_INTERNAL_WIREADDR;
wireaddr_from_ipv6(&addr->u.wireaddr,
wireaddr_from_ipv6(&addr->u.wireaddr.wireaddr,
&s6->sin6_addr, ntohs(s6->sin6_port));
} else if (s.ss_family == AF_INET) {
struct sockaddr_in *s4 = (void *)&s;
addr->itype = ADDR_INTERNAL_WIREADDR;
wireaddr_from_ipv4(&addr->u.wireaddr,
wireaddr_from_ipv4(&addr->u.wireaddr.wireaddr,
&s4->sin_addr, ntohs(s4->sin_port));
} else if (s.ss_family == AF_UNIX) {
struct sockaddr_un *sun = (void *)&s;
@ -468,6 +468,7 @@ static struct io_plan *connection_in(struct io_conn *conn,
{
struct conn_in conn_in_arg;
conn_in_arg.addr.u.wireaddr.is_websocket = false;
if (!get_remote_address(conn, &conn_in_arg.addr))
return io_close(conn);
@ -487,6 +488,7 @@ static struct io_plan *websocket_connection_in(struct io_conn *conn,
int err;
struct conn_in conn_in_arg;
conn_in_arg.addr.u.wireaddr.is_websocket = true;
if (!get_remote_address(conn, &conn_in_arg.addr))
return io_close(conn);
@ -724,10 +726,10 @@ static struct io_plan *conn_init(struct io_conn *conn,
break;
case ADDR_INTERNAL_WIREADDR:
/* DNS should have been resolved before */
assert(addr->u.wireaddr.type != ADDR_TYPE_DNS);
assert(addr->u.wireaddr.wireaddr.type != ADDR_TYPE_DNS);
/* If it was a Tor address, we wouldn't be here. */
assert(!is_toraddr((char*)addr->u.wireaddr.addr));
ai = wireaddr_to_addrinfo(tmpctx, &addr->u.wireaddr);
assert(!is_toraddr((char*)addr->u.wireaddr.wireaddr.addr));
ai = wireaddr_to_addrinfo(tmpctx, &addr->u.wireaddr.wireaddr);
break;
}
assert(ai);
@ -751,8 +753,8 @@ static struct io_plan *conn_proxy_init(struct io_conn *conn,
port = addr->u.unresolved.port;
break;
case ADDR_INTERNAL_WIREADDR:
host = fmt_wireaddr_without_port(tmpctx, &addr->u.wireaddr);
port = addr->u.wireaddr.port;
host = fmt_wireaddr_without_port(tmpctx, &addr->u.wireaddr.wireaddr);
port = addr->u.wireaddr.wireaddr.port;
break;
case ADDR_INTERNAL_SOCKNAME:
case ADDR_INTERNAL_ALLPROTO:
@ -818,7 +820,7 @@ static void try_connect_one_addr(struct connecting *connect)
use_proxy = true;
break;
case ADDR_INTERNAL_WIREADDR:
switch (addr->u.wireaddr.type) {
switch (addr->u.wireaddr.wireaddr.type) {
case ADDR_TYPE_TOR_V2_REMOVED:
af = -1;
break;
@ -848,9 +850,9 @@ static void try_connect_one_addr(struct connecting *connect)
hints.ai_family = AF_UNSPEC;
hints.ai_protocol = 0;
hints.ai_flags = AI_ADDRCONFIG;
gai_err = getaddrinfo((char *)addr->u.wireaddr.addr,
gai_err = getaddrinfo((char *)addr->u.wireaddr.wireaddr.addr,
tal_fmt(tmpctx, "%d",
addr->u.wireaddr.port),
addr->u.wireaddr.wireaddr.port),
&hints, &ais);
if (gai_err != 0) {
tal_append_fmt(&connect->errors,
@ -864,16 +866,17 @@ static void try_connect_one_addr(struct connecting *connect)
/* create new addrhints on-the-fly per result ... */
for (aii = ais; aii; aii = aii->ai_next) {
addrhint.itype = ADDR_INTERNAL_WIREADDR;
addrhint.u.wireaddr.is_websocket = false;
if (aii->ai_family == AF_INET) {
sa4 = (struct sockaddr_in *) aii->ai_addr;
wireaddr_from_ipv4(&addrhint.u.wireaddr,
wireaddr_from_ipv4(&addrhint.u.wireaddr.wireaddr,
&sa4->sin_addr,
addr->u.wireaddr.port);
addr->u.wireaddr.wireaddr.port);
} else if (aii->ai_family == AF_INET6) {
sa6 = (struct sockaddr_in6 *) aii->ai_addr;
wireaddr_from_ipv6(&addrhint.u.wireaddr,
wireaddr_from_ipv6(&addrhint.u.wireaddr.wireaddr,
&sa6->sin6_addr,
addr->u.wireaddr.port);
addr->u.wireaddr.wireaddr.port);
} else {
/* skip unsupported ai_family */
continue;
@ -1038,15 +1041,15 @@ fail:
static struct listen_fd *handle_wireaddr_listen(const tal_t *ctx,
const struct wireaddr_internal *wi,
bool listen_mayfail,
enum is_websocket is_websocket,
char **errstr)
{
struct sockaddr_in addr;
struct sockaddr_in6 addr6;
const struct wireaddr *wireaddr;
bool is_websocket = wi->u.wireaddr.is_websocket;
assert(wi->itype == ADDR_INTERNAL_WIREADDR);
wireaddr = &wi->u.wireaddr;
wireaddr = &wi->u.wireaddr.wireaddr;
/* Note the use of a switch() over enum here, even though it must be
* IPv4 or IPv6 here; that will catch future changes. */
@ -1098,10 +1101,12 @@ find_local_address(const struct listen_fd **listen_fds)
for (size_t i = 0; i < tal_count(listen_fds); i++) {
if (listen_fds[i]->wi.itype != ADDR_INTERNAL_WIREADDR)
continue;
if (listen_fds[i]->wi.u.wireaddr.type != ADDR_TYPE_IPV4
&& listen_fds[i]->wi.u.wireaddr.type != ADDR_TYPE_IPV6)
if (listen_fds[i]->wi.u.wireaddr.is_websocket)
continue;
return &listen_fds[i]->wi.u.wireaddr;
if (listen_fds[i]->wi.u.wireaddr.wireaddr.type != ADDR_TYPE_IPV4
&& listen_fds[i]->wi.u.wireaddr.wireaddr.type != ADDR_TYPE_IPV6)
continue;
return &listen_fds[i]->wi.u.wireaddr.wireaddr;
}
return NULL;
}
@ -1164,7 +1169,7 @@ setup_listeners(const tal_t *ctx,
/* You can only announce wiretypes, not internal formats! */
assert(proposed_wireaddr[i].itype
== ADDR_INTERNAL_WIREADDR);
add_announceable(announceable, &wa.u.wireaddr);
add_announceable(announceable, &wa.u.wireaddr.wireaddr);
}
/* Now look for listening addresses. */
@ -1204,42 +1209,41 @@ setup_listeners(const tal_t *ctx,
bool ipv6_ok;
wa.itype = ADDR_INTERNAL_WIREADDR;
wa.u.wireaddr.port = wa.u.port;
wa.u.wireaddr.wireaddr.port = wa.u.allproto.port;
wa.u.wireaddr.is_websocket = wa.u.allproto.is_websocket;
/* First, create wildcard IPv6 address. */
wa.u.wireaddr.type = ADDR_TYPE_IPV6;
wa.u.wireaddr.addrlen = 16;
memset(wa.u.wireaddr.addr, 0,
sizeof(wa.u.wireaddr.addr));
wa.u.wireaddr.wireaddr.type = ADDR_TYPE_IPV6;
wa.u.wireaddr.wireaddr.addrlen = 16;
memset(wa.u.wireaddr.wireaddr.addr, 0,
sizeof(wa.u.wireaddr.wireaddr.addr));
/* This may fail due to no IPv6 support. */
lfd = handle_wireaddr_listen(ctx, &wa, false,
NORMAL_SOCKET, errstr);
lfd = handle_wireaddr_listen(ctx, &wa, false, errstr);
if (lfd) {
tal_arr_expand(&listen_fds,
tal_steal(listen_fds, lfd));
if (announce
&& public_address(daemon, &wa.u.wireaddr))
&& public_address(daemon, &wa.u.wireaddr.wireaddr))
add_announceable(announceable,
&wa.u.wireaddr);
&wa.u.wireaddr.wireaddr);
}
ipv6_ok = (lfd != NULL);
/* Now, create wildcard IPv4 address. */
wa.u.wireaddr.type = ADDR_TYPE_IPV4;
wa.u.wireaddr.addrlen = 4;
memset(wa.u.wireaddr.addr, 0,
sizeof(wa.u.wireaddr.addr));
wa.u.wireaddr.wireaddr.type = ADDR_TYPE_IPV4;
wa.u.wireaddr.wireaddr.addrlen = 4;
memset(wa.u.wireaddr.wireaddr.addr, 0,
sizeof(wa.u.wireaddr.wireaddr.addr));
/* This listen *may* fail, as long as IPv6 succeeds! */
lfd = handle_wireaddr_listen(ctx, &wa, ipv6_ok,
NORMAL_SOCKET, errstr);
lfd = handle_wireaddr_listen(ctx, &wa, ipv6_ok, errstr);
if (lfd) {
tal_arr_expand(&listen_fds,
tal_steal(listen_fds, lfd));
if (announce
&& public_address(daemon, &wa.u.wireaddr))
&& public_address(daemon, &wa.u.wireaddr.wireaddr))
add_announceable(announceable,
&wa.u.wireaddr);
&wa.u.wireaddr.wireaddr);
} else if (!ipv6_ok) {
/* Both failed, return now, errstr set. */
return NULL;
@ -1248,13 +1252,12 @@ setup_listeners(const tal_t *ctx,
}
/* This is a vanilla wireaddr as per BOLT #7 */
case ADDR_INTERNAL_WIREADDR:
lfd = handle_wireaddr_listen(ctx, &wa, false,
NORMAL_SOCKET, errstr);
lfd = handle_wireaddr_listen(ctx, &wa, false, errstr);
if (!lfd)
return NULL;
tal_arr_expand(&listen_fds, tal_steal(listen_fds, lfd));
if (announce && public_address(daemon, &wa.u.wireaddr))
add_announceable(announceable, &wa.u.wireaddr);
if (announce && public_address(daemon, &wa.u.wireaddr.wireaddr))
add_announceable(announceable, &wa.u.wireaddr.wireaddr);
continue;
case ADDR_INTERNAL_FORPROXY:
break;
@ -1288,14 +1291,14 @@ setup_listeners(const tal_t *ctx,
/* Override with websocket port */
addr = listen_fds[i]->wi;
addr.u.wireaddr.port = daemon->websocket_port;
addr.u.wireaddr.is_websocket = true;
addr.u.wireaddr.wireaddr.port = daemon->websocket_port;
/* We set mayfail on all but the first websocket;
* it's quite common to have multple overlapping
* addresses. */
lfd = handle_wireaddr_listen(ctx, &addr,
announced_some,
WEBSOCKET, errstr);
lfd = handle_wireaddr_listen(ctx, &addr, announced_some,
errstr);
if (!lfd)
continue;
@ -1610,10 +1613,11 @@ static void add_seed_addrs(struct wireaddr_internal **addrs,
continue;
struct wireaddr_internal a;
a.itype = ADDR_INTERNAL_WIREADDR;
a.u.wireaddr = new_addrs[j];
a.u.wireaddr.is_websocket = false;
a.u.wireaddr.wireaddr = new_addrs[j];
status_peer_debug(id, "Resolved %s to %s", hostnames[i],
type_to_string(tmpctx, struct wireaddr,
&a.u.wireaddr));
&a.u.wireaddr.wireaddr));
tal_arr_expand(addrs, a);
}
/* Other seeds will likely have the same information. */
@ -1640,7 +1644,8 @@ static void add_gossip_addrs_bytypes(struct wireaddr_internal **addrs,
if (((u64)1 << normal_addrs[i].type) & types) {
struct wireaddr_internal addr;
addr.itype = ADDR_INTERNAL_WIREADDR;
addr.u.wireaddr = normal_addrs[i];
addr.u.wireaddr.is_websocket = false;
addr.u.wireaddr.wireaddr = normal_addrs[i];
tal_arr_expand(addrs, addr);
}
}
@ -1731,8 +1736,10 @@ static void try_connect_peer(struct daemon *daemon,
/* Tell it to omit the existing hint (if that's a wireaddr itself) */
add_gossip_addrs(&addrs, gossip_addrs,
addrhint && addrhint->itype == ADDR_INTERNAL_WIREADDR
? &addrhint->u.wireaddr : NULL);
addrhint
&& addrhint->itype == ADDR_INTERNAL_WIREADDR
&& !addrhint->u.wireaddr.is_websocket
? &addrhint->u.wireaddr.wireaddr : NULL);
if (tal_count(addrs) == 0) {
/* Don't resolve via DNS seed if we're supposed to use proxy. */

View file

@ -236,13 +236,15 @@ struct io_plan *peer_exchange_initmsg(struct io_conn *conn,
* incoming connection, if the node is the receiver and the connection was done
* via IP.
*/
if (incoming && addr->itype == ADDR_INTERNAL_WIREADDR &&
address_routable(&addr->u.wireaddr, true)) {
switch (addr->u.wireaddr.type) {
if (incoming
&& addr->itype == ADDR_INTERNAL_WIREADDR
&& !addr->u.wireaddr.is_websocket
&& address_routable(&addr->u.wireaddr.wireaddr, true)) {
switch (addr->u.wireaddr.wireaddr.type) {
case ADDR_TYPE_IPV4:
case ADDR_TYPE_IPV6:
tlvs->remote_addr = tal_arr(tlvs, u8, 0);
towire_wireaddr(&tlvs->remote_addr, &addr->u.wireaddr);
towire_wireaddr(&tlvs->remote_addr, &addr->u.wireaddr.wireaddr);
break;
/* Only report IP addresses back for now */
case ADDR_TYPE_TOR_V2_REMOVED:

View file

@ -327,7 +327,7 @@ int main(int argc, char *argv[])
e_pub = pubkey("036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f7");
dummy.itype = ADDR_INTERNAL_WIREADDR;
dummy.u.wireaddr.addrlen = 0;
dummy.u.wireaddr.wireaddr.addrlen = 0;
initiator_handshake((void *)tmpctx, &ls_pub, &rs_pub, &dummy, NULL, NORMAL_SOCKET, success, NULL);
/* Should not exit! */
abort();

View file

@ -321,7 +321,7 @@ int main(int argc, char *argv[])
e_pub = pubkey("02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27");
dummy.itype = ADDR_INTERNAL_WIREADDR;
dummy.u.wireaddr.addrlen = 0;
dummy.u.wireaddr.wireaddr.addrlen = 0;
responder_handshake((void *)tmpctx, &ls_pub, &dummy, NULL, NORMAL_SOCKET, success, NULL);
/* Should not exit! */
abort();

View file

@ -342,7 +342,10 @@ int main(int argc, char *argv[])
opt_usage_exit_fail("Don't support proxy use");
case ADDR_INTERNAL_WIREADDR:
switch (addr.u.wireaddr.type) {
if (addr.u.wireaddr.is_websocket)
opt_usage_exit_fail("Don't support websocket use");
switch (addr.u.wireaddr.wireaddr.type) {
case ADDR_TYPE_TOR_V2_REMOVED:
case ADDR_TYPE_TOR_V3:
opt_usage_exit_fail("Don't support proxy use");
@ -357,7 +360,7 @@ int main(int argc, char *argv[])
af = AF_INET6;
break;
}
ai = wireaddr_to_addrinfo(tmpctx, &addr.u.wireaddr);
ai = wireaddr_to_addrinfo(tmpctx, &addr.u.wireaddr.wireaddr);
}
if (af == -1 || ai == NULL)

View file

@ -53,10 +53,17 @@ On success, an object is returned, containing:
- **channel** (hex): negotiated channel features we (as channel initiator) publish in the channel\_announcement message
- **invoice** (hex): features in our BOLT11 invoices
- **binding** (array of objects, optional): The addresses we are listening on:
- **type** (string): Type of connection (one of "local socket", "ipv4", "ipv6", "torv2", "torv3")
- **type** (string): Type of connection (one of "local socket", "websocket", "ipv4", "ipv6", "torv2", "torv3")
- **address** (string, optional): address in expected format for **type**
- **port** (u16, optional): port number
- **socket** (string, optional): socket filename (only if **type** is "local socket")
If **type** is "local socket":
- **socket** (string): socket filename
If **type** is "websocket":
- **subtype** (string): type of address
The following warnings may also be returned:
@ -132,4 +139,4 @@ RESOURCES
Main web site: <https://github.com/ElementsProject/lightning>
[comment]: # ( SHA256STAMP:60310adb57a49cb425a4b0d424f176a0ffa4de312ed07855b5e5611a44a64fcf)
[comment]: # ( SHA256STAMP:0e6f06ba4f0f0264614d93d4eb7abc38eeb13c9619f7bd4e21203cdaba363a02)

View file

@ -100,4 +100,4 @@ RESOURCES
Main web site: <https://github.com/ElementsProject/lightning>
[comment]: # ( SHA256STAMP:f7177be7c118fecf2e701d45140ad2714a42b746871caa8cd89e42bdc466d21c)
[comment]: # ( SHA256STAMP:d74d92ee8839258837055e65823f74cae9775cf1c111565366c034c62e1c3021)

View file

@ -176,13 +176,13 @@
"required": [
"type"
],
"additionalProperties": false,
"properties": {
"type": {
"type": "string",
"*FIXME*": "The variant in connect.schema.json is more complete",
"enum": [
"local socket",
"websocket",
"ipv4",
"ipv6",
"torv2",
@ -197,12 +197,92 @@
"port": {
"type": "u16",
"description": "port number"
},
"socket": {
"type": "string",
"description": "socket filename (only if **type** is \"local socket\")"
}
}
},
"allOf": [
{
"if": {
"properties": {
"type": {
"type": "string",
"enum": [
"local socket"
]
}
}
},
"then": {
"additionalProperties": false,
"required": [
"type",
"socket"
],
"properties": {
"type": {},
"socket": {
"type": "string",
"description": "socket filename"
}
}
},
"else": {
"additionalProperties": false,
"required": [
"type",
"address",
"port"
],
"properties": {
"type": {},
"address": {},
"port": {},
"subtype": {}
}
}
},
{
"if": {
"properties": {
"type": {
"type": "string",
"enum": [
"websocket"
]
}
}
},
"then": {
"additionalProperties": false,
"required": [
"type",
"address",
"port",
"subtype"
],
"properties": {
"type": {},
"address": {},
"port": {},
"subtype": {
"type": "string",
"description": "type of address"
}
}
},
"else": {
"additionalProperties": false,
"required": [
"type"
],
"properties": {
"type": {},
"address": {},
"port": {},
"socket": {}
}
}
}
]
}
},
"warning_bitcoind_sync": {

View file

@ -80,7 +80,7 @@
"torv2",
"torv3"
],
"description": "Type of connection (until 23.08, `websocket` was also allowed)"
"description": "Type of connection (until 23.08, `websocket` was also allowed)"
},
"port": {
"type": "u16",

View file

@ -417,7 +417,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid,
channel->scb = tal(channel, struct scb_chan);
channel->scb->id = dbid;
channel->scb->unused = 0;
channel->scb->addr = peer->addr.u.wireaddr;
channel->scb->addr = peer->addr.u.wireaddr.wireaddr;
channel->scb->node_id = peer->id;
channel->scb->funding = *funding;
channel->scb->cid = *cid;

View file

@ -680,7 +680,8 @@ int connectd_init(struct lightningd *ld)
wireaddrs = tal_arrz(tmpctx, struct wireaddr_internal, 1);
listen_announce = tal_arr(tmpctx, enum addr_listen_announce, 1);
wireaddrs->itype = ADDR_INTERNAL_ALLPROTO;
wireaddrs->u.port = ld->portnum;
wireaddrs->u.allproto.is_websocket = false;
wireaddrs->u.allproto.port = ld->portnum;
*listen_announce = ADDR_LISTEN_AND_ANNOUNCE;
}

View file

@ -1265,7 +1265,7 @@ wallet_commit_channel(struct lightningd *ld,
channel->scb = tal(channel, struct scb_chan);
channel->scb->id = channel->dbid;
channel->scb->unused = 0;
channel->scb->addr = channel->peer->addr.u.wireaddr;
channel->scb->addr = channel->peer->addr.u.wireaddr.wireaddr;
channel->scb->node_id = channel->peer->id;
channel->scb->funding = *funding;
channel->scb->cid = channel->cid;

View file

@ -1345,7 +1345,8 @@ static struct channel *stub_chan(struct command *cmd,
struct wireaddr_internal wint;
wint.itype = ADDR_INTERNAL_WIREADDR;
wint.u.wireaddr = addr;
wint.u.wireaddr.is_websocket = false;
wint.u.wireaddr.wireaddr = addr;
peer = new_peer(cmd->ld,
0,
&nodeid,

View file

@ -231,7 +231,7 @@ static size_t num_announced_types(enum wire_addr_type type, struct lightningd *l
for (size_t i = 0; i < tal_count(ld->proposed_wireaddr); i++) {
if (ld->proposed_wireaddr[i].itype != ADDR_INTERNAL_WIREADDR)
continue;
if (ld->proposed_wireaddr[i].u.wireaddr.type != type)
if (ld->proposed_wireaddr[i].u.wireaddr.wireaddr.type != type)
continue;
if (ld->proposed_listen_announce[i] & ADDR_ANNOUNCE)
num++;
@ -268,7 +268,7 @@ static char *opt_add_addr_withtype(const char *arg,
/* Check they didn't specify some weird type! */
switch (wi.itype) {
case ADDR_INTERNAL_WIREADDR:
switch (wi.u.wireaddr.type) {
switch (wi.u.wireaddr.wireaddr.type) {
case ADDR_TYPE_IPV4:
case ADDR_TYPE_IPV6:
/* These can be either bind or announce */