package net.i2p.router.transport.udp;

import net.i2p.util.ObjectCounter;
import net.i2p.util.SimpleTimer;
import net.i2p.util.SimpleTimer2;
import net.i2p.util.SipHash;

/**
 * Count IPs
 *
 * @since 0.9.3
 */
class IPThrottler {
    private ObjectCounter<Integer> _counter;
    private final int _max;

    public IPThrottler(int max, long time) {
        _max = max;
        _counter = new ObjectCounter<Integer>();
        SimpleTimer2.getInstance().addPeriodicEvent(new Cleaner(), time);
    }

    /**
     *  Increments before checking
     */
    public boolean shouldThrottle(byte[] ip) {
        // for IPv4 we simply use the IP;
        // for IPv6 we use a hash of the first 8 bytes
        Integer key;
        if (ip.length == 4)
            key = toInt(ip);
        else
            key = hashCode(ip);
        return _counter.increment(key) > _max;
    }

    private static Integer toInt(byte ip[]) {
        int rv = 0;
        for (int i = 0; i < 4; i++)
            rv |= (ip[i] & 0xff) << ((3-i)*8);
        return Integer.valueOf(rv);
    }

    /** @since 0.9.55 */
    private static Integer hashCode(byte ip[]) {
        int rv = 0;
        for (int i = 0; i < 8; i++) {
            rv ^= ip[i] << (i * 4);
        }
        return Integer.valueOf(rv);
    }

    private class Cleaner implements SimpleTimer.TimedEvent {
        public void timeReached() {
            _counter.clear();
        }
    }
}
