diff --git a/lightningd/Makefile b/lightningd/Makefile index b4a7ce316..aaa84876e 100644 --- a/lightningd/Makefile +++ b/lightningd/Makefile @@ -15,6 +15,7 @@ LIGHTNINGD_OLD_SRC := \ daemon/json.c \ daemon/jsonrpc.c \ daemon/log.c \ + daemon/netaddr.c \ daemon/options.c \ daemon/opt_time.c \ daemon/pseudorand.c \ diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index 3b9d8c79b..18063cd98 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -32,9 +32,11 @@ static void peer_bad_message(struct subdaemon *gossip, const u8 *msg) if (!peer) fatal("Gossip gave bad peerid %"PRIu64, unique_id); - log_info(gossip->log, "Peer %s gave bad msg %s", - type_to_string(msg, struct pubkey, peer->id), - tal_hex(msg, msg)); + log_debug(gossip->log, "Peer %s gave bad msg %s", + type_to_string(msg, struct pubkey, peer->id), + tal_hex(msg, msg)); + peer_set_condition(peer, "Bad message %s during gossip phase", + gossip_status_wire_type_name(fromwire_peektype(msg))); tal_free(peer); } @@ -54,9 +56,11 @@ static void peer_nongossip(struct subdaemon *gossip, const u8 *msg, int fd) if (!peer) fatal("Gossip gave bad peerid %"PRIu64, unique_id); - log_info(gossip->log, "Peer %s said %s", - type_to_string(msg, struct pubkey, peer->id), - gossip_status_wire_type_name(fromwire_peektype(inner))); + log_debug(gossip->log, "Peer %s said %s", + type_to_string(msg, struct pubkey, peer->id), + gossip_status_wire_type_name(fromwire_peektype(inner))); + peer_set_condition(peer, "Gossip ended up receipt of %s", + gossip_status_wire_type_name(fromwire_peektype(inner))); /* FIXME: create new daemon to handle peer. */ } @@ -74,8 +78,8 @@ static void peer_ready(struct subdaemon *gossip, const u8 *msg) if (!peer) fatal("Gossip gave bad peerid %"PRIu64, unique_id); - log_info_struct(gossip->log, "Peer %s ready for channel open", - struct pubkey, peer->id); + log_debug_struct(gossip->log, "Peer %s ready for channel open", + struct pubkey, peer->id); if (peer->connect_cmd) { struct json_result *response; @@ -87,6 +91,8 @@ static void peer_ready(struct subdaemon *gossip, const u8 *msg) command_success(peer->connect_cmd, response); peer->connect_cmd = NULL; } + + peer_set_condition(peer, "Exchanging gossip"); } static enum subdaemon_status gossip_status(struct subdaemon *gossip, diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 308a887a4..56a7a3162 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -24,21 +24,46 @@ static void destroy_peer(struct peer *peer) if (peer->fd >= 0) close(peer->fd); if (peer->connect_cmd) - /* FIXME: Better diagnostics */ - command_fail(peer->connect_cmd, "Connect failed"); + command_fail(peer->connect_cmd, "Failed after %s", + peer->condition); } -static struct peer *new_peer(const tal_t *ctx, struct lightningd *ld, int fd, +void peer_set_condition(struct peer *peer, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + tal_free(peer->condition); + peer->condition = tal_vfmt(peer, fmt, ap); + va_end(ap); +} + +static struct peer *new_peer(struct lightningd *ld, + struct io_conn *conn, + const char *in_or_out, struct command *cmd) { static u64 id_counter; - struct peer *peer = tal(ctx, struct peer); + struct peer *peer = tal(ld, struct peer); + const char *netname; + peer->ld = ld; peer->unique_id = id_counter++; peer->owner = NULL; peer->id = NULL; - peer->fd = fd; + peer->fd = io_conn_fd(conn); peer->connect_cmd = cmd; + + /* FIXME: Don't assume protocol here! */ + if (!netaddr_from_fd(peer->fd, SOCK_STREAM, IPPROTO_TCP, + &peer->netaddr)) { + log_unusual(ld->log, "Failed to get netaddr for outgoing: %s", + strerror(errno)); + return tal_free(peer); + } + netname = netaddr_name(peer, &peer->netaddr); + peer->condition = tal_fmt(peer, "%s %s", in_or_out, netname); + tal_free(netname); list_add_tail(&ld->peers, &peer->list); tal_add_destructor(peer, destroy_peer); return peer; @@ -82,6 +107,7 @@ static void handshake_succeeded(struct subdaemon *hs, const u8 *msg, peer->owner = peer->ld->gossip; tal_steal(peer->owner, peer); + peer_set_condition(peer, "Beginning gossip"); /* Tell gossip to handle it now. */ msg = towire_gossipctl_new_peer(msg, peer->unique_id, cs); @@ -119,6 +145,7 @@ static void peer_got_hsmfd(struct subdaemon *hsm, const u8 *msg, if (!peer->owner) { log_unusual(peer->ld->log, "Could not subdaemon handshake: %s", strerror(errno)); + peer_set_condition(peer, "Failed to subdaemon handshake"); goto error; } @@ -126,11 +153,14 @@ static void peer_got_hsmfd(struct subdaemon *hsm, const u8 *msg, * when it does. */ tal_steal(peer->owner, peer); - if (peer->id) + if (peer->id) { req = towire_handshake_initiator_req(peer, &peer->ld->dstate.id, peer->id); - else + peer_set_condition(peer, "Starting handshake as initiator"); + } else { req = towire_handshake_responder_req(peer, &peer->ld->dstate.id); + peer_set_condition(peer, "Starting handshake as responder"); + } /* Now hand peer fd to the handshake daemon, it hand back on success */ subdaemon_req(peer->owner, take(req), @@ -148,7 +178,10 @@ error: /* FIXME: timeout handshake if taking too long? */ static struct io_plan *peer_in(struct io_conn *conn, struct lightningd *ld) { - struct peer *peer = new_peer(ld, ld, io_conn_fd(conn), NULL); + struct peer *peer = new_peer(ld, conn, "Incoming from", NULL); + + if (!peer) + return io_close(conn); /* Get HSM fd for this peer. */ subdaemon_req(ld->hsm, @@ -273,7 +306,10 @@ static struct io_plan *peer_out(struct io_conn *conn, struct json_connecting *jc) { struct lightningd *ld = ld_from_dstate(jc->cmd->dstate); - struct peer *peer = new_peer(ld, ld, io_conn_fd(conn), jc->cmd); + struct peer *peer = new_peer(ld, conn, "Outgoing to", jc->cmd); + + if (!peer) + return io_close(conn); /* We already know ID we're trying to reach. */ peer->id = tal_dup(peer, struct pubkey, &jc->id); diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index 230404e6c..b935833ac 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -1,6 +1,8 @@ #ifndef LIGHTNING_LIGHTNINGD_PEER_CONTROL_H #define LIGHTNING_LIGHTNINGD_PEER_CONTROL_H #include "config.h" +#include +#include #include struct peer { @@ -12,15 +14,21 @@ struct peer { /* Inside ld->peers. */ struct list_node list; - /* What stage is this in? */ + /* What stage is this in? NULL during first creation. */ struct subdaemon *owner; + /* What's happening (doubles as error return for connect_cmd) */ + const char *condition; + /* ID of peer (NULL before initial handshake). */ struct pubkey *id; - /* Our fd to the peer. */ + /* Our fd to the peer (-1 when we don't have it). */ int fd; + /* Where we connected to, or it connected from. */ + struct netaddr netaddr; + /* HSM connection for this peer. */ int hsmfd; @@ -30,5 +38,6 @@ struct peer { struct peer *peer_by_unique_id(struct lightningd *ld, u64 unique_id); +PRINTF_FMT(2,3) void peer_set_condition(struct peer *peer, const char *fmt, ...); void setup_listeners(struct lightningd *ld); #endif /* LIGHTNING_LIGHTNINGD_PEER_CONTROL_H */