From c6483a57d09df0b9baa2d1fc7b8cb140b09b8500 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 26 Apr 2018 14:21:01 +0930 Subject: [PATCH] gossipd: give more distinct errors. At least say whether we failed to connect at all, or failed cryptographic handshake, or failed reading/writing init messages. The errno can be "Operation now in progress" if the other end closes the socket on us: this happens when we handshake with the wrong key and it hangs up on us. Fixing this would require work on ccan/io though. Signed-off-by: Rusty Russell --- gossipd/gossip.c | 11 ++++++++++- gossipd/handshake.c | 1 + tests/test_lightningd.py | 10 ++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/gossipd/gossip.c b/gossipd/gossip.c index 4dde30b03..b04b37f12 100644 --- a/gossipd/gossip.c +++ b/gossipd/gossip.c @@ -148,6 +148,9 @@ struct reaching { /* How many (if any) connect commands are waiting for the result. */ size_t num_master_responses; + + /* How far did we get? */ + const char *connstate; }; /* Things we need when we're talking direct to the peer. */ @@ -1681,6 +1684,7 @@ static struct io_plan *handshake_out_success(struct io_conn *conn, const struct crypto_state *cs, struct reaching *reach) { + reach->connstate = "Exchanging init messages"; return init_new_peer(conn, id, addr, cs, reach->daemon); } @@ -1692,6 +1696,7 @@ static struct io_plan *connection_out(struct io_conn *conn, status_trace("Connected out for %s", type_to_string(tmpctx, struct pubkey, &reach->id)); + reach->connstate = "Cryptographic handshake"; return initiator_handshake(conn, &reach->daemon->id, &reach->id, &reach->addr, handshake_out_success, reach); @@ -1701,10 +1706,13 @@ static void connect_failed(struct io_conn *conn, struct reaching *reach) { u8 *msg; struct important_peerid *imp; + const char *err = tal_fmt(tmpctx, "%s: %s", + reach->connstate, + strerror(errno)); /* Tell any connect commands what happened. */ msg = towire_gossipctl_connect_to_peer_result(reach, &reach->id, - false, strerror(errno)); + false, err); for (size_t i = 0; i < reach->num_master_responses; i++) daemon_conn_send(&reach->daemon->master, msg); @@ -1878,6 +1886,7 @@ static void try_reach_peer(struct daemon *daemon, const struct pubkey *id, reach->id = *id; reach->addr = a->addr; reach->num_master_responses = master_needs_response; + reach->connstate = "Connection establishment"; list_add_tail(&daemon->reaching, &reach->list); tal_add_destructor(reach, destroy_reaching); diff --git a/gossipd/handshake.c b/gossipd/handshake.c index 04b61feb2..26dbf1c9c 100644 --- a/gossipd/handshake.c +++ b/gossipd/handshake.c @@ -341,6 +341,7 @@ static struct io_plan *handshake_failed_(struct io_conn *conn, status_trace("%s: handshake failed %s:%u", h->side == RESPONDER ? "Responder" : "Initiator", function, line); + errno = EPROTO; return io_close(conn); } #define handshake_failed(conn, h) \ diff --git a/tests/test_lightningd.py b/tests/test_lightningd.py index 5820a85f8..a5754f6ff 100644 --- a/tests/test_lightningd.py +++ b/tests/test_lightningd.py @@ -623,6 +623,16 @@ class LightningDTests(BaseLightningDTests): "No address known", l1.rpc.connect, '032cf15d1ad9c4a08d26eab1918f732d8ef8fdc6abb9640bf3db174372c491304e') + # Should get reasonable error if connection refuse. + self.assertRaisesRegex(ValueError, + "Connection establishment: Connection refused", + l1.rpc.connect, '032cf15d1ad9c4a08d26eab1918f732d8ef8fdc6abb9640bf3db174372c491304e', 'localhost', 1) + + # Should get reasonable error if wrong key for peer. + self.assertRaisesRegex(ValueError, + "Cryptographic handshake: ", + l1.rpc.connect, '032cf15d1ad9c4a08d26eab1918f732d8ef8fdc6abb9640bf3db174372c491304e', 'localhost', l2.info['port']) + def test_connect_standard_addr(self): """Test standard node@host:port address """