mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-24 01:24:26 +01:00
peer: keep addresses separately from peers.
This makes more sense eventually: we may know the network addresses of many peers, not just those we're connecting to. So keep a mapping, and update it when we successfully connect outwards. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
108
daemon/db.c
108
daemon/db.c
@@ -203,48 +203,6 @@ void db_add_wallet_privkey(struct lightningd_state *dstate,
|
||||
fatal("db_add_wallet_privkey:%s", err);
|
||||
}
|
||||
|
||||
static void load_peer_address(struct peer *peer)
|
||||
{
|
||||
int err;
|
||||
sqlite3_stmt *stmt;
|
||||
sqlite3 *sql = peer->dstate->db->sql;
|
||||
char *ctx = tal(peer, char);
|
||||
const char *select;
|
||||
bool addr_set = false;
|
||||
|
||||
select = tal_fmt(ctx,
|
||||
"SELECT * FROM peer_address WHERE peer = x'%s';",
|
||||
pubkey_to_hexstr(ctx, peer->dstate->secpctx, peer->id));
|
||||
|
||||
err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL);
|
||||
if (err != SQLITE_OK)
|
||||
fatal("load_peer_address:prepare gave %s:%s",
|
||||
sqlite3_errstr(err), sqlite3_errmsg(sql));
|
||||
|
||||
while ((err = sqlite3_step(stmt)) != SQLITE_DONE) {
|
||||
if (err != SQLITE_ROW)
|
||||
fatal("load_peer_address:step gave %s:%s",
|
||||
sqlite3_errstr(err), sqlite3_errmsg(sql));
|
||||
if (addr_set)
|
||||
fatal("load_peer_address: two addresses for '%s'",
|
||||
select);
|
||||
if (!netaddr_from_blob(sqlite3_column_blob(stmt, 1),
|
||||
sqlite3_column_bytes(stmt, 1),
|
||||
&peer->addr))
|
||||
fatal("load_peer_address: unparsable addresses for '%s'",
|
||||
select);
|
||||
addr_set = true;
|
||||
peer->log = new_log(peer, peer->dstate->log_record, "%s%s:",
|
||||
log_prefix(peer->dstate->base_log),
|
||||
netaddr_name(peer, &peer->addr));
|
||||
}
|
||||
|
||||
if (!addr_set)
|
||||
fatal("load_peer_address: no addresses for '%s'", select);
|
||||
|
||||
tal_free(ctx);
|
||||
}
|
||||
|
||||
static void load_peer_secrets(struct peer *peer)
|
||||
{
|
||||
int err;
|
||||
@@ -928,7 +886,6 @@ static void db_load_peers(struct lightningd_state *dstate)
|
||||
sqlite3_errmsg(dstate->db->sql));
|
||||
|
||||
list_for_each(&dstate->peers, peer, list) {
|
||||
load_peer_address(peer);
|
||||
load_peer_secrets(peer);
|
||||
load_peer_closing(peer);
|
||||
peer->anchor.min_depth = 0;
|
||||
@@ -946,10 +903,45 @@ static void db_load_peers(struct lightningd_state *dstate)
|
||||
connect_htlc_src(dstate);
|
||||
}
|
||||
|
||||
static void db_load_addresses(struct lightningd_state *dstate)
|
||||
{
|
||||
int err;
|
||||
sqlite3_stmt *stmt;
|
||||
sqlite3 *sql = dstate->db->sql;
|
||||
char *ctx = tal(dstate, char);
|
||||
const char *select;
|
||||
|
||||
select = tal_fmt(ctx, "SELECT * FROM peer_address;");
|
||||
|
||||
err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL);
|
||||
if (err != SQLITE_OK)
|
||||
fatal("load_peer_addresses:prepare gave %s:%s",
|
||||
sqlite3_errstr(err), sqlite3_errmsg(sql));
|
||||
|
||||
while ((err = sqlite3_step(stmt)) != SQLITE_DONE) {
|
||||
struct peer_address *addr;
|
||||
|
||||
if (err != SQLITE_ROW)
|
||||
fatal("load_peer_addresses:step gave %s:%s",
|
||||
sqlite3_errstr(err), sqlite3_errmsg(sql));
|
||||
addr = tal(dstate, struct peer_address);
|
||||
pubkey_from_sql(dstate->secpctx, stmt, 0, &addr->id);
|
||||
if (!netaddr_from_blob(sqlite3_column_blob(stmt, 1),
|
||||
sqlite3_column_bytes(stmt, 1),
|
||||
&addr->addr))
|
||||
fatal("load_peer_addresses: unparsable addresses for '%s'",
|
||||
select);
|
||||
list_add_tail(&dstate->addresses, &addr->list);
|
||||
log_debug(dstate->base_log, "load_peer_addresses:%s",
|
||||
pubkey_to_hexstr(ctx, dstate->secpctx, &addr->id));
|
||||
}
|
||||
tal_free(ctx);
|
||||
}
|
||||
|
||||
static void db_load(struct lightningd_state *dstate)
|
||||
{
|
||||
db_load_wallet(dstate);
|
||||
|
||||
db_load_addresses(dstate);
|
||||
db_load_peers(dstate);
|
||||
}
|
||||
|
||||
@@ -1152,14 +1144,6 @@ bool db_create_peer(struct peer *peer)
|
||||
if (errmsg)
|
||||
goto out;
|
||||
|
||||
errmsg = db_exec(ctx, peer->dstate,
|
||||
"INSERT INTO peer_address VALUES (x'%s', x'%s');",
|
||||
peerid,
|
||||
netaddr_to_hex(ctx, &peer->addr));
|
||||
|
||||
if (errmsg)
|
||||
goto out;
|
||||
|
||||
if (!db_commit_transaction(peer))
|
||||
errmsg = "Commit failed";
|
||||
|
||||
@@ -1413,6 +1397,26 @@ bool db_add_commit_map(struct peer *peer,
|
||||
return !errmsg;
|
||||
}
|
||||
|
||||
/* FIXME: Clean out old ones! */
|
||||
bool db_add_peer_address(struct lightningd_state *dstate,
|
||||
const struct peer_address *addr)
|
||||
{
|
||||
const char *errmsg, *ctx = tal(dstate, char);
|
||||
|
||||
log_debug(dstate->base_log, "%s", __func__);
|
||||
|
||||
assert(!dstate->db->in_transaction);
|
||||
errmsg = db_exec(ctx, dstate,
|
||||
"INSERT OR REPLACE INTO peer_address VALUES (x'%s', x'%s');",
|
||||
pubkey_to_hexstr(ctx, dstate->secpctx, &addr->id),
|
||||
netaddr_to_hex(ctx, &addr->addr));
|
||||
|
||||
if (errmsg)
|
||||
log_broken(dstate->base_log, "%s:%s", __func__, errmsg);
|
||||
tal_free(ctx);
|
||||
return !errmsg;
|
||||
}
|
||||
|
||||
void db_forget_peer(struct peer *peer)
|
||||
{
|
||||
const char *ctx = tal(peer, char);
|
||||
|
||||
@@ -17,6 +17,9 @@ bool db_commit_transaction(struct peer *peer);
|
||||
void db_add_wallet_privkey(struct lightningd_state *dstate,
|
||||
const struct privkey *privkey);
|
||||
|
||||
bool db_add_peer_address(struct lightningd_state *dstate,
|
||||
const struct peer_address *addr);
|
||||
|
||||
/* Must NOT be inside transaction. */
|
||||
bool db_htlc_fulfilled(struct peer *peer, const struct htlc *htlc);
|
||||
bool db_set_our_closing_script(struct peer *peer);
|
||||
|
||||
@@ -251,6 +251,7 @@ static struct lightningd_state *lightningd_state(void)
|
||||
list_head_init(&dstate->bitcoin_req);
|
||||
list_head_init(&dstate->wallet);
|
||||
list_head_init(&dstate->payments);
|
||||
list_head_init(&dstate->addresses);
|
||||
dstate->dev_never_routefail = false;
|
||||
dstate->bitcoin_req_running = false;
|
||||
dstate->nodes = empty_node_map(dstate);
|
||||
|
||||
@@ -84,6 +84,9 @@ struct lightningd_state {
|
||||
/* Our peers. */
|
||||
struct list_head peers;
|
||||
|
||||
/* Addresses to contact peers. */
|
||||
struct list_head addresses;
|
||||
|
||||
/* Crypto tables for global use. */
|
||||
secp256k1_context *secpctx;
|
||||
|
||||
|
||||
@@ -77,3 +77,12 @@ bool netaddr_from_blob(const void *linear, size_t len, struct netaddr *a)
|
||||
pull(&p, &len, &a->saddr, a->addrlen);
|
||||
return p != NULL && len == 0;
|
||||
}
|
||||
|
||||
bool netaddr_from_fd(int fd, int type, int protocol, struct netaddr *a)
|
||||
{
|
||||
a->type = type;
|
||||
a->protocol = protocol;
|
||||
a->addrlen = sizeof(a->saddr);
|
||||
return getpeername(fd, &a->saddr.s, &a->addrlen) == 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@ char *netaddr_name(const tal_t *ctx, const struct netaddr *a);
|
||||
/* Create a addrinfo (as wanted by io_connect) for this address. */
|
||||
void netaddr_to_addrinfo(struct addrinfo *ai, const struct netaddr *a);
|
||||
|
||||
bool netaddr_from_fd(int fd, int type, int protocol, struct netaddr *a);
|
||||
|
||||
bool netaddr_from_blob(const void *linear, size_t len, struct netaddr *a);
|
||||
char *netaddr_to_hex(const tal_t *ctx, const struct netaddr *a);
|
||||
|
||||
|
||||
124
daemon/peer.c
124
daemon/peer.c
@@ -2101,21 +2101,6 @@ struct commit_info *new_commit_info(const tal_t *ctx, u64 commit_num)
|
||||
return ci;
|
||||
}
|
||||
|
||||
static bool peer_getaddr(struct peer *peer,
|
||||
int fd, int addr_type, int addr_protocol)
|
||||
{
|
||||
peer->addr.type = addr_type;
|
||||
peer->addr.protocol = addr_protocol;
|
||||
peer->addr.addrlen = sizeof(peer->addr.saddr);
|
||||
if (getpeername(fd, &peer->addr.saddr.s, &peer->addr.addrlen) != 0) {
|
||||
log_broken(peer->dstate->base_log,
|
||||
"Could not get address for peer: %s",
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool peer_reconnected(struct peer *peer,
|
||||
struct io_conn *conn,
|
||||
int addr_type, int addr_protocol,
|
||||
@@ -2123,13 +2108,15 @@ static bool peer_reconnected(struct peer *peer,
|
||||
const struct pubkey *id,
|
||||
bool we_connected)
|
||||
{
|
||||
char *prefix;
|
||||
char *name;
|
||||
struct netaddr addr;
|
||||
|
||||
assert(structeq(peer->id, id));
|
||||
|
||||
peer->io_data = tal_steal(peer, iod);
|
||||
|
||||
/* FIXME: Attach IO logging for this peer. */
|
||||
if (!peer_getaddr(peer, io_conn_fd(conn), addr_type, addr_protocol))
|
||||
if (!netaddr_from_fd(io_conn_fd(conn), addr_type, addr_protocol, &addr))
|
||||
return false;
|
||||
|
||||
/* If we free peer, conn should be closed, but can't be freed
|
||||
@@ -2137,18 +2124,10 @@ static bool peer_reconnected(struct peer *peer,
|
||||
peer->conn = conn;
|
||||
io_set_finish(conn, peer_disconnect, peer);
|
||||
|
||||
prefix = tal_fmt(peer, "%s%s:%s:",
|
||||
log_prefix(peer->dstate->base_log),
|
||||
we_connected ? "out" : "in",
|
||||
netaddr_name(peer, &peer->addr));
|
||||
if (peer->log) {
|
||||
log_info(peer->log, "Reconnected as %s", prefix);
|
||||
set_log_prefix(peer->log, prefix);
|
||||
} else {
|
||||
peer->log = new_log(peer, peer->dstate->log_record,
|
||||
"%s", prefix);
|
||||
}
|
||||
tal_free(prefix);
|
||||
name = netaddr_name(peer, &addr);
|
||||
log_info(peer->log, "Reconnected %s %s",
|
||||
we_connected ? "out to" : "in from", name);
|
||||
tal_free(name);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -2202,6 +2181,8 @@ struct peer *new_peer(struct lightningd_state *dstate,
|
||||
peer->local.mindepth = dstate->config.anchor_confirms;
|
||||
peer->local.commit = peer->remote.commit = NULL;
|
||||
peer->local.staging_cstate = peer->remote.staging_cstate = NULL;
|
||||
peer->log = new_log(peer, peer->dstate->log_record, "%s:peer %p:",
|
||||
log_prefix(peer->dstate->base_log), peer);
|
||||
|
||||
htlc_map_init(&peer->htlcs);
|
||||
shachain_init(&peer->their_preimages);
|
||||
@@ -2211,6 +2192,34 @@ struct peer *new_peer(struct lightningd_state *dstate,
|
||||
return peer;
|
||||
}
|
||||
|
||||
static struct peer_address *find_address(struct lightningd_state *dstate,
|
||||
const struct pubkey *id)
|
||||
{
|
||||
struct peer_address *i;
|
||||
|
||||
list_for_each(&dstate->addresses, i, list) {
|
||||
if (structeq(&id->pubkey, &i->id.pubkey))
|
||||
return i;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool add_peer_address(struct lightningd_state *dstate,
|
||||
const struct pubkey *id,
|
||||
const struct netaddr *addr)
|
||||
{
|
||||
struct peer_address *a = find_address(dstate, id);
|
||||
if (a) {
|
||||
a->addr = *addr;
|
||||
} else {
|
||||
a = tal(dstate, struct peer_address);
|
||||
a->addr = *addr;
|
||||
a->id = *id;
|
||||
list_add_tail(&dstate->addresses, &a->list);
|
||||
}
|
||||
return db_add_peer_address(dstate, a);
|
||||
}
|
||||
|
||||
static bool peer_first_connected(struct peer *peer,
|
||||
struct io_conn *conn,
|
||||
int addr_type, int addr_protocol,
|
||||
@@ -2218,6 +2227,9 @@ static bool peer_first_connected(struct peer *peer,
|
||||
const struct pubkey *id,
|
||||
bool we_connected)
|
||||
{
|
||||
char *name;
|
||||
struct netaddr addr;
|
||||
|
||||
peer->io_data = tal_steal(peer, iod);
|
||||
peer->id = tal_dup(peer, struct pubkey, id);
|
||||
/* FIXME: Make this dynamic! */
|
||||
@@ -2234,28 +2246,25 @@ static bool peer_first_connected(struct peer *peer,
|
||||
peer->conn = conn;
|
||||
io_set_finish(conn, peer_disconnect, peer);
|
||||
|
||||
/* FIXME: Attach IO logging for this peer. */
|
||||
|
||||
peer->addr.type = addr_type;
|
||||
peer->addr.protocol = addr_protocol;
|
||||
peer->addr.addrlen = sizeof(peer->addr.saddr);
|
||||
if (getpeername(io_conn_fd(conn), &peer->addr.saddr.s,
|
||||
&peer->addr.addrlen) != 0) {
|
||||
log_unusual(peer->dstate->base_log,
|
||||
"Could not get address for peer: %s",
|
||||
strerror(errno));
|
||||
return tal_free(peer);
|
||||
}
|
||||
peer->anchor.min_depth = get_block_height(peer->dstate);
|
||||
|
||||
peer->log = new_log(peer, peer->dstate->log_record, "%s%s:%s:",
|
||||
log_prefix(peer->dstate->base_log),
|
||||
we_connected ? "out" : "in",
|
||||
netaddr_name(peer, &peer->addr));
|
||||
/* FIXME: Attach IO logging for this peer. */
|
||||
if (!netaddr_from_fd(io_conn_fd(conn), addr_type, addr_protocol, &addr))
|
||||
return false;
|
||||
|
||||
/* Save/update address if we connected to them. */
|
||||
if (we_connected && !add_peer_address(peer->dstate, peer->id, &addr))
|
||||
return false;
|
||||
|
||||
name = netaddr_name(peer, &addr);
|
||||
log_info(peer->log, "Connected %s %s id %s",
|
||||
we_connected ? "out to" : "in from", name,
|
||||
pubkey_to_hexstr(name, peer->dstate->secpctx, peer->id));
|
||||
tal_free(name);
|
||||
|
||||
log_debug(peer->log, "Using fee rate %"PRIu64,
|
||||
peer->local.commit_fee_rate);
|
||||
return peer;
|
||||
return true;
|
||||
}
|
||||
|
||||
static u64 peer_commitsigs_received(struct peer *peer)
|
||||
@@ -2372,8 +2381,8 @@ static struct io_plan *crypto_on_reconnect(struct io_conn *conn,
|
||||
u64 sigs, revokes, shutdown, closing;
|
||||
|
||||
/* Setup peer->conn and peer->io_data */
|
||||
if (!peer_reconnected(peer, conn, peer->addr.type,
|
||||
peer->addr.protocol, iod, id, we_connected))
|
||||
if (!peer_reconnected(peer, conn, SOCK_STREAM, IPPROTO_TCP,
|
||||
iod, id, we_connected))
|
||||
return io_close(conn);
|
||||
|
||||
sigs = peer_commitsigs_received(peer);
|
||||
@@ -3849,14 +3858,17 @@ static void reconnect_failed(struct io_conn *conn, struct peer *peer)
|
||||
static struct io_plan *init_conn(struct io_conn *conn, struct peer *peer)
|
||||
{
|
||||
struct addrinfo a;
|
||||
struct peer_address *addr = find_address(peer->dstate, peer->id);
|
||||
|
||||
netaddr_to_addrinfo(&a, &peer->addr);
|
||||
netaddr_to_addrinfo(&a, &addr->addr);
|
||||
return io_connect(conn, &a, peer_reconnect, peer);
|
||||
}
|
||||
|
||||
static void try_reconnect(struct peer *peer)
|
||||
{
|
||||
struct io_conn *conn;
|
||||
struct peer_address *addr;
|
||||
char *name;
|
||||
int fd;
|
||||
|
||||
/* Already reconnected? */
|
||||
@@ -3865,8 +3877,14 @@ static void try_reconnect(struct peer *peer)
|
||||
return;
|
||||
}
|
||||
|
||||
fd = socket(peer->addr.saddr.s.sa_family, peer->addr.type,
|
||||
peer->addr.protocol);
|
||||
addr = find_address(peer->dstate, peer->id);
|
||||
if (!addr) {
|
||||
log_debug(peer->log, "try_reconnect: no known address");
|
||||
return;
|
||||
}
|
||||
|
||||
fd = socket(addr->addr.saddr.s.sa_family, addr->addr.type,
|
||||
addr->addr.protocol);
|
||||
if (fd < 0) {
|
||||
log_broken(peer->log, "do_reconnect: failed to create socket: %s",
|
||||
strerror(errno));
|
||||
@@ -3877,7 +3895,9 @@ static void try_reconnect(struct peer *peer)
|
||||
|
||||
assert(!peer->conn);
|
||||
conn = io_new_conn(peer->dstate, fd, init_conn, peer);
|
||||
log_debug(peer->log, "Trying to reconnect...");
|
||||
name = netaddr_name(peer, &addr->addr);
|
||||
log_debug(peer->log, "Trying to reconnect to %s", name);
|
||||
tal_free(name);
|
||||
io_set_finish(conn, reconnect_failed, peer);
|
||||
}
|
||||
|
||||
|
||||
@@ -103,9 +103,6 @@ struct peer {
|
||||
/* Global state. */
|
||||
struct lightningd_state *dstate;
|
||||
|
||||
/* The other end's address. */
|
||||
struct netaddr addr;
|
||||
|
||||
/* Their ID. */
|
||||
struct pubkey *id;
|
||||
|
||||
@@ -228,6 +225,13 @@ struct peer {
|
||||
struct shachain their_preimages;
|
||||
};
|
||||
|
||||
/* Mapping for id -> network address. */
|
||||
struct peer_address {
|
||||
struct list_node list;
|
||||
struct pubkey id;
|
||||
struct netaddr addr;
|
||||
};
|
||||
|
||||
void setup_listeners(struct lightningd_state *dstate, unsigned int portnum);
|
||||
|
||||
struct peer *find_peer(struct lightningd_state *dstate, const struct pubkey *id);
|
||||
|
||||
Reference in New Issue
Block a user