Skip to content
This repository has been archived by the owner on Apr 13, 2022. It is now read-only.

Commit

Permalink
[refer #393] Support periodic random connection eviction
Browse files Browse the repository at this point in the history
  • Loading branch information
knizhnik committed Dec 18, 2020
1 parent 30f3bea commit 5d8be6d
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/main/resources/reference.conf
Expand Up @@ -183,6 +183,8 @@ scorex {
# Max penalty score peer can accumulate before being banned
penaltyScoreThreshold = 100

# interval of evicting random peer to avoid eclipsing
peerEvictInterval = 1h
}

ntp {
Expand Down
21 changes: 19 additions & 2 deletions src/main/scala/scorex/core/network/NetworkController.scala
@@ -1,7 +1,6 @@
package scorex.core.network

import java.net._

import akka.actor._
import akka.io.Tcp._
import akka.io.{IO, Tcp}
Expand All @@ -21,7 +20,7 @@ import scorex.util.ScorexLogging
import scala.concurrent.ExecutionContext
import scala.concurrent.duration._
import scala.language.{existentials, postfixOps}
import scala.util.Try
import scala.util.{Random, Try}

/**
* Control all network interaction
Expand Down Expand Up @@ -89,6 +88,7 @@ class NetworkController(settings: NetworkSettings,
log.info("Successfully bound to the port " + settings.bindAddress.getPort)
scheduleConnectionToPeer()
scheduleDroppingDeadConnections()
scheduleEvictRandomConnections()

case CommandFailed(_: Bind) =>
log.error("Network port " + settings.bindAddress.getPort + " already in use!")
Expand Down Expand Up @@ -231,6 +231,23 @@ class NetworkController(settings: NetworkSettings,
}

/**
* Schedule a periodic eviction of random connection.
* It is needed to prevent eclipsing (https://www.usenix.org/system/files/conference/usenixsecurity15/sec15-paper-heilman.pdf)
*/
private def scheduleEvictRandomConnections(): Unit = {
context.system.scheduler.scheduleWithFixedDelay(settings.peerEvictInterval, settings.peerEvictInterval) {
() =>
val connectedPeers = connections.values.filter(_.peerInfo.nonEmpty).toSeq
if (!connectedPeers.isEmpty) {
val victim = Random.nextInt(connectedPeers.size)
val cp = connectedPeers(victim)
log.info(s"Evict connection to ${cp.peerInfo}")
cp.handlerRef ! CloseConnection
}
}
}

/**
* Schedule a periodic dropping of connections which seem to be inactive
*/
private def scheduleDroppingDeadConnections(): Unit = {
Expand Down
3 changes: 2 additions & 1 deletion src/main/scala/scorex/core/settings/Settings.scala
Expand Up @@ -50,7 +50,8 @@ case class NetworkSettings(nodeName: String,
maxPeerSpecObjects: Int,
temporalBanDuration: FiniteDuration,
penaltySafeInterval: FiniteDuration,
penaltyScoreThreshold: Int)
penaltyScoreThreshold: Int,
peerEvictInterval: FiniteDuration)

case class ScorexSettings(dataDir: File,
logDir: File,
Expand Down

0 comments on commit 5d8be6d

Please sign in to comment.