Changeset fe575a3


Ignore:
Timestamp:
Dec 15, 2010 10:59:35 PM (9 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
df3fc6e
Parents:
4c9558c
Message:

fix up DH like YK

File:
1 edited

Legend:

Unmodified
Added
Removed
  • core/java/src/net/i2p/crypto/DHSessionKeyBuilder.java

    r4c9558c rfe575a3  
    1414import java.io.OutputStream;
    1515import java.math.BigInteger;
    16 import java.util.ArrayList;
    17 import java.util.List;
     16import java.util.concurrent.LinkedBlockingQueue;
    1817
    1918import net.i2p.I2PAppContext;
     
    4948 */
    5049public class DHSessionKeyBuilder {
    51     private static I2PAppContext _context = I2PAppContext.getGlobalContext();
    52     private final static Log _log = new Log(DHSessionKeyBuilder.class);
    53     private static int MIN_NUM_BUILDERS = -1;
    54     private static int MAX_NUM_BUILDERS = -1;
    55     private static int CALC_DELAY = -1;
    56     /* FIXME this should be final if you syncronize FIXME */
    57     private static volatile List _builders = new ArrayList(50);
    58     private static Thread _precalcThread = null;
     50    private static final I2PAppContext _context = I2PAppContext.getGlobalContext();
     51    private static final Log _log;
     52    private static final int MIN_NUM_BUILDERS;
     53    private static final int MAX_NUM_BUILDERS;
     54    private static final int CALC_DELAY;
     55    private static final LinkedBlockingQueue<DHSessionKeyBuilder> _builders;
     56    private static final Thread _precalcThread;
     57
     58    // the data of importance
    5959    private BigInteger _myPrivateValue;
    6060    private BigInteger _myPublicValue;
     
    6666    public final static String PROP_DH_PRECALC_MAX = "crypto.dh.precalc.max";
    6767    public final static String PROP_DH_PRECALC_DELAY = "crypto.dh.precalc.delay";
    68     public final static int DEFAULT_DH_PRECALC_MIN = 5;
    69     public final static int DEFAULT_DH_PRECALC_MAX = 50;
    70     public final static int DEFAULT_DH_PRECALC_DELAY = 10000;
     68    public final static int DEFAULT_DH_PRECALC_MIN = 15;
     69    public final static int DEFAULT_DH_PRECALC_MAX = 40;
     70    public final static int DEFAULT_DH_PRECALC_DELAY = 200;
     71
     72    /** check every 30 seconds whether we have less than the minimum */
     73    private static long _checkDelay = 30 * 1000;
    7174
    7275    static {
    7376        I2PAppContext ctx = _context;
    74         ctx.statManager().createRateStat("crypto.dhGeneratePublicTime", "How long it takes to create x and X", "Encryption", new long[] { 60*1000, 5*60*1000, 60*60*1000 });
    75         ctx.statManager().createRateStat("crypto.dhCalculateSessionTime", "How long it takes to create the session key", "Encryption", new long[] { 60*1000, 5*60*1000, 60*60*1000 });       
    76         MIN_NUM_BUILDERS = ctx.getProperty(PROP_DH_PRECALC_MIN, DEFAULT_DH_PRECALC_MIN);
    77         MAX_NUM_BUILDERS = ctx.getProperty(PROP_DH_PRECALC_MAX, DEFAULT_DH_PRECALC_MAX);
     77        _log = ctx.logManager().getLog(DHSessionKeyBuilder.class);
     78        ctx.statManager().createRateStat("crypto.dhGeneratePublicTime", "How long it takes to create x and X", "Encryption", new long[] { 60*60*1000 });
     79        ctx.statManager().createRateStat("crypto.dhCalculateSessionTime", "How long it takes to create the session key", "Encryption", new long[] { 60*60*1000 });       
     80        ctx.statManager().createRateStat("crypto.DHUsed", "Need a DH from the queue", "Encryption", new long[] { 60*60*1000 });
     81        ctx.statManager().createRateStat("crypto.DHEmpty", "DH queue empty", "Encryption", new long[] { 60*60*1000 });
     82
     83        // add to the defaults for every 128MB of RAM, up to 512MB
     84        long maxMemory = Runtime.getRuntime().maxMemory();
     85        int factor = Math.min(4, (int) (1 + (maxMemory / (128*1024*1024l))));
     86        int defaultMin = DEFAULT_DH_PRECALC_MIN * factor;
     87        int defaultMax = DEFAULT_DH_PRECALC_MAX * factor;
     88        MIN_NUM_BUILDERS = ctx.getProperty(PROP_DH_PRECALC_MIN, defaultMin);
     89        MAX_NUM_BUILDERS = ctx.getProperty(PROP_DH_PRECALC_MAX, defaultMax);
     90
    7891        CALC_DELAY = ctx.getProperty(PROP_DH_PRECALC_DELAY, DEFAULT_DH_PRECALC_DELAY);
     92        _builders = new LinkedBlockingQueue(MAX_NUM_BUILDERS);
    7993
    8094        if (_log.shouldLog(Log.DEBUG))
     
    91105    /**
    92106     * Construct a new DH key builder
    93      *
     107     * or pulls a prebuilt one from the queue.
    94108     */
    95109    public DHSessionKeyBuilder() {
    96         this(false);
    97         DHSessionKeyBuilder builder = null;
    98         synchronized (_builders) {
    99             if (!_builders.isEmpty()) {
    100                 builder = (DHSessionKeyBuilder) _builders.remove(0);
    101                 if (_log.shouldLog(Log.DEBUG)) _log.debug("Removing a builder.  # left = " + _builders.size());
    102             } else {
    103                 if (_log.shouldLog(Log.WARN)) _log.warn("NO MORE BUILDERS!  creating one now");
    104             }
    105         }
     110        _context.statManager().addRateData("crypto.DHUsed", 1, 0);
     111        DHSessionKeyBuilder builder = _builders.poll();
    106112        if (builder != null) {
     113            if (_log.shouldLog(Log.DEBUG)) _log.debug("Removing a builder.  # left = " + _builders.size());
    107114            _myPrivateValue = builder._myPrivateValue;
    108115            _myPublicValue = builder._myPublicValue;
    109             _peerValue = builder._peerValue;
    110             _sessionKey = builder._sessionKey;
     116            // these two are still null after precalc
     117            //_peerValue = builder._peerValue;
     118            //_sessionKey = builder._sessionKey;
    111119            _extraExchangedBytes = builder._extraExchangedBytes;
    112120        } else {
    113             _myPrivateValue = null;
    114             _myPublicValue = null;
    115             _peerValue = null;
    116             _sessionKey = null;
     121            if (_log.shouldLog(Log.INFO)) _log.info("No more builders, creating one now");
     122            _context.statManager().addRateData("crypto.DHEmpty", 1, 0);
     123            // sets _myPrivateValue as a side effect
    117124            _myPublicValue = generateMyValue();
    118125            _extraExchangedBytes = new ByteArray();
     
    120127    }
    121128
    122     public DHSessionKeyBuilder(boolean usePool) {
    123         _myPrivateValue = null;
    124         _myPublicValue = null;
    125         _peerValue = null;
    126         _sessionKey = null;
     129    /**
     130     * Only for internal use
     131     * @parameter usePool unused, just to make it different from other constructor
     132     */
     133    private DHSessionKeyBuilder(boolean usePool) {
    127134        _extraExchangedBytes = new ByteArray();
    128135    }
     
    190197   
    191198    private static final int getSize() {
    192         synchronized (_builders) {
    193199            return _builders.size();
    194         }
    195     }
    196 
    197     private static final int addBuilder(DHSessionKeyBuilder builder) {
    198         int sz = 0;
    199         synchronized (_builders) {
    200             _builders.add(builder);
    201             sz = _builders.size();
    202         }
    203         return sz;
     200    }
     201
     202    /** @return true if successful, false if full */
     203    private static final boolean addBuilder(DHSessionKeyBuilder builder) {
     204        return _builders.offer(builder);
    204205    }
    205206
     
    211212    public BigInteger generateMyValue() {
    212213        long start = System.currentTimeMillis();
    213         _myPrivateValue = new NativeBigInteger(KeyGenerator.PUBKEY_EXPONENT_SIZE, RandomSource.getInstance());
     214        _myPrivateValue = new NativeBigInteger(KeyGenerator.PUBKEY_EXPONENT_SIZE, _context.random());
    214215        BigInteger myValue = CryptoConstants.elgg.modPow(_myPrivateValue, CryptoConstants.elgp);
    215216        long end = System.currentTimeMillis();
     
    315316     * the SHA256 of the key itself is used.
    316317     *
     318     * @return non-null (but rv.getData() may be null)
    317319     */
    318320    public ByteArray getExtraBytes() {
     
    407409    */
    408410   
     411/******
    409412    public static void main(String args[]) {
    410413        //if (true) { testValidation(); return; }
     
    420423        try {
    421424            for (int i = 0; i < 5; i++) {
    422                 long startNeg = Clock.getInstance().now();
     425                long startNeg = System.currentTimeMillis();
    423426                DHSessionKeyBuilder builder1 = new DHSessionKeyBuilder();
    424427                DHSessionKeyBuilder builder2 = new DHSessionKeyBuilder();
     
    429432                SessionKey key1 = builder1.getSessionKey();
    430433                SessionKey key2 = builder2.getSessionKey();
    431                 long endNeg = Clock.getInstance().now();
     434                long endNeg = System.currentTimeMillis();
    432435                negTime += endNeg - startNeg;
    433436
     
    459462        }
    460463    }
     464******/
    461465
    462466    private static class DHSessionKeyBuilderPrecalcRunner implements Runnable {
    463         private int _minSize;
    464         private int _maxSize;
     467        private final int _minSize;
     468        private final int _maxSize;
    465469
    466470        private DHSessionKeyBuilderPrecalcRunner(int minSize, int maxSize) {
     
    473477
    474478                int curSize = 0;
    475                 long start = Clock.getInstance().now();
     479                long start = System.currentTimeMillis();
    476480                int startSize = getSize();
     481                // Adjust delay
     482                if (startSize <= (_minSize * 2 / 3) && _checkDelay > 1000)
     483                    _checkDelay -= 1000;
     484                else if (startSize > (_minSize * 3 / 2) && _checkDelay < 60*1000)
     485                    _checkDelay += 1000;
    477486                curSize = startSize;
    478                 while (curSize < _minSize) {
    479                     while (curSize < _maxSize) {
     487                if (curSize < _minSize) {
     488                    for (int i = curSize; i < _maxSize; i++) {
    480489                        long curStart = System.currentTimeMillis();
    481                         curSize = addBuilder(precalc(curSize));
     490                        if (!addBuilder(precalc()))
     491                            break;
    482492                        long curCalc = System.currentTimeMillis() - curStart;
    483493                        // for some relief...
    484494                        try {
    485                             Thread.sleep(CALC_DELAY + curCalc * 10);
     495                            Thread.sleep(CALC_DELAY + (curCalc * 3));
    486496                        } catch (InterruptedException ie) { // nop
    487497                        }
    488498                    }
    489499                }
    490                 long end = Clock.getInstance().now();
     500                long end = System.currentTimeMillis();
    491501                int numCalc = curSize - startSize;
    492502                if (numCalc > 0) {
     
    497507                }
    498508                try {
    499                     Thread.sleep(30 * 1000);
     509                    Thread.sleep(_checkDelay);
    500510                } catch (InterruptedException ie) { // nop
    501511                }
     
    503513        }
    504514
    505         private DHSessionKeyBuilder precalc(int i) {
     515        private static DHSessionKeyBuilder precalc() {
    506516            DHSessionKeyBuilder builder = new DHSessionKeyBuilder(false);
    507517            builder.getMyPublicValue();
    508             //_log.debug("Precalc " + i + " complete");
    509518            return builder;
    510519        }
Note: See TracChangeset for help on using the changeset viewer.