@ -102,12 +102,12 @@ struct reaching {
/* Did we succeed? */
bool succeeded ;
/* Is this an important peer to keep connected? */
bool keep_connected ;
/* How many times have we attempted to connect? */
u32 attempts ;
/* How many times to attempt */
u32 max_attempts ;
/* Timestamp of the first attempt */
u32 first_attempt ;
} ;
@ -158,7 +158,7 @@ struct peer {
bool gossip_sync ;
/* If we die, should we reach again? */
bool reach_again ;
bool keep_connected ;
/* Only one of these is set: */
struct local_peer_state * local ;
@ -179,13 +179,14 @@ static struct io_plan *peer_start_gossip(struct io_conn *conn,
struct peer * peer ) ;
static bool send_peer_with_fds ( struct peer * peer , const u8 * msg ) ;
static void wake_pkt_out ( struct peer * peer ) ;
static bool try_reach_peer ( struct daemon * daemon , const struct pubkey * id ) ;
static bool try_reach_peer ( struct daemon * daemon , const struct pubkey * id ,
bool keep_connected ) ;
static void destroy_peer ( struct peer * peer )
{
list_del_from ( & peer - > daemon - > peers , & peer - > list ) ;
if ( peer - > reach_again )
try_reach_peer ( peer - > daemon , & peer - > id ) ;
if ( peer - > keep_connected )
try_reach_peer ( peer - > daemon , & peer - > id , true ) ;
}
static struct peer * find_peer ( struct daemon * daemon , const struct pubkey * id )
@ -242,7 +243,7 @@ static struct peer *new_peer(const tal_t *ctx,
peer - > daemon = daemon ;
peer - > local = new_local_peer_state ( peer , cs ) ;
peer - > remote = NULL ;
peer - > reach_again = false ;
peer - > keep_connected = false ;
return peer ;
}
@ -273,18 +274,21 @@ static struct reaching *find_reaching(struct daemon *daemon,
return NULL ;
}
static void reached_peer ( struct daemon * daemon , const struct pubkey * id ,
struct io_conn * conn )
static void reached_peer ( struct peer * peer , struct io_conn * conn )
{
struct reaching * r = find_reaching ( daemon , id ) ;
struct reaching * r = find_reaching ( peer - > daemon , & peer - > id ) ;
if ( ! r )
return ;
/* If this peer was important, remember, so we reconnect. */
if ( r - > keep_connected )
peer - > keep_connected = true ;
/* OK, we've reached the peer successfully, stop retrying. */
/* Don't free conn with reach. */
tal_steal ( daemon , conn ) ;
tal_steal ( peer - > daemon , conn ) ;
/* Don't call connect_failed */
io_set_finish ( conn , NULL , NULL ) ;
@ -350,7 +354,7 @@ static struct io_plan *peer_init_received(struct io_conn *conn,
return io_close ( conn ) ;
}
reached_peer ( peer - > daemon , & peer - > id , conn ) ;
reached_peer ( peer , conn ) ;
/* BOLT #7:
*
@ -1574,7 +1578,7 @@ static void connect_failed(struct io_conn *conn, struct reaching *reach)
u32 diff = time_now ( ) . ts . tv_sec - reach - > first_attempt ;
reach - > attempts + + ;
if ( reach - > attempts > = reach - > max_ attempts) {
if ( ! reach - > keep_connected & & reach - > attempts > = 10 ) {
status_info ( " Failed to connect after %d attempts, giving up "
" after %d seconds " ,
reach - > attempts , diff ) ;
@ -1724,25 +1728,31 @@ static void try_connect(struct reaching *reach)
}
/* Returns true if we're already connected. */
static bool try_reach_peer ( struct daemon * daemon , const struct pubkey * id )
static bool try_reach_peer ( struct daemon * daemon , const struct pubkey * id ,
bool keep_connected )
{
struct reaching * reach ;
struct peer * peer ;
if ( find_reaching ( daemon , id ) ) {
/* FIXME: Perhaps kick timer in this case? */
reach = find_reaching ( daemon , id ) ;
if ( reach ) {
/* May not have been important before */
if ( keep_connected )
reach - > keep_connected = true ;
status_trace ( " try_reach_peer: already trying to reach %s " ,
type_to_string ( tmpctx , struct pubkey , id ) ) ;
return false ;
}
/* Master might find out before we do that a peer is dead; if we
* seem to be connected just mark it for reconnect . */
/* Master might find out before we do that a peer is dead. */
peer = find_peer ( daemon , id ) ;
if ( peer ) {
status_trace ( " reach_peer: have %s, will retry if it dies " ,
type_to_string ( tmpctx , struct pubkey , id ) ) ;
peer - > reach_again = true ;
/* May not have been important before */
if ( keep_connected )
peer - > keep_connected = true ;
status_trace ( " reach_peer: have peer %s%s " ,
type_to_string ( tmpctx , struct pubkey , id ) ,
peer - > keep_connected ? " (will retry if it dies) " : " " ) ;
return true ;
}
@ -1752,7 +1762,7 @@ static bool try_reach_peer(struct daemon *daemon, const struct pubkey *id)
reach - > id = * id ;
reach - > first_attempt = time_now ( ) . ts . tv_sec ;
reach - > attempts = 0 ;
reach - > max_attempts = 10 ;
reach - > keep_connected = keep_connected ;
list_add_tail ( & daemon - > reaching , & reach - > list ) ;
tal_add_destructor ( reach , destroy_reaching ) ;
@ -1760,7 +1770,6 @@ static bool try_reach_peer(struct daemon *daemon, const struct pubkey *id)
return false ;
}
/* This catches all kinds of failures, like network errors. */
static struct io_plan * reach_peer ( struct io_conn * conn ,
struct daemon * daemon , const u8 * msg )
{
@ -1770,7 +1779,7 @@ static struct io_plan *reach_peer(struct io_conn *conn,
master_badmsg ( WIRE_GOSSIPCTL_REACH_PEER , msg ) ;
/* Master can't check this itself, because that's racy. */
if ( try_reach_peer ( daemon , & id ) ) {
if ( try_reach_peer ( daemon , & id , false ) ) {
daemon_conn_send ( & daemon - > master ,
take ( towire_gossip_peer_already_connected ( NULL ,
& id ) ) ) ;
@ -1796,6 +1805,33 @@ static struct io_plan *addr_hint(struct io_conn *conn,
return daemon_conn_read_next ( conn , & daemon - > master ) ;
}
static struct io_plan * peer_important ( struct io_conn * conn ,
struct daemon * daemon , const u8 * msg )
{
struct pubkey id ;
bool important ;
struct reaching * r ;
struct peer * p ;
if ( ! fromwire_gossipctl_peer_important ( msg , & id , & important ) )
master_badmsg ( WIRE_GOSSIPCTL_REACH_PEER , msg ) ;
r = find_reaching ( daemon , & id ) ;
p = find_peer ( daemon , & id ) ;
/* Override keep_connected flag everywhere */
if ( r )
r - > keep_connected = important ;
if ( p )
p - > keep_connected = important ;
/* If it's important and we're not connected/connecting, do so now. */
if ( important & & ! r & & ! p )
try_reach_peer ( daemon , & id , true ) ;
return daemon_conn_read_next ( conn , & daemon - > master ) ;
}
static struct io_plan * get_peers ( struct io_conn * conn ,
struct daemon * daemon , const u8 * msg )
{
@ -2044,6 +2080,9 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master
case WIRE_GOSSIPCTL_PEER_ADDRHINT :
return addr_hint ( conn , daemon , master - > msg_in ) ;
case WIRE_GOSSIPCTL_PEER_IMPORTANT :
return peer_important ( conn , daemon , master - > msg_in ) ;
case WIRE_GOSSIP_GETPEERS_REQUEST :
return get_peers ( conn , daemon , master - > msg_in ) ;