connectd: implement connection timeout (60 seconds).

This is simple, and we now can multifundchannel to every node on testnet
(one simply hangs once we connect).

Changelog-Fixed: Protocol: We now hang up if peer doesn't respond to init message after 60 seconds.
This commit is contained in:
Rusty Russell 2020-09-11 16:18:12 +09:30
parent 1deba1c8e4
commit 7f2b332021
7 changed files with 47 additions and 10 deletions

View File

@ -24,6 +24,7 @@
#include <ccan/str/str.h>
#include <ccan/take/take.h>
#include <ccan/tal/str/str.h>
#include <ccan/timer/timer.h>
#include <common/bech32.h>
#include <common/bech32_util.h>
#include <common/cryptomsg.h>
@ -38,6 +39,7 @@
#include <common/pseudorand.h>
#include <common/status.h>
#include <common/subdaemon.h>
#include <common/timeout.h>
#include <common/type_to_string.h>
#include <common/utils.h>
#include <common/version.h>
@ -121,6 +123,10 @@ struct daemon {
/* pubkey equivalent. */
struct pubkey mykey;
/* Base for timeout timers, and how long to wait for init msg */
struct timers timers;
u32 timeout_secs;
/* Peers that we've handed to `lightningd`, which it hasn't told us
* have disconnected. */
struct node_set peers;
@ -509,6 +515,12 @@ static struct io_plan *handshake_in_success(struct io_conn *conn,
cs, &id, addr);
}
/*~ If the timer goes off, we simply free everything, which hangs up. */
static void conn_timeout(struct io_conn *conn)
{
tal_free(conn);
}
/*~ When we get a connection in we set up its network address then call
* handshake.c to set up the crypto state. */
static struct io_plan *connection_in(struct io_conn *conn, struct daemon *daemon)
@ -544,7 +556,11 @@ static struct io_plan *connection_in(struct io_conn *conn, struct daemon *daemon
return io_close(conn);
}
/* FIXME: Timeout */
/* If they don't complete handshake in reasonable time, hang up */
notleak(new_reltimer(&daemon->timers, conn,
time_from_sec(daemon->timeout_secs),
conn_timeout, conn));
/*~ The crypto handshake differs depending on whether you received or
* initiated the socket connection, so there are two entry points.
* Note, again, the notleak() to avoid our simplistic leak detection
@ -583,7 +599,10 @@ struct io_plan *connection_out(struct io_conn *conn, struct connecting *connect)
return io_close(conn);
}
/* FIXME: Timeout */
/* If they don't complete handshake in reasonable time, hang up */
notleak(new_reltimer(&connect->daemon->timers, conn,
time_from_sec(connect->daemon->timeout_secs),
conn_timeout, conn));
status_peer_debug(&connect->id, "Connected out, starting crypto");
connect->connstate = "Cryptographic handshake";
@ -1243,7 +1262,8 @@ static struct io_plan *connect_init(struct io_conn *conn,
&proxyaddr, &daemon->use_proxy_always,
&daemon->dev_allow_localhost, &daemon->use_dns,
&tor_password,
&daemon->use_v3_autotor)) {
&daemon->use_v3_autotor,
&daemon->timeout_secs)) {
/* This is a helper which prints the type expected and the actual
* message, then exits (it should never be called!). */
master_badmsg(WIRE_CONNECTD_INIT, msg);
@ -1638,6 +1658,7 @@ int main(int argc, char *argv[])
memleak_add_helper(daemon, memleak_daemon_cb);
list_head_init(&daemon->connecting);
daemon->listen_fds = tal_arr(daemon, struct listen_fd, 0);
timers_init(&daemon->timers, time_mono());
/* stdin == control */
daemon->master = daemon_conn_new(daemon, STDIN_FILENO, recv_req, NULL,
daemon);

View File

@ -17,6 +17,7 @@ msgdata,connectd_init,dev_allow_localhost,bool,
msgdata,connectd_init,use_dns,bool,
msgdata,connectd_init,tor_password,wirestring,
msgdata,connectd_init,use_v3_autotor,bool,
msgdata,connectd_init,timeout_secs,u32,
# Connectd->master, here are the addresses I bound, can announce.
msgtype,connectd_init_reply,2100

1 #include <common/cryptomsg.h>
17 msgdata,connectd_init,tor_password,wirestring,
18 msgdata,connectd_init,use_v3_autotor,bool,
19 # Connectd->master, here are the addresses I bound, can announce. msgdata,connectd_init,timeout_secs,u32,
20 # Connectd->master, here are the addresses I bound, can announce.
21 msgtype,connectd_init_reply,2100
22 msgdata,connectd_init_reply,num_bindings,u16,
23 msgdata,connectd_init_reply,bindings,wireaddr_internal,num_bindings

View File

@ -61,7 +61,7 @@ bool connectd_wire_is_defined(u16 type)
/* WIRE: CONNECTD_INIT */
u8 *towire_connectd_init(const tal_t *ctx, const struct chainparams *chainparams, const struct feature_set *our_features, const struct node_id *id, const struct wireaddr_internal *wireaddrs, const enum addr_listen_announce *listen_announce, const struct wireaddr *tor_proxyaddr, bool use_tor_proxy_always, bool dev_allow_localhost, bool use_dns, const wirestring *tor_password, bool use_v3_autotor)
u8 *towire_connectd_init(const tal_t *ctx, const struct chainparams *chainparams, const struct feature_set *our_features, const struct node_id *id, const struct wireaddr_internal *wireaddrs, const enum addr_listen_announce *listen_announce, const struct wireaddr *tor_proxyaddr, bool use_tor_proxy_always, bool dev_allow_localhost, bool use_dns, const wirestring *tor_password, bool use_v3_autotor, u32 timeout_secs)
{
u16 num_wireaddrs = tal_count(listen_announce);
u8 *p = tal_arr(ctx, u8, 0);
@ -86,10 +86,11 @@ u8 *towire_connectd_init(const tal_t *ctx, const struct chainparams *chainparams
towire_bool(&p, use_dns);
towire_wirestring(&p, tor_password);
towire_bool(&p, use_v3_autotor);
towire_u32(&p, timeout_secs);
return memcheck(p, tal_count(p));
}
bool fromwire_connectd_init(const tal_t *ctx, const void *p, const struct chainparams **chainparams, struct feature_set **our_features, struct node_id *id, struct wireaddr_internal **wireaddrs, enum addr_listen_announce **listen_announce, struct wireaddr **tor_proxyaddr, bool *use_tor_proxy_always, bool *dev_allow_localhost, bool *use_dns, wirestring **tor_password, bool *use_v3_autotor)
bool fromwire_connectd_init(const tal_t *ctx, const void *p, const struct chainparams **chainparams, struct feature_set **our_features, struct node_id *id, struct wireaddr_internal **wireaddrs, enum addr_listen_announce **listen_announce, struct wireaddr **tor_proxyaddr, bool *use_tor_proxy_always, bool *dev_allow_localhost, bool *use_dns, wirestring **tor_password, bool *use_v3_autotor, u32 *timeout_secs)
{
u16 num_wireaddrs;
@ -121,6 +122,7 @@ bool fromwire_connectd_init(const tal_t *ctx, const void *p, const struct chainp
*use_dns = fromwire_bool(&cursor, &plen);
*tor_password = fromwire_wirestring(ctx, &cursor, &plen);
*use_v3_autotor = fromwire_bool(&cursor, &plen);
*timeout_secs = fromwire_u32(&cursor, &plen);
return cursor != NULL;
}
@ -404,4 +406,4 @@ bool fromwire_connectd_dev_memleak_reply(const void *p, bool *leak)
*leak = fromwire_bool(&cursor, &plen);
return cursor != NULL;
}
// SHA256STAMP:ae6ae82d79526abc039896e90f677549a6acb73c0a2cd171f6658849025318b5
// SHA256STAMP:48e50860685655b8ae8e12dd3f07d1c1cceea48934fe3846c7d276d93c70b211

View File

@ -49,8 +49,8 @@ bool connectd_wire_is_defined(u16 type);
/* WIRE: CONNECTD_INIT */
u8 *towire_connectd_init(const tal_t *ctx, const struct chainparams *chainparams, const struct feature_set *our_features, const struct node_id *id, const struct wireaddr_internal *wireaddrs, const enum addr_listen_announce *listen_announce, const struct wireaddr *tor_proxyaddr, bool use_tor_proxy_always, bool dev_allow_localhost, bool use_dns, const wirestring *tor_password, bool use_v3_autotor);
bool fromwire_connectd_init(const tal_t *ctx, const void *p, const struct chainparams **chainparams, struct feature_set **our_features, struct node_id *id, struct wireaddr_internal **wireaddrs, enum addr_listen_announce **listen_announce, struct wireaddr **tor_proxyaddr, bool *use_tor_proxy_always, bool *dev_allow_localhost, bool *use_dns, wirestring **tor_password, bool *use_v3_autotor);
u8 *towire_connectd_init(const tal_t *ctx, const struct chainparams *chainparams, const struct feature_set *our_features, const struct node_id *id, const struct wireaddr_internal *wireaddrs, const enum addr_listen_announce *listen_announce, const struct wireaddr *tor_proxyaddr, bool use_tor_proxy_always, bool dev_allow_localhost, bool use_dns, const wirestring *tor_password, bool use_v3_autotor, u32 timeout_secs);
bool fromwire_connectd_init(const tal_t *ctx, const void *p, const struct chainparams **chainparams, struct feature_set **our_features, struct node_id *id, struct wireaddr_internal **wireaddrs, enum addr_listen_announce **listen_announce, struct wireaddr **tor_proxyaddr, bool *use_tor_proxy_always, bool *dev_allow_localhost, bool *use_dns, wirestring **tor_password, bool *use_v3_autotor, u32 *timeout_secs);
/* WIRE: CONNECTD_INIT_REPLY */
/* Connectd->master */
@ -103,4 +103,4 @@ bool fromwire_connectd_dev_memleak_reply(const void *p, bool *leak);
#endif /* LIGHTNING_CONNECTD_CONNECTD_WIREGEN_H */
// SHA256STAMP:ae6ae82d79526abc039896e90f677549a6acb73c0a2cd171f6658849025318b5
// SHA256STAMP:48e50860685655b8ae8e12dd3f07d1c1cceea48934fe3846c7d276d93c70b211

View File

@ -371,7 +371,8 @@ int connectd_init(struct lightningd *ld)
ld->proxyaddr, ld->use_proxy_always || ld->pure_tor_setup,
IFDEV(ld->dev_allow_localhost, false), ld->config.use_dns,
ld->tor_service_password ? ld->tor_service_password : "",
ld->config.use_v3_autotor);
ld->config.use_v3_autotor,
ld->config.connection_timeout_secs);
subd_req(ld->connectd, ld->connectd, take(msg), -1, 0,
connect_init_done, NULL);

View File

@ -69,6 +69,9 @@ struct config {
/* This is the key we use to encrypt `hsm_secret`. */
struct secret *keypass;
/* How long before we give up waiting for INIT msg */
u32 connection_timeout_secs;
};
typedef STRMAP(const char *) alt_subdaemon_map;

View File

@ -593,6 +593,9 @@ static void dev_register_opts(struct lightningd *ld)
"Make builtin plugins unimportant so you can plugin stop them.");
opt_register_arg("--dev-force-features", opt_force_featureset, NULL, ld,
"Force the init/globalinit/node_announce/channel/bolt11 features, each comma-separated bitnumbers");
opt_register_arg("--dev-timeout-secs", opt_set_u32, opt_show_u32,
&ld->config.connection_timeout_secs,
"Seconds to timeout if we don't receive INIT from peer");
}
#endif /* DEVELOPER */
@ -638,6 +641,9 @@ static const struct config testnet_config = {
.min_capacity_sat = 10000,
.use_v3_autotor = true,
/* 1 minute should be enough for anyone! */
.connection_timeout_secs = 60,
};
/* aka. "Dude, where's my coins?" */
@ -694,6 +700,9 @@ static const struct config mainnet_config = {
/* Allow to define the default behavior of tor services calls*/
.use_v3_autotor = true,
/* 1 minute should be enough for anyone! */
.connection_timeout_secs = 60,
};
static void check_config(struct lightningd *ld)