@@ -100,31 +100,11 @@ static struct connecting *find_connecting(struct daemon *daemon,
100
100
return connecting_htable_get (daemon -> connecting , id );
101
101
}
102
102
103
- /*~ When we free a peer, we remove it from the daemon's hashtable.
104
- * We also call this manually if we want to elegantly drain peer's
105
- * queues. */
106
- void destroy_peer (struct peer * peer )
103
+ /*~ When we free a peer, we remove it from the daemon's hashtable. */
104
+ static void destroy_peer (struct peer * peer )
107
105
{
108
- assert (!peer -> draining );
109
-
110
106
if (!peer_htable_del (peer -> daemon -> peers , peer ))
111
107
abort ();
112
-
113
- /* Tell gossipd to stop asking this peer gossip queries */
114
- daemon_conn_send (peer -> daemon -> gossipd ,
115
- take (towire_gossipd_peer_gone (NULL , & peer -> id )));
116
-
117
- /* Tell lightningd it's really disconnected */
118
- daemon_conn_send (peer -> daemon -> master ,
119
- take (towire_connectd_peer_disconnect_done (NULL ,
120
- & peer -> id ,
121
- peer -> counter )));
122
- /* This makes multiplex.c routines not feed us more, but
123
- * *also* means that if we're freed directly, the ->to_peer
124
- * destructor won't call drain_peer(). */
125
- peer -> draining = true;
126
-
127
- schedule_reconnect_if_important (peer -> daemon , & peer -> id );
128
108
}
129
109
130
110
/*~ This is where we create a new peer. */
@@ -277,6 +257,22 @@ static void reset_reconnect_timer(struct peer *peer)
277
257
imp -> reconnect_secs = INITIAL_WAIT_SECONDS ;
278
258
}
279
259
260
+ void send_disconnected (struct daemon * daemon ,
261
+ const struct node_id * id ,
262
+ u64 connectd_counter )
263
+ {
264
+ /* lightningd: it's gone */
265
+ daemon_conn_send (daemon -> master ,
266
+ take (towire_connectd_peer_disconnected (NULL , id , connectd_counter )));
267
+
268
+ /* Tell gossipd to stop asking this peer gossip queries */
269
+ daemon_conn_send (daemon -> gossipd ,
270
+ take (towire_gossipd_peer_gone (NULL , id )));
271
+
272
+ /* Start reconnection process if we care */
273
+ schedule_reconnect_if_important (daemon , id );
274
+ }
275
+
280
276
/*~ Note the lack of static: this is called by peer_exchange_initmsg.c once the
281
277
* INIT messages are exchanged, and also by the retry code above. */
282
278
struct io_plan * peer_connected (struct io_conn * conn ,
@@ -290,17 +286,20 @@ struct io_plan *peer_connected(struct io_conn *conn,
290
286
bool incoming )
291
287
{
292
288
u8 * msg ;
293
- struct peer * peer ;
289
+ struct peer * peer , * oldpeer ;
294
290
int unsup ;
295
291
size_t depender , missing ;
296
292
int subd_fd ;
297
293
bool option_gossip_queries ;
298
294
struct connecting * connect ;
295
+ u64 prev_connectd_counter ;
299
296
300
297
/* We remove any previous connection immediately, on the assumption it's dead */
301
- peer = peer_htable_get (daemon -> peers , id );
302
- if (peer )
303
- tal_free (peer );
298
+ oldpeer = peer_htable_get (daemon -> peers , id );
299
+ if (oldpeer ) {
300
+ prev_connectd_counter = oldpeer -> counter ;
301
+ destroy_peer_immediately (oldpeer );
302
+ }
304
303
305
304
/* We promised we'd take it by marking it TAKEN above; prepare to free it. */
306
305
if (taken (their_features ))
@@ -318,6 +317,9 @@ struct io_plan *peer_connected(struct io_conn *conn,
318
317
unsup = features_unsupported (daemon -> our_features , their_features ,
319
318
INIT_FEATURE );
320
319
if (unsup != -1 ) {
320
+ /* We were going to send a reconnect message, but not now! */
321
+ if (oldpeer )
322
+ send_disconnected (daemon , id , prev_connectd_counter );
321
323
status_peer_unusual (id , "Unsupported feature %u" , unsup );
322
324
msg = towire_warningfmt (NULL , NULL , "Unsupported feature %u" ,
323
325
unsup );
@@ -326,6 +328,9 @@ struct io_plan *peer_connected(struct io_conn *conn,
326
328
}
327
329
328
330
if (!feature_check_depends (their_features , & depender , & missing )) {
331
+ /* We were going to send a reconnect message, but not now! */
332
+ if (oldpeer )
333
+ send_disconnected (daemon , id , prev_connectd_counter );
329
334
status_peer_unusual (id , "Feature %zu requires feature %zu" ,
330
335
depender , missing );
331
336
msg = towire_warningfmt (NULL , NULL ,
@@ -362,23 +367,37 @@ struct io_plan *peer_connected(struct io_conn *conn,
362
367
peer = new_peer (daemon , id , cs , their_features , is_websocket , conn ,
363
368
& subd_fd );
364
369
/* Only takes over conn if it succeeds. */
365
- if (!peer )
370
+ if (!peer ) {
371
+ /* We were going to send a reconnect message, but not now! */
372
+ if (oldpeer )
373
+ send_disconnected (daemon , id , prev_connectd_counter );
366
374
return io_close (conn );
375
+ }
367
376
368
377
/* Tell gossipd it can ask query this new peer for gossip */
369
378
option_gossip_queries = feature_negotiated (daemon -> our_features ,
370
379
their_features ,
371
380
OPT_GOSSIP_QUERIES );
372
- msg = towire_gossipd_new_peer (NULL , id , option_gossip_queries );
373
- daemon_conn_send (daemon -> gossipd , take (msg ));
374
381
375
382
/* Get ready for streaming gossip from the store */
376
383
setup_peer_gossip_store (peer , daemon -> our_features , their_features );
377
384
378
- /* Create message to tell master peer has connected. */
379
- msg = towire_connectd_peer_connected (NULL , id , peer -> counter ,
380
- addr , remote_addr ,
381
- incoming , their_features );
385
+ /* Create message to tell master peer has connected/reconnected. */
386
+ if (oldpeer ) {
387
+ msg = towire_connectd_peer_reconnected (NULL , id ,
388
+ prev_connectd_counter ,
389
+ peer -> counter ,
390
+ addr , remote_addr ,
391
+ incoming , their_features );
392
+ } else {
393
+ /* Tell gossipd about new peer */
394
+ msg = towire_gossipd_new_peer (NULL , id , option_gossip_queries );
395
+ daemon_conn_send (daemon -> gossipd , take (msg ));
396
+
397
+ msg = towire_connectd_peer_connected (NULL , id , peer -> counter ,
398
+ addr , remote_addr ,
399
+ incoming , their_features );
400
+ }
382
401
383
402
/*~ daemon_conn is a message queue for inter-daemon communication: we
384
403
* queue up the `connect_peer_connected` message to tell lightningd
@@ -1923,9 +1942,7 @@ static void peer_disconnect(struct daemon *daemon, const u8 *msg)
1923
1942
if (peer -> counter != counter )
1924
1943
return ;
1925
1944
1926
- /* We make sure any final messages from the subds are sent! */
1927
- status_peer_debug (& id , "disconnect_peer" );
1928
- drain_peer (peer );
1945
+ disconnect_peer (peer );
1929
1946
}
1930
1947
1931
1948
/* lightningd tells us a peer is no longer "important". */
@@ -2371,7 +2388,8 @@ static struct io_plan *recv_req(struct io_conn *conn,
2371
2388
case WIRE_CONNECTD_PING_DONE :
2372
2389
case WIRE_CONNECTD_GOT_ONIONMSG_TO_US :
2373
2390
case WIRE_CONNECTD_CUSTOMMSG_IN :
2374
- case WIRE_CONNECTD_PEER_DISCONNECT_DONE :
2391
+ case WIRE_CONNECTD_PEER_DISCONNECTED :
2392
+ case WIRE_CONNECTD_PEER_RECONNECTED :
2375
2393
case WIRE_CONNECTD_START_SHUTDOWN_REPLY :
2376
2394
case WIRE_CONNECTD_INJECT_ONIONMSG_REPLY :
2377
2395
case WIRE_CONNECTD_ONIONMSG_FORWARD_FAIL :
0 commit comments