1
0
mirror of https://github.com/ACINQ/eclair.git synced 2024-11-19 09:54:02 +01:00

Manual watching of peer-connection actor (#1567)

Instead of `Peer` watching `PeerConnection`, we have `PeerConnection`
notify `Peer` when it dies. Not relying on a watch allows for harder
security settings when enabling akka cluster.
This commit is contained in:
Pierre-Marie Padiou 2020-10-15 17:44:40 +02:00 committed by GitHub
parent 90bf08e62c
commit 9c16bb75c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 13 additions and 7 deletions

View File

@ -172,7 +172,7 @@ class Peer(val nodeParams: NodeParams, remoteNodeId: PublicKey, watcher: ActorRe
d.peerConnection ! PoisonPill
stay
case Event(Terminated(actor), d: ConnectedData) if actor == d.peerConnection =>
case Event(ConnectionDown(peerConnection), d: ConnectedData) if peerConnection == d.peerConnection =>
Logs.withMdc(diagLog)(Logs.mdc(category_opt = Some(Logs.LogCategory.CONNECTION))) {
log.info("connection lost")
}
@ -196,7 +196,6 @@ class Peer(val nodeParams: NodeParams, remoteNodeId: PublicKey, watcher: ActorRe
case Event(connectionReady: PeerConnection.ConnectionReady, d: ConnectedData) =>
log.info(s"got new connection, killing current one and switching")
context unwatch d.peerConnection
d.peerConnection ! PoisonPill
d.channels.values.toSet[ActorRef].foreach(_ ! INPUT_DISCONNECTED) // we deduplicate with toSet because there might be two entries per channel (tmp id and final id)
gotoConnected(connectionReady, d.channels)
@ -254,8 +253,6 @@ class Peer(val nodeParams: NodeParams, remoteNodeId: PublicKey, watcher: ActorRe
require(remoteNodeId == connectionReady.remoteNodeId, s"invalid nodeid: $remoteNodeId != ${connectionReady.remoteNodeId}")
log.debug("got authenticated connection to address {}:{}", connectionReady.address.getHostString, connectionReady.address.getPort)
context watch connectionReady.peerConnection
if (connectionReady.outgoing) {
// we store the node address upon successful outgoing connection, so we can reconnect later
// any previous address is overwritten
@ -397,6 +394,12 @@ object Peer {
case class Transition(previousData: Peer.Data, nextData: Peer.Data)
/**
* Sent by the peer-connection to notify the peer that the connection is down.
* We could use watchWith on the peer-connection but it doesn't work with akka cluster when untrusted mode is enabled
*/
case class ConnectionDown(peerConnection: ActorRef)
// @formatter:on
def makeChannelParams(nodeParams: NodeParams, features: Features, defaultFinalScriptPubkey: ByteVector, walletStaticPaymentBasepoint: Option[PublicKey], isFunder: Boolean, fundingAmount: Satoshi): LocalParams = {

View File

@ -406,7 +406,9 @@ class PeerConnection(keyPair: KeyPair, conf: PeerConnection.Conf, switchboard: A
}
onTermination {
case StopEvent(_, CONNECTED, _: ConnectedData) => Metrics.PeerConnectionsConnected.withoutTags().decrement()
case StopEvent(_, CONNECTED, d: ConnectedData) =>
Metrics.PeerConnectionsConnected.withoutTags().decrement()
d.peer ! Peer.ConnectionDown(self)
}
/**

View File

@ -91,22 +91,23 @@ class ReconnectionTask(nodeParams: NodeParams, remoteNodeId: PublicKey) extends
// reason to eagerly retry
// That's why we set the next reconnection delay to a random value between MAX_RECONNECT_INTERVAL/2 and MAX_RECONNECT_INTERVAL.
val firstNextReconnectionDelay = nodeParams.maxReconnectInterval.minus(Random.nextInt(nodeParams.maxReconnectInterval.toSeconds.toInt / 2).seconds)
log.debug("first connection attempt in {}", initialDelay)
(initialDelay, firstNextReconnectionDelay)
case (_, cd: ConnectingData) if System.currentTimeMillis.milliseconds - d.since < 30.seconds =>
log.info("peer is disconnected (shortly after connection was established)")
// If our latest successful connection attempt was less than 30 seconds ago, we pick up the exponential
// back-off retry delay where we left it. The goal is to address cases where the reconnection is successful,
// but we are disconnected right away.
val initialDelay = cd.nextReconnectionDelay
val firstNextReconnectionDelay = nextReconnectionDelay(initialDelay, nodeParams.maxReconnectInterval)
log.info("peer got disconnected shortly after connection was established, next reconnection in {}", initialDelay)
(initialDelay, firstNextReconnectionDelay)
case _ =>
log.info("peer is disconnected")
// Randomizing the initial delay is important in the case of a reconnection. If both peers have a public
// address, they may attempt to simultaneously connect back to each other, which could result in reconnection loop,
// given that each new connection will cause the previous one to be killed.
val initialDelay = randomizeDelay(nodeParams.initialRandomReconnectDelay)
val firstNextReconnectionDelay = nextReconnectionDelay(initialDelay, nodeParams.maxReconnectInterval)
log.info("peer is disconnected, next reconnection in {}", initialDelay)
(initialDelay, firstNextReconnectionDelay)
}
setReconnectTimer(initialDelay)