package com.limegroup.gnutella.filters; import java.util.Iterator; import java.util.LinkedList; import java.util.List; /** * A mutable list of IP addresses. More specifically, a list of sets of * addresses, like "18.239.0.*". Provides fast operations to find if an address * is in the list. Used to implement IPFilter. Not synchronized. * * @author Gregorio Roper */ public class IPList { /** The list of IP's. */ private List /* of IP */ ips = new LinkedList(); public IPList () {} /** * Adds a certain IP to the IPList. * @param ip_str a String containing the IP, see IP.java for formatting */ public void add(String ip_str) { IP ip; try { ip = new IP(ip_str); } catch (IllegalArgumentException e) { return; } if (!ips.contains(ip)) {// don't add the same IP more than once ips.add(ip); } } /** * @param String equal to an IP * @returns true if ip_address is contained somewhere in the list of IPs */ public boolean contains (IP ip) { for (Iterator iter=ips.iterator(); iter.hasNext(); ) { IP pattern=(IP)iter.next(); if (pattern.contains(ip)) return true; } return false; } /** * Calculates the first set bit in the distance between an IPv4 address and * the ranges represented by this list. * * This is equivalent to floor(log2(distance)) + 1. * * @param ip an IPv4 address, represented as an IP object with a /32 netmask. * @return an int on the interval [0,31]. */ public int logMinDistanceTo(IP ip) { int distance = minDistanceTo(ip); int logDistance = 0; int testMask = -1; // All bits set // Guaranteed to terminate since testMask will reach zero while ((distance & testMask) != 0) { testMask <<= 1; ++logDistance; } return logDistance; } /** * Calculates the minimum distance between an IPv4 address this list of IPv4 address ranges. * * @param ip an IPv4 address, represented as an IP object with a /32 netmask. * @return 32-bit unsigned distance (using xor metric), represented as Java int */ public int minDistanceTo(IP ip) { if (ip.getMask() != -1) { throw new IllegalArgumentException("Expected single IP, not an IP range."); } // Note that this function uses xor with Integer.MIN_VALUE // to reverse the sense of the most significant bit. This // causes the "<" and ">" operators to work properly even // though we're representing 32-bit unsinged values as // Java ints. int min_distance = Integer.MAX_VALUE; for (Iterator iter=ips.iterator(); iter.hasNext();) { IP ipRange = (IP) iter.next(); int distance = Integer.MIN_VALUE ^ ipRange.getDistanceTo(ip); if (min_distance > distance) { min_distance = distance; } } // Change the most significant bit back to its normal sense. return Integer.MIN_VALUE ^ min_distance; } }