java.lang.Object
java.lang.Thread
net.i2p.util.I2PThread
net.i2p.router.crypto.ratchet.Elg2KeyFactory
All Implemented Interfaces:
Runnable, KeyFactory

public class Elg2KeyFactoryextends I2PThread implements KeyFactory
Threaded factory for pre-calculating Elligator2-encoded X25519 key pairs to prevent Diffie-Hellman computation bottlenecks in critical paths

Try to keep DH pairs at the ready. It's important to do this in a separate thread, because if we run out, the pairs are generated in the NTCP Pumper thread, and it can fall behind.

  • Field Details

    • lastInstance

      private static volatile Elg2KeyFactory lastInstance
      The factory created last, for reuse.
    • _context

      private final RouterContext _context
      The router context.
    • _log

      private final Log _log
      Logger for the key precalculation.
    • _elg2

      private final Elligator2 _elg2
      Mapping that makes the Decloak keys.
    • _minSize

      private volatile int _minSize
      Keys kept in the queue at least.
    • _maxSize

      private volatile int _maxSize
      Keys kept in the queue at most.
    • _calcDelay

      private volatile int _calcDelay
      Delay between precalculation batches.
    • _keys

      private final LinkedBlockingQueue<Elg2KeyPair> _keys
      Queue of the precalculated key pairs.
    • _isRunning

      private volatile boolean _isRunning
      True while the factory thread runs.
    • _checkDelay

      private long _checkDelay
      Delay before checking the queue again.
    • _emptyCount

      private final AtomicInteger _emptyCount
      Times the queue was found empty.
    • _usedCount

      private final AtomicInteger _usedCount
      Keys taken from the queue.
    • PROP_DH_PRECALC_MIN

      private static final String PROP_DH_PRECALC_MIN
      Config key for the minimum queue size.
      See Also:
    • PROP_DH_PRECALC_MAX

      private static final String PROP_DH_PRECALC_MAX
      Config key for the maximum queue size.
      See Also:
    • PROP_DH_PRECALC_DELAY

      private static final String PROP_DH_PRECALC_DELAY
      Config key for the precalculation delay.
      See Also:
    • DEFAULT_DH_PRECALC_MIN

      private static final int DEFAULT_DH_PRECALC_MIN
      Default minimum queue size.
    • DEFAULT_DH_PRECALC_MAX

      private static final int DEFAULT_DH_PRECALC_MAX
      Default maximum queue size.
    • DEFAULT_DH_PRECALC_DELAY

      private static final int DEFAULT_DH_PRECALC_DELAY
      Default precalculation delay, in ms.
      See Also:
    • HARD_MAX

      private static final int HARD_MAX
      Largest queue size allowed.
      See Also:
    • RETURN_UNUSED_TO_XDH

      private final boolean RETURN_UNUSED_TO_XDH
      True to return unused keys to the X25519 factory.
  • Constructor Details

    • Elg2KeyFactory

      public Elg2KeyFactory(RouterContext ctx)
      Creates factory and starts background key precomputation thread.
      Parameters:
      ctx - the router context supplying the log, statistics and precomputation thread
  • Method Details

    • getInstance

      public static Elg2KeyFactory getInstance()
      Last created instance.
      Returns:
      the most recently constructed factory, or null if none was built
    • getMinSize

      public int getMinSize()
      Current minimum precalc queue size.
      Returns:
      the min size
    • setMinSize

      public void setMinSize(int min)
      Minimum precalc queue size.
      Parameters:
      min - the requested floor, raised to 1 if less than that is passed
    • getMaxSize

      public int getMaxSize()
      Current maximum precalc queue size.
      Returns:
      the max size
    • setMaxSize

      public void setMaxSize(int max)
      Maximum precalc queue size.
      Parameters:
      max - the requested ceiling, raised to the current minimum if it is lower
    • getSize

      public int getSize()
      Current number of precalc keys queued.
      Returns:
      the number of precomputed keys waiting in the queue
    • refreshPoolSize

      public void refreshPoolSize()
      Called by the Tuner every 15 seconds. Adjusts max pool size based on demand.
    • shutdown

      public void shutdown()
      Note that this stops the singleton precalc thread. You don't want to do this if there are multiple routers in the JVM. Fix this if you care. See Router.shutdown(int).
    • run

      public void run()
      Precalc queue fill loop.
      Specified by:
      run in interface Runnable
      Overrides:
      run in class I2PThread
    • run2

      private void run2()
      Runs the precalculation loop.
    • getKeys

      public Elg2KeyPair getKeys()
      Pulls a prebuilt keypair from the queue, or if not available, construct a new one.
      Specified by:
      getKeys in interface KeyFactory
      Returns:
      a prebuilt keypair taken from the queue, or a freshly generated one if the queue was empty
    • precalc

      private Elg2KeyPair precalc()
      Generates one key pair.
      Returns:
      the new key pair
    • returnUnused

      public void returnUnused(Elg2KeyPair kp)
      Unused DH key builder; keys are discarded, not pooled.
      Parameters:
      kp - the key pair to discard; currently unused, as nothing is returned to the pool
    • addKeys

      private final boolean addKeys(Elg2KeyPair kp)
      Adds a precomputed key pair to the pool.
      Parameters:
      kp - the key pair to add
      Returns:
      true if successful, false if full