Browse Source

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 <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 7 years ago
parent
commit
c6483a57d0
  1. 11
      gossipd/gossip.c
  2. 1
      gossipd/handshake.c
  3. 10
      tests/test_lightningd.py

11
gossipd/gossip.c

@ -148,6 +148,9 @@ struct reaching {
/* How many (if any) connect commands are waiting for the result. */ /* How many (if any) connect commands are waiting for the result. */
size_t num_master_responses; size_t num_master_responses;
/* How far did we get? */
const char *connstate;
}; };
/* Things we need when we're talking direct to the peer. */ /* 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, const struct crypto_state *cs,
struct reaching *reach) struct reaching *reach)
{ {
reach->connstate = "Exchanging init messages";
return init_new_peer(conn, id, addr, cs, reach->daemon); 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", status_trace("Connected out for %s",
type_to_string(tmpctx, struct pubkey, &reach->id)); type_to_string(tmpctx, struct pubkey, &reach->id));
reach->connstate = "Cryptographic handshake";
return initiator_handshake(conn, &reach->daemon->id, &reach->id, return initiator_handshake(conn, &reach->daemon->id, &reach->id,
&reach->addr, &reach->addr,
handshake_out_success, reach); handshake_out_success, reach);
@ -1701,10 +1706,13 @@ static void connect_failed(struct io_conn *conn, struct reaching *reach)
{ {
u8 *msg; u8 *msg;
struct important_peerid *imp; struct important_peerid *imp;
const char *err = tal_fmt(tmpctx, "%s: %s",
reach->connstate,
strerror(errno));
/* Tell any connect commands what happened. */ /* Tell any connect commands what happened. */
msg = towire_gossipctl_connect_to_peer_result(reach, &reach->id, 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++) for (size_t i = 0; i < reach->num_master_responses; i++)
daemon_conn_send(&reach->daemon->master, msg); 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->id = *id;
reach->addr = a->addr; reach->addr = a->addr;
reach->num_master_responses = master_needs_response; reach->num_master_responses = master_needs_response;
reach->connstate = "Connection establishment";
list_add_tail(&daemon->reaching, &reach->list); list_add_tail(&daemon->reaching, &reach->list);
tal_add_destructor(reach, destroy_reaching); tal_add_destructor(reach, destroy_reaching);

1
gossipd/handshake.c

@ -341,6 +341,7 @@ static struct io_plan *handshake_failed_(struct io_conn *conn,
status_trace("%s: handshake failed %s:%u", status_trace("%s: handshake failed %s:%u",
h->side == RESPONDER ? "Responder" : "Initiator", h->side == RESPONDER ? "Responder" : "Initiator",
function, line); function, line);
errno = EPROTO;
return io_close(conn); return io_close(conn);
} }
#define handshake_failed(conn, h) \ #define handshake_failed(conn, h) \

10
tests/test_lightningd.py

@ -623,6 +623,16 @@ class LightningDTests(BaseLightningDTests):
"No address known", "No address known",
l1.rpc.connect, '032cf15d1ad9c4a08d26eab1918f732d8ef8fdc6abb9640bf3db174372c491304e') 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): def test_connect_standard_addr(self):
"""Test standard node@host:port address """Test standard node@host:port address
""" """

Loading…
Cancel
Save