Skip to content

Commit 4a3ee19

Browse files
committed
connectd: Update connection list with new address
If we're already attempting to connect to a peer, we would ignore new connection requests. This is problematic if your node has bad connection details for the node -- you can't update it while inflight. This patch appends new connection suggestions to the list of connections to try. Fixes #4154
1 parent cd7d5cd commit 4a3ee19

File tree

3 files changed

+67
-1
lines changed

3 files changed

+67
-1
lines changed

connectd/connectd.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1457,8 +1457,17 @@ static void try_connect_peer(struct daemon *daemon,
14571457
return;
14581458

14591459
/* If we're trying to connect it right now, that's OK. */
1460-
if (find_connecting(daemon, id))
1460+
if ((connect = find_connecting(daemon, id))) {
1461+
/* If we've been passed in new connection details
1462+
* for this connection, update our addrhint + add
1463+
* to addresses to check */
1464+
if (addrhint) {
1465+
connect->addrhint = tal_steal(connect, addrhint);
1466+
tal_arr_expand(&connect->addrs, *addrhint);
1467+
}
1468+
14611469
return;
1470+
}
14621471

14631472
/* Start an array of addresses to try. */
14641473
addrs = tal_arr(tmpctx, struct wireaddr_internal, 0);

tests/plugins/slow_start.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/usr/bin/env python3
2+
"""This plugin is used to check that updated connection hints work properly.
3+
4+
"""
5+
from pyln.client import Plugin
6+
7+
import socket
8+
import time
9+
10+
plugin = Plugin()
11+
12+
13+
@plugin.async_method('waitconn')
14+
def wait_connection(request, plugin):
15+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
16+
sock.bind(('localhost', 0))
17+
sock.listen(1)
18+
print("listening for connections on port {}".format(sock.getsockname()[1]))
19+
20+
# We are a one and done socket connection!
21+
conn, client_addr = sock.accept()
22+
try:
23+
print("connection from {}".format(client_addr))
24+
time.sleep(3)
25+
26+
finally:
27+
conn.close()
28+
29+
print("closing socket")
30+
sock.close()
31+
32+
33+
plugin.run()

tests/test_connection.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,30 @@ def test_reconnect_channel_peers(node_factory, executor):
111111
fut3.result(10)
112112

113113

114+
def test_connection_moved(node_factory, executor):
115+
slow_start = os.path.join(os.getcwd(), 'tests/plugins/slow_start.py')
116+
options = {'may_reconnect': True, 'plugin': slow_start}
117+
l1, l2 = node_factory.get_nodes(2, opts=options)
118+
119+
# Set up the plugin to wait for a connection
120+
executor.submit(l1.rpc.waitconn)
121+
log = l1.daemon.wait_for_log('listening for connections')
122+
match = re.search(r'on port (\d*)', log)
123+
assert match and len(match.groups()) == 1
124+
hang_port = match.groups()[0]
125+
126+
# Attempt connection
127+
fut_hang = executor.submit(l1.rpc.connect, l2.info['id'],
128+
'localhost', hang_port)
129+
l1.daemon.wait_for_log('connection from')
130+
131+
# Provide correct connection details
132+
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
133+
134+
# If we failed to update the connection, this call will error
135+
fut_hang.result(TIMEOUT)
136+
137+
114138
def test_balance(node_factory):
115139
l1, l2 = node_factory.line_graph(2, fundchannel=True)
116140
p1 = only_one(l1.rpc.getpeer(peer_id=l2.info['id'], level='info')['channels'])

0 commit comments

Comments
 (0)