Changeset 9286d6a


Ignore:
Timestamp:
Sep 4, 2012 8:33:04 PM (8 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
b8949ea
Parents:
2cddf14
Message:
  • IP Lookup:
    • Add caching in RouterAddress? with secondary caching in Addresses; use caches to speed up transport bids, blocklist checks, geoip lookups, and profile organizer checks (ticket #707)
    • Limit IP cache size in TransportImpl?
    • Clear caches at shutdown
  • RouterAddress?: Remove unused expiration field to save space
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • core/java/src/net/i2p/data/RouterAddress.java

    r2cddf14 r9286d6a  
    1818import java.util.Properties;
    1919
     20import net.i2p.util.Addresses;
    2021import net.i2p.util.OrderedProperties;
    2122
     
    3435public class RouterAddress extends DataStructureImpl {
    3536    private int _cost;
    36     private Date _expiration;
     37    //private Date _expiration;
    3738    private String _transportStyle;
    3839    private final Properties _options;
     40    // cached values
     41    private byte[] _ip;
     42    private int _port;
     43
     44    public static final String PROP_HOST = "host";
     45    public static final String PROP_PORT = "port";
    3946
    4047    public RouterAddress() {
     
    6976     *
    7077     * @deprecated unused for now
     78     * @return null always
    7179     */
    7280    public Date getExpiration() {
    73         return _expiration;
     81        //return _expiration;
     82        return null;
    7483    }
    7584
     
    7887     *
    7988     * Unused for now, always null
     89     * @deprecated unused for now
    8090     */
    8191    public void setExpiration(Date expiration) {
    82         _expiration = expiration;
     92        //_expiration = expiration;
    8393    }
    8494
     
    142152   
    143153    /**
     154     *  Caching version of InetAddress.getByName(getOption("host")).getAddress(), which is slow.
     155     *  Caches numeric host names only.
     156     *  Will resolve but not cache resolution of DNS host names.
     157     *
     158     *  @return IP or null
     159     *  @since 0.9.3
     160     */
     161    public byte[] getIP() {
     162        if (_ip != null)
     163            return _ip;
     164        byte[] rv = null;
     165        String host = _options.getProperty(PROP_HOST);
     166        if (host != null) {
     167            rv = Addresses.getIP(host);
     168            if (rv != null &&
     169                (host.replaceAll("[0-9\\.]", "").length() == 0 ||
     170                 host.replaceAll("[0-9a-fA-F:]", "").length() == 0)) {
     171                _ip = rv;
     172            }
     173        }
     174        return rv;
     175    }
     176   
     177    /**
     178     *  Caching version of Integer.parseInt(getOption("port"))
     179     *  Caches valid ports 1-65535 only.
     180     *
     181     *  @return 1-65535 or 0 if invalid
     182     *  @since 0.9.3
     183     */
     184    public int getPort() {
     185        if (_port != 0)
     186            return _port;
     187        String port = _options.getProperty(PROP_PORT);
     188        if (port != null) {
     189            try {
     190                int rv = Integer.parseInt(port);
     191                if (rv > 0 && rv <= 65535)
     192                    _port = rv;
     193            } catch (NumberFormatException nfe) {}
     194        }
     195        return _port;
     196    }
     197
     198    /**
    144199     *  @throws IllegalStateException if was already read in
    145200     */
     
    148203            throw new IllegalStateException();
    149204        _cost = (int) DataHelper.readLong(in, 1);
    150         _expiration = DataHelper.readDate(in);
     205        //_expiration = DataHelper.readDate(in);
     206        DataHelper.readDate(in);
    151207        _transportStyle = DataHelper.readString(in);
    152208        // reduce Object proliferation
     
    162218            throw new DataFormatException("Not enough data to write a router address");
    163219        DataHelper.writeLong(out, 1, _cost);
    164         DataHelper.writeDate(out, _expiration);
     220        //DataHelper.writeDate(out, _expiration);
     221        DataHelper.writeDate(out, null);
    165222        DataHelper.writeString(out, _transportStyle);
    166223        DataHelper.writeProperties(out, _options);
     
    199256        buf.append("\n\tTransportStyle: ").append(_transportStyle);
    200257        buf.append("\n\tCost: ").append(_cost);
    201         buf.append("\n\tExpiration: ").append(_expiration);
    202         if (_options != null) {
     258        //buf.append("\n\tExpiration: ").append(_expiration);
    203259            buf.append("\n\tOptions: #: ").append(_options.size());
    204260            for (Map.Entry e : _options.entrySet()) {
     
    207263                buf.append("\n\t\t[").append(key).append("] = [").append(val).append("]");
    208264            }
    209         }
    210265        buf.append("]");
    211266        return buf.toString();
  • core/java/src/net/i2p/util/Addresses.java

    r2cddf14 r9286d6a  
    1111import java.net.UnknownHostException;
    1212import java.util.Enumeration;
     13import java.util.LinkedHashMap;
     14import java.util.Map;
    1315import java.util.Set;
    1416import java.util.SortedSet;
    1517import java.util.TreeSet;
    1618
     19import net.i2p.I2PAppContext;
    1720
    1821/**
     
    154157
    155158    /**
     159     *  Textual IP to bytes, because InetAddress.getByName() is slow.
     160     *
     161     *  @since 0.9.3
     162     */
     163    private static final Map<String, byte[]> _IPAddress;
     164
     165    static {
     166        int size;
     167        I2PAppContext ctx = I2PAppContext.getCurrentContext();
     168        if (ctx != null && ctx.isRouterContext()) {
     169            long maxMemory = Runtime.getRuntime().maxMemory();
     170            if (maxMemory == Long.MAX_VALUE)
     171                maxMemory = 96*1024*1024l;
     172            long min = 128;
     173            long max = 4096;
     174            // 512 nominal for 128 MB
     175            size = (int) Math.max(min, Math.min(max, 1 + (maxMemory / (256*1024))));
     176        } else {
     177            size = 32;
     178        }
     179        _IPAddress = new LHMCache(size);
     180    }
     181
     182    /**
     183     *  Caching version of InetAddress.getByName(host).getAddress(), which is slow.
     184     *  Caches numeric host names only.
     185     *  Will resolve but not cache DNS host names.
     186     *
     187     *  @param host DNS or IPv4 or IPv6 host name; if null returns null
     188     *  @return IP or null
     189     *  @since 0.9.3
     190     */
     191    public static byte[] getIP(String host) {
     192        if (host == null)
     193            return null;
     194        byte[] rv;
     195        synchronized (_IPAddress) {
     196            rv = _IPAddress.get(host);
     197        }
     198        if (rv == null) {
     199            try {
     200                rv = InetAddress.getByName(host).getAddress();
     201                if (host.replaceAll("[0-9\\.]", "").length() == 0 ||
     202                    host.replaceAll("[0-9a-fA-F:]", "").length() == 0) {
     203                    synchronized (_IPAddress) {
     204                        _IPAddress.put(host, rv);
     205                    }
     206                }
     207            } catch (UnknownHostException uhe) {}
     208        }
     209        return rv;
     210    }
     211
     212    /**
     213     *  @since 0.9.3
     214     */
     215    public static void clearCaches() {
     216        synchronized(_IPAddress) {
     217            _IPAddress.clear();
     218        }
     219    }
     220
     221    /**
    156222     *  Print out the local addresses
    157223     */
  • router/java/src/net/i2p/router/Blocklist.java

    r2cddf14 r9286d6a  
    2525
    2626import net.i2p.data.Base64;
     27import net.i2p.data.DataHelper;
    2728import net.i2p.data.Hash;
    2829import net.i2p.data.RouterAddress;
     
    439440     */
    440441    public void add(String ip) {
    441         InetAddress pi;
    442         try {
    443             pi = InetAddress.getByName(ip);
    444         } catch (UnknownHostException uhe) {
    445             return;
    446         }
    447         if (pi == null) return;
    448         byte[] pib = pi.getAddress();
     442        byte[] pib = Addresses.getIP(ip);
     443        if (pib == null) return;
    449444        add(pib);
    450445    }
     
    479474        RouterInfo pinfo = _context.netDb().lookupRouterInfoLocally(peer);
    480475        if (pinfo == null) return rv;
    481         String oldphost = null;
     476        byte[] oldpib = null;
    482477        // for each peer address
    483478        for (RouterAddress pa : pinfo.getAddresses()) {
    484             String phost = pa.getOption("host");
    485             if (phost == null) continue;
    486             if (oldphost != null && oldphost.equals(phost)) continue;
    487             oldphost = phost;
    488             InetAddress pi;
    489             try {
    490                 pi = InetAddress.getByName(phost);
    491             } catch (UnknownHostException uhe) {
    492                 continue;
    493             }
    494             if (pi == null) continue;
    495             byte[] pib = pi.getAddress();
     479            byte[] pib = pa.getIP();
     480            if (pib == null) continue;
     481            if (DataHelper.eq(oldpib, pib)) continue;
     482            oldpib = pib;
    496483            rv.add(pib);
    497484         }
     
    521508     */
    522509    public boolean isBlocklisted(String ip) {
    523         InetAddress pi;
    524         try {
    525             pi = InetAddress.getByName(ip);
    526         } catch (UnknownHostException uhe) {
    527             return false;
    528         }
    529         if (pi == null) return false;
    530         byte[] pib = pi.getAddress();
     510        byte[] pib = Addresses.getIP(ip);
     511        if (pib == null) return false;
    531512        return isBlocklisted(pib);
    532513    }
  • router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java

    r2cddf14 r9286d6a  
    12621262            return rv;
    12631263        for (RouterAddress pa : paddr) {
    1264             String phost = pa.getOption("host");
    1265             if (phost == null) continue;
    1266             InetAddress pi;
    1267             try {
    1268                 pi = InetAddress.getByName(phost);
    1269             } catch (UnknownHostException uhe) {
    1270                 continue;
    1271             }
    1272             if (pi == null) continue;
    1273             byte[] pib = pi.getAddress();
     1264            byte[] pib = pa.getIP();
     1265            if (pib == null) continue;
    12741266            rv.add(maskedIP(pib, mask));
    12751267        }
  • router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java

    r2cddf14 r9286d6a  
    6363        if (_manager != null)
    6464            _manager.shutdown();
     65        _geoIP.shutdown();
    6566    }
    6667   
     
    251252        RouterAddress addr = new RouterAddress();
    252253        addr.setCost(NTCPAddress.DEFAULT_COST);
    253         addr.setExpiration(null);
     254        //addr.setExpiration(null);
    254255        addr.setOptions(props);
    255256        addr.setTransportStyle(NTCPTransport.STYLE);
  • router/java/src/net/i2p/router/transport/GeoIP.java

    r2cddf14 r9286d6a  
    2222import net.i2p.router.Router;
    2323import net.i2p.router.RouterContext;
     24import net.i2p.util.Addresses;
    2425import net.i2p.util.ConcurrentHashSet;
    2526import net.i2p.util.Log;
     
    7475
    7576    /**
     77     *  @since 0.9.3
     78     */
     79    public void shutdown() {
     80        _codeToName.clear();
     81        _codeCache.clear();
     82        _IPToCountry.clear();
     83        _pendingSearch.clear();
     84        _notFound.clear();
     85    }
     86
     87    /**
    7688     * Fire off a thread to lookup all pending IPs.
    7789     * There is no indication of completion.
     
    298310     */
    299311    public void add(String ip) {
    300         InetAddress pi;
    301         try {
    302             pi = InetAddress.getByName(ip);
    303         } catch (UnknownHostException uhe) {
    304             return;
    305         }
    306         if (pi == null) return;
    307         byte[] pib = pi.getAddress();
     312        byte[] pib = Addresses.getIP(ip);
     313        if (pib == null) return;
    308314        add(pib);
    309315    }
     
    326332     */
    327333    public String get(String ip) {
    328         InetAddress pi;
    329         try {
    330             pi = InetAddress.getByName(ip);
    331         } catch (UnknownHostException uhe) {
    332             return null;
    333         }
    334         if (pi == null) return null;
    335         byte[] pib = pi.getAddress();
     334        byte[] pib = Addresses.getIP(ip);
     335        if (pib == null) return null;
    336336        return get(pib);
    337337    }
  • router/java/src/net/i2p/router/transport/TransportImpl.java

    r2cddf14 r9286d6a  
    2323import java.util.concurrent.ConcurrentHashMap;
    2424
     25import net.i2p.data.DataHelper;
    2526import net.i2p.data.Hash;
    2627import net.i2p.data.RouterAddress;
     
    3637import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade;
    3738import net.i2p.util.ConcurrentHashSet;
     39import net.i2p.util.LHMCache;
    3840import net.i2p.util.Log;
    3941import net.i2p.util.SimpleScheduler;
     
    5456    private final Set<Hash> _wasUnreachableEntries;
    5557    /** global router ident -> IP */
    56     private static final Map<Hash, byte[]> _IPMap = new ConcurrentHashMap(128);
     58    private static final Map<Hash, byte[]> _IPMap;
     59
     60    static {
     61        long maxMemory = Runtime.getRuntime().maxMemory();
     62        if (maxMemory == Long.MAX_VALUE)
     63            maxMemory = 96*1024*1024l;
     64        long min = 512;
     65        long max = 4096;
     66        // 1024 nominal for 128 MB
     67        int size = (int) Math.max(min, Math.min(max, 1 + (maxMemory / (128*1024))));
     68        _IPMap = new LHMCache(size);
     69    }
    5770
    5871    /**
     
    586599
    587600    public void setIP(Hash peer, byte[] ip) {
    588         _IPMap.put(peer, ip);
    589         _context.commSystem().queueLookup(ip);
     601        byte[] old;
     602        synchronized (_IPMap) {
     603            old = _IPMap.put(peer, ip);
     604        }
     605        if (!DataHelper.eq(old, ip))
     606            _context.commSystem().queueLookup(ip);
    590607    }
    591608
    592609    public static byte[] getIP(Hash peer) {
    593         return _IPMap.get(peer);
     610        synchronized (_IPMap) {
     611            return _IPMap.get(peer);
     612        }
     613    }
     614
     615    /**
     616     *  @since 0.9.3
     617     */
     618    static void clearCaches() {
     619        synchronized(_IPMap) {
     620            _IPMap.clear();
     621        }
    594622    }
    595623
  • router/java/src/net/i2p/router/transport/TransportManager.java

    r2cddf14 r9286d6a  
    186186        stopListening();
    187187        _dhThread.shutdown();
     188        Addresses.clearCaches();
     189        TransportImpl.clearCaches();
    188190    }
    189191   
  • router/java/src/net/i2p/router/transport/ntcp/NTCPAddress.java

    r2cddf14 r9286d6a  
    99 */
    1010
    11 import java.net.InetAddress;
    1211import java.util.Properties;
    1312
     
    1615import net.i2p.data.RouterAddress;
    1716import net.i2p.router.transport.TransportImpl;
     17import net.i2p.util.Addresses;
    1818import net.i2p.util.Log;
    1919
     
    2626    //private InetAddress _addr;
    2727    /** Port number used in RouterAddress definitions */
    28     public final static String PROP_PORT = "port";
     28    public final static String PROP_PORT = RouterAddress.PROP_PORT;
    2929    /** Host name used in RouterAddress definitions */
    30     public final static String PROP_HOST = "host";
     30    public final static String PROP_HOST = RouterAddress.PROP_HOST;
    3131    public static final int DEFAULT_COST = 10;
    3232   
     
    6060            return;
    6161        }
    62         String host = addr.getOption(PROP_HOST);
    63         int iport = -1;
    64         if (host == null) {
    65             _host = null;
    66         } else {
    67             _host = host.trim();
    68             String port = addr.getOption(PROP_PORT);
    69             if ( (port != null) && (port.trim().length() > 0) && !("null".equals(port)) ) {
    70                 try {
    71                     iport = Integer.parseInt(port.trim());
    72                 } catch (NumberFormatException nfe) {
    73                     Log log = I2PAppContext.getGlobalContext().logManager().getLog(NTCPAddress.class);
    74                     log.error("Invalid port [" + port + "]", nfe);
    75                 }
    76             }
    77         }
    78         _port = iport;
     62        _host = addr.getOption(PROP_HOST);
     63        _port = addr.getPort();
    7964    }
    8065   
     
    8671       
    8772        addr.setCost(DEFAULT_COST);
    88         addr.setExpiration(null);
     73        //addr.setExpiration(null);
    8974       
    9075        Properties props = new Properties();
     
    10792        return isPubliclyRoutable(_host);
    10893    }
     94
    10995    public static boolean isPubliclyRoutable(String host) {
    11096        if (host == null) return false;
    111         try {
    112             InetAddress addr = InetAddress.getByName(host);
    113             byte quad[] = addr.getAddress();
    114             // allow ipv6 for ntcpaddress, since we've still got ssu
    115             //if (quad.length != 4) {
    116             //    if (_log.shouldLog(Log.ERROR))
    117             //        _log.error("Refusing IPv6 address (" + host + " / " + addr.getHostAddress() + ") "
    118             //                   + " since not all peers support it, and we don't support restricted routes");
    119             //    return false;
    120             //}
    121             return TransportImpl.isPubliclyRoutable(quad);
    122         } catch (Throwable t) {
    123             //if (_log.shouldLog(Log.WARN))
    124             //    _log.warn("Error checking routability", t);
    125             return false;
    126         }
     97        byte quad[] = Addresses.getIP(host);
     98        return TransportImpl.isPubliclyRoutable(quad);
    12799    }
    128100   
  • router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java

    r2cddf14 r9286d6a  
    299299            return null;
    300300        }
    301         NTCPAddress naddr = new NTCPAddress(addr);
    302         if ( (naddr.getPort() <= 0) || (naddr.getHost() == null) ) {
     301        byte[] ip = addr.getIP();
     302        if ( (addr.getPort() <= 0) || (ip == null) ) {
    303303            _context.statManager().addRateData("ntcp.connectFailedInvalidPort", 1);
    304304            markUnreachable(peer);
     
    308308            return null;
    309309        }
    310         if (!naddr.isPubliclyRoutable()) {
     310        if (!isPubliclyRoutable(ip)) {
    311311            if (! _context.getProperty("i2np.ntcp.allowLocal", "false").equals("true")) {
    312312                _context.statManager().addRateData("ntcp.bidRejectedLocalAddress", 1);
  • router/java/src/net/i2p/router/transport/udp/PeerTestManager.java

    r2cddf14 r9286d6a  
    1010import net.i2p.data.Base64;
    1111import net.i2p.data.DataHelper;
     12import net.i2p.data.RouterAddress;
    1213import net.i2p.data.RouterInfo;
    1314import net.i2p.data.SessionKey;
     
    585586            testInfo.readIntroKey(aliceIntroKey.getData(), 0);
    586587
    587             UDPAddress addr = new UDPAddress(charlieInfo.getTargetAddress(UDPTransport.STYLE));
     588            RouterAddress raddr = charlieInfo.getTargetAddress(UDPTransport.STYLE);
     589            if (raddr == null) {
     590                if (_log.shouldLog(Log.WARN))
     591                    _log.warn("Unable to pick a charlie");
     592                return;
     593            }
     594            UDPAddress addr = new UDPAddress(raddr);
    588595            SessionKey charlieIntroKey = new SessionKey(addr.getIntroKey());
    589596           
  • router/java/src/net/i2p/router/transport/udp/UDPAddress.java

    r2cddf14 r9286d6a  
    1313 */
    1414public class UDPAddress {
    15     private String _host;
     15    private final String _host;
    1616    private InetAddress _hostAddress;
    17     private int _port;
     17    private final int _port;
    1818    private byte[] _introKey;
    1919    private String _introHosts[];
     
    2424    private int _mtu;
    2525   
    26     public static final String PROP_PORT = "port";
    27     public static final String PROP_HOST = "host";
     26    public static final String PROP_PORT = RouterAddress.PROP_PORT;
     27    public static final String PROP_HOST = RouterAddress.PROP_HOST;
    2828    public static final String PROP_INTRO_KEY = "key";
    2929    public static final String PROP_MTU = "mtu";
     
    4141    public UDPAddress(RouterAddress addr) {
    4242        // TODO make everything final
    43         if (addr == null) return;
     43        if (addr == null) {
     44            _host = null;
     45            _port = 0;
     46            return;
     47        }
    4448        _host = addr.getOption(PROP_HOST);
    45         if (_host != null) _host = _host.trim();
    46         try {
    47             String port = addr.getOption(PROP_PORT);
    48             if (port != null)
    49                 _port = Integer.parseInt(port);
    50         } catch (NumberFormatException nfe) {
    51             _port = -1;
    52         }
     49        _port = addr.getPort();
    5350        try {
    5451            String mtu = addr.getOption(PROP_MTU);
     
    147144
    148145    /**
    149      *  @return 0 if unset; -1 if invalid
     146     *  @return 0 if unset or invalid
    150147     */
    151148    public int getPort() { return _port; }
  • router/java/src/net/i2p/router/transport/udp/UDPTransport.java

    r2cddf14 r9286d6a  
    12041204            //if (ua.getIntroducerCount() <= 0) {
    12051205            if (addr.getOption("ihost0") == null) {
    1206                 String host = addr.getOption(UDPAddress.PROP_HOST);
    1207                 String port = addr.getOption(UDPAddress.PROP_PORT);
    1208                 if (host == null || port == null) {
     1206                byte[] ip = addr.getIP();
     1207                int port = addr.getPort();
     1208                if (ip == null || port <= 0 ||
     1209                    (!isValid(ip)) ||
     1210                    Arrays.equals(ip, getExternalIP())) {
    12091211                    markUnreachable(to);
    12101212                    return null;
    1211                 }
    1212                 try {
    1213                     InetAddress ia = InetAddress.getByName(host);
    1214                     int iport = Integer.parseInt(port);
    1215                     if (iport <= 0 || iport > 65535 || (!isValid(ia.getAddress())) ||
    1216                         Arrays.equals(ia.getAddress(), getExternalIP())) {
    1217                         markUnreachable(to);
    1218                         return null;
    1219                     }
    1220                 } catch (UnknownHostException uhe) {
    1221                         markUnreachable(to);
    1222                         return null;
    1223                 } catch (NumberFormatException nfe) {
    1224                         markUnreachable(to);
    1225                         return null;
    12261213                }
    12271214            }
     
    13391326    }
    13401327
     1328    /**
     1329     *  "injected" message from the EstablishmentManager
     1330     */
    13411331    void send(I2NPMessage msg, PeerState peer) {
    13421332        if (_log.shouldLog(Log.DEBUG))
     
    14481438            else
    14491439                addr.setCost(DEFAULT_COST);
    1450             addr.setExpiration(null);
     1440            //addr.setExpiration(null);
    14511441            addr.setTransportStyle(STYLE);
    14521442            addr.setOptions(options);
Note: See TracChangeset for help on using the changeset viewer.