Changeset ad24f14
- Timestamp:
- Mar 10, 2011 5:59:35 PM (10 years ago)
- Branches:
- master
- Children:
- de815e2
- Parents:
- b6a0426 (diff), a3fb49a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Files:
-
- 25 added
- 7 deleted
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
LICENSE.txt
rb6a0426 rad24f14 73 73 See licenses/LICENSE-InstallCert.txt 74 74 75 BlockFile: 76 Copyright (c) 2006, Matthew Estes 77 See licenses/LICENSE-BlockFile.txt 78 75 79 76 80 Router: -
build.xml
rb6a0426 rad24f14 258 258 doctitle="I2P Javadocs for Release ${release.number} Build ${build.number}" 259 259 windowtitle="I2P Anonymous Network - Java Documentation - Version ${release.number}"> 260 <group title="Core SDK (i2p.jar)" packages="net.i2p:net.i2p.*:net.i2p.client:net.i2p.client.*:net.i2p.internal:net.i2p.internal.*:freenet.support.CPUInformation:org.bouncycastle.crypto:org.bouncycastle.crypto.*:gnu.crypto.*:gnu.gettext:org.xlattice.crypto.filters:com.nettgryppa.security " />260 <group title="Core SDK (i2p.jar)" packages="net.i2p:net.i2p.*:net.i2p.client:net.i2p.client.*:net.i2p.internal:net.i2p.internal.*:freenet.support.CPUInformation:org.bouncycastle.crypto:org.bouncycastle.crypto.*:gnu.crypto.*:gnu.gettext:org.xlattice.crypto.filters:com.nettgryppa.security:net.metanotion.*" /> 261 261 <group title="Streaming Library" packages="net.i2p.client.streaming" /> 262 262 <group title="Router" packages="net.i2p.router:net.i2p.router.*:net.i2p.data.i2np:org.cybergarage.*:org.freenetproject" /> -
core/java/src/net/i2p/I2PAppContext.java
rb6a0426 rad24f14 8 8 9 9 import net.i2p.client.naming.NamingService; 10 import net.i2p.client.naming.PetNameDB;11 10 import net.i2p.crypto.AESEngine; 12 11 import net.i2p.crypto.CryptixAESEngine; … … 73 72 private SessionKeyManager _sessionKeyManager; 74 73 private NamingService _namingService; 75 private PetNameDB _petnameDb;76 74 private ElGamalEngine _elGamalEngine; 77 75 private ElGamalAESEngine _elGamalAESEngine; … … 90 88 private volatile boolean _sessionKeyManagerInitialized; 91 89 private volatile boolean _namingServiceInitialized; 92 private volatile boolean _petnameDbInitialized;93 90 private volatile boolean _elGamalEngineInitialized; 94 91 private volatile boolean _elGamalAESEngineInitialized; … … 178 175 _sessionKeyManager = null; 179 176 _namingService = null; 180 _petnameDb = null;181 177 _elGamalEngine = null; 182 178 _elGamalAESEngine = null; … … 581 577 } 582 578 583 /** @deprecated unused */584 public PetNameDB petnameDb() {585 if (!_petnameDbInitialized)586 initializePetnameDb();587 return _petnameDb;588 }589 590 /** @deprecated unused */591 private void initializePetnameDb() {592 synchronized (this) {593 if (_petnameDb == null) {594 _petnameDb = new PetNameDB();595 }596 _petnameDbInitialized = true;597 }598 }599 600 579 /** 601 580 * This is the ElGamal engine used within this context. While it doesn't -
core/java/src/net/i2p/client/naming/DummyNamingService.java
rb6a0426 rad24f14 8 8 package net.i2p.client.naming; 9 9 10 import java.util.ArrayList; 11 import java.util.HashMap; 12 import java.util.List; 13 import java.util.Map; 14 import java.util.Properties; 15 10 16 import net.i2p.I2PAppContext; 11 17 import net.i2p.data.Destination; 12 18 13 19 /** 14 * A Dummy naming service that can only handle base64 destinations.20 * A Dummy naming service that can only handle base64 and b32 destinations. 15 21 */ 16 22 class DummyNamingService extends NamingService { 23 private final Map<String, CacheEntry> _cache; 24 25 private static final int BASE32_HASH_LENGTH = 52; // 1 + Hash.HASH_LENGTH * 8 / 5 26 public final static String PROP_B32 = "i2p.naming.hostsTxt.useB32"; 27 protected static final int CACHE_MAX_SIZE = 16; 28 public static final int DEST_SIZE = 516; // Std. Base64 length (no certificate) 29 17 30 /** 18 31 * The naming service should only be constructed and accessed through the … … 21 34 * 22 35 */ 23 protected DummyNamingService(I2PAppContext context) { super(context); } 24 private DummyNamingService() { super(null); } 36 protected DummyNamingService(I2PAppContext context) { 37 super(context); 38 _cache = new HashMap(CACHE_MAX_SIZE); 39 } 25 40 26 41 @Override 27 public Destination lookup(String hostname) { 28 return lookupBase64(hostname); 42 public Destination lookup(String hostname, Properties lookupOptions, Properties storedOptions) { 43 Destination d = getCache(hostname); 44 if (d != null) 45 return d; 46 47 // If it's long, assume it's a key. 48 if (hostname.length() >= 516) { 49 d = lookupBase64(hostname); 50 // What the heck, cache these too 51 putCache(hostname, d); 52 return d; 53 } 54 55 // Try Base32 decoding 56 if (hostname.length() == BASE32_HASH_LENGTH + 8 && hostname.endsWith(".b32.i2p") && 57 _context.getBooleanPropertyDefaultTrue(PROP_B32)) { 58 d = LookupDest.lookupBase32Hash(_context, hostname.substring(0, BASE32_HASH_LENGTH)); 59 if (d != null) { 60 putCache(hostname, d); 61 return d; 62 } 63 } 64 65 return null; 66 } 67 68 /** 69 * Provide basic caching for the service 70 * The service may override the age and/or size limit 71 */ 72 /** Don't know why a dest would ever change but keep this short anyway */ 73 protected static final long CACHE_MAX_AGE = 7*60*1000; 74 75 private class CacheEntry { 76 public Destination dest; 77 public long exp; 78 public CacheEntry(Destination d) { 79 dest = d; 80 exp = _context.clock().now() + CACHE_MAX_AGE; 81 } 82 public boolean isExpired() { 83 return exp < _context.clock().now(); 84 } 85 } 86 87 /** 88 * Clean up when full. 89 * Don't bother removing old entries unless full. 90 * Caller must synchronize on _cache. 91 */ 92 private void cacheClean() { 93 if (_cache.size() < CACHE_MAX_SIZE) 94 return; 95 boolean full = true; 96 String oldestKey = null; 97 long oldestExp = Long.MAX_VALUE; 98 List<String> deleteList = new ArrayList(CACHE_MAX_SIZE); 99 for (Map.Entry<String, CacheEntry> entry : _cache.entrySet()) { 100 CacheEntry ce = entry.getValue(); 101 if (ce.isExpired()) { 102 deleteList.add(entry.getKey()); 103 full = false; 104 continue; 105 } 106 if (oldestKey == null || ce.exp < oldestExp) { 107 oldestKey = entry.getKey(); 108 oldestExp = ce.exp; 109 } 110 } 111 if (full && oldestKey != null) 112 deleteList.add(oldestKey); 113 for (String s : deleteList) { 114 _cache.remove(s); 115 } 116 } 117 118 protected void putCache(String s, Destination d) { 119 if (d == null) 120 return; 121 synchronized (_cache) { 122 _cache.put(s, new CacheEntry(d)); 123 cacheClean(); 124 } 125 } 126 127 protected Destination getCache(String s) { 128 synchronized (_cache) { 129 CacheEntry ce = _cache.get(s); 130 if (ce == null) 131 return null; 132 if (ce.isExpired()) { 133 _cache.remove(s); 134 return null; 135 } 136 return ce.dest; 137 } 138 } 139 140 /** @since 0.8.5 */ 141 protected void removeCache(String s) { 142 synchronized (_cache) { 143 _cache.remove(s); 144 } 145 } 146 147 /** @since 0.8.1 */ 148 public void clearCache() { 149 synchronized (_cache) { 150 _cache.clear(); 151 } 29 152 } 30 153 } -
core/java/src/net/i2p/client/naming/EepGetAndAddNamingService.java
rb6a0426 rad24f14 31 31 * 32 32 * @author zzz 33 * @deprecated use HostsTxtNamingService.put() 33 34 * @since 0.7.9 34 35 */ -
core/java/src/net/i2p/client/naming/EepGetNamingService.java
rb6a0426 rad24f14 8 8 import java.util.ArrayList; 9 9 import java.util.List; 10 import java.util.Properties; 10 11 import java.util.StringTokenizer; 11 12 … … 26 27 * Cannot be used as the only NamingService! Be sure any naming service hosts 27 28 * are in hosts.txt. 29 * Supports caching, b32, and b64. 28 30 * 29 31 * Sample config to put in configadvanced.jsp (restart required): … … 34 36 * 35 37 */ 36 public class EepGetNamingService extends NamingService {38 public class EepGetNamingService extends DummyNamingService { 37 39 38 40 private final static String PROP_EEPGET_LIST = "i2p.naming.eepget.list"; … … 60 62 61 63 @Override 62 public Destination lookup(String hostname ) {63 // If it's long, assume it's a key.64 if ( hostname.length() >= DEST_SIZE)65 return lookupBase64(hostname);64 public Destination lookup(String hostname, Properties lookupOptions, Properties storedOptions) { 65 Destination d = super.lookup(hostname, null, null); 66 if (d != null) 67 return d; 66 68 67 69 hostname = hostname.toLowerCase(); 68 69 // If you want b32, chain with HostsTxtNamingService70 if (hostname.length() == 60 && hostname.endsWith(".b32.i2p"))71 return null;72 73 // check the cache74 Destination d = getCache(hostname);75 if (d != null)76 return d;77 70 78 71 List URLs = getURLs(); … … 104 97 105 98 // FIXME allow larger Dests for non-null Certs 106 private static final int DEST_SIZE = 516; // Std. Base64 length (no certificate)107 99 private static final int MAX_RESPONSE = DEST_SIZE + 68 + 10; // allow for hostname= and some trailing stuff 108 100 private String fetchAddr(String url, String hostname) { -
core/java/src/net/i2p/client/naming/ExecNamingService.java
rb6a0426 rad24f14 6 6 7 7 import java.io.InputStream; 8 import java.util.Properties; 8 9 9 10 import net.i2p.I2PAppContext; … … 28 29 * Can be used from MetaNamingService, (e.g. after HostsTxtNamingService), 29 30 * or as the sole naming service. 31 * Supports caching, b32, and b64. 30 32 * 31 33 * Sample chained config to put in configadvanced.jsp (restart required): … … 41 43 * 42 44 */ 43 public class ExecNamingService extends NamingService {45 public class ExecNamingService extends DummyNamingService { 44 46 45 47 private final static String PROP_EXEC_CMD = "i2p.naming.exec.command"; … … 60 62 61 63 @Override 62 public Destination lookup(String hostname ) {63 // If it's long, assume it's a key.64 if ( hostname.length() >= DEST_SIZE)65 return lookupBase64(hostname);64 public Destination lookup(String hostname, Properties lookupOptions, Properties storedOptions) { 65 Destination d = super.lookup(hostname, null, null); 66 if (d != null) 67 return d; 66 68 67 69 hostname = hostname.toLowerCase(); 68 69 // If you want b32, chain with HostsTxtNamingService70 if (hostname.length() == 60 && hostname.endsWith(".b32.i2p"))71 return null;72 73 // check the cache74 Destination d = getCache(hostname);75 if (d != null)76 return d;77 70 78 71 // lookup … … 88 81 89 82 // FIXME allow larger Dests for non-null Certs 90 private static final int DEST_SIZE = 516; // Std. Base64 length (no certificate)91 83 private static final int MAX_RESPONSE = DEST_SIZE + 68 + 10; // allow for hostname= and some trailing stuff 92 84 private String fetchAddr(String hostname) { -
core/java/src/net/i2p/client/naming/HostsTxtNamingService.java
rb6a0426 rad24f14 8 8 package net.i2p.client.naming; 9 9 10 import java.io.BufferedReader;11 import java.io.File;12 import java.io.FileInputStream;13 import java.io.InputStreamReader;14 import java.io.IOException;15 10 import java.util.ArrayList; 16 import java.util.Iterator;17 11 import java.util.List; 18 12 import java.util.Properties; 19 import java.util.Set;20 13 import java.util.StringTokenizer; 21 14 22 15 import net.i2p.I2PAppContext; 23 import net.i2p.data.DataFormatException;24 import net.i2p.data.DataHelper;25 16 import net.i2p.data.Destination; 26 import net.i2p.data.Hash;27 import net.i2p.util.Log;28 17 29 18 /** 30 * A naming service based on the "hosts.txt" file. 19 * A naming service based on multiple "hosts.txt" files. 20 * Supports .b32.i2p and {b64} lookups. 21 * Supports caching. 22 * All host names are converted to lower case. 31 23 */ 32 public class HostsTxtNamingService extends NamingService {24 public class HostsTxtNamingService extends MetaNamingService { 33 25 34 26 /** … … 38 30 * 39 31 */ 40 public HostsTxtNamingService(I2PAppContext context) { super(context); } 41 private HostsTxtNamingService() { super(null); } 32 public HostsTxtNamingService(I2PAppContext context) { 33 super(context, null); 34 for (String name : getFilenames()) { 35 addNamingService(new SingleFileNamingService(context, name), false); 36 } 37 } 42 38 43 39 /** … … 46 42 */ 47 43 public final static String PROP_HOSTS_FILE = "i2p.hostsfilelist"; 48 public final static String PROP_B32 = "i2p.naming.hostsTxt.useB32";49 44 50 /** default hosts.txt filename */45 /** default hosts.txt filenames */ 51 46 public final static String DEFAULT_HOSTS_FILE = 52 47 "privatehosts.txt,userhosts.txt,hosts.txt"; 53 48 54 private final static Log _log = new Log(HostsTxtNamingService.class); 55 56 private List getFilenames() { 49 private List<String> getFilenames() { 57 50 String list = _context.getProperty(PROP_HOSTS_FILE, DEFAULT_HOSTS_FILE); 58 51 StringTokenizer tok = new StringTokenizer(list, ","); 59 List rv = new ArrayList(tok.countTokens());52 List<String> rv = new ArrayList(tok.countTokens()); 60 53 while (tok.hasMoreTokens()) 61 54 rv.add(tok.nextToken()); … … 63 56 } 64 57 65 private static final int BASE32_HASH_LENGTH = 52; // 1 + Hash.HASH_LENGTH * 8 / 5 58 @Override 59 public Destination lookup(String hostname, Properties lookupOptions, Properties storedOptions) { 60 // If it's long, assume it's a key. 61 if (hostname.length() >= DEST_SIZE) 62 return lookupBase64(hostname); 63 return super.lookup(hostname.toLowerCase(), lookupOptions, storedOptions); 64 } 66 65 67 66 @Override 68 public Destination lookup(String hostname) { 69 Destination d = getCache(hostname); 70 if (d != null) 71 return d; 72 73 // If it's long, assume it's a key. 74 if (hostname.length() >= 516) { 75 d = lookupBase64(hostname); 76 // What the heck, cache these too 77 putCache(hostname, d); 78 return d; 79 } 80 81 // Try Base32 decoding 82 if (hostname.length() == BASE32_HASH_LENGTH + 8 && hostname.endsWith(".b32.i2p") && 83 Boolean.valueOf(_context.getProperty(PROP_B32, "true")).booleanValue()) { 84 d = LookupDest.lookupBase32Hash(_context, hostname.substring(0, BASE32_HASH_LENGTH)); 85 if (d != null) { 86 putCache(hostname, d); 87 return d; 88 } 89 } 90 91 List filenames = getFilenames(); 92 for (int i = 0; i < filenames.size(); i++) { 93 String hostsfile = (String)filenames.get(i); 94 try { 95 File f = new File(_context.getRouterDir(), hostsfile); 96 if ( (f.exists()) && (f.canRead()) ) { 97 String key = getKey(f, hostname.toLowerCase()); 98 if ( (key != null) && (key.trim().length() > 0) ) { 99 d = lookupBase64(key); 100 putCache(hostname, d); 101 return d; 102 } 103 104 } else { 105 _log.warn("Hosts file " + hostsfile + " does not exist."); 106 } 107 } catch (Exception ioe) { 108 _log.error("Error loading hosts file " + hostsfile, ioe); 109 } 110 // not found, continue to the next file 111 } 112 return null; 113 } 114 115 @Override 116 public String reverseLookup(Destination dest) { 117 String destkey = dest.toBase64(); 118 List filenames = getFilenames(); 119 for (int i = 0; i < filenames.size(); i++) { 120 String hostsfile = (String)filenames.get(i); 121 Properties hosts = new Properties(); 122 try { 123 File f = new File(_context.getRouterDir(), hostsfile); 124 if ( (f.exists()) && (f.canRead()) ) { 125 DataHelper.loadProps(hosts, f, true); 126 Set keyset = hosts.keySet(); 127 Iterator iter = keyset.iterator(); 128 while (iter.hasNext()) { 129 String host = (String)iter.next(); 130 String key = hosts.getProperty(host); 131 if (destkey.equals(key)) 132 return host; 133 } 134 } 135 } catch (Exception ioe) { 136 _log.error("Error loading hosts file " + hostsfile, ioe); 137 } 138 } 139 return null; 67 public boolean put(String hostname, Destination d, Properties options) { 68 return super.put(hostname.toLowerCase(), d, options); 140 69 } 141 70 142 /** @deprecated unused */143 71 @Override 144 public String reverseLookup(Hash h) { 145 List filenames = getFilenames(); 146 for (int i = 0; i < filenames.size(); i++) { 147 String hostsfile = (String)filenames.get(i); 148 Properties hosts = new Properties(); 149 try { 150 File f = new File(_context.getRouterDir(), hostsfile); 151 if ( (f.exists()) && (f.canRead()) ) { 152 DataHelper.loadProps(hosts, f, true); 153 Set keyset = hosts.keySet(); 154 Iterator iter = keyset.iterator(); 155 while (iter.hasNext()) { 156 String host = (String)iter.next(); 157 String key = hosts.getProperty(host); 158 try { 159 Destination destkey = new Destination(); 160 destkey.fromBase64(key); 161 if (h.equals(destkey.calculateHash())) 162 return host; 163 } catch (DataFormatException dfe) {} 164 } 165 } 166 } catch (Exception ioe) { 167 _log.error("Error loading hosts file " + hostsfile, ioe); 168 } 169 } 170 return null; 72 public boolean putIfAbsent(String hostname, Destination d, Properties options) { 73 return super.putIfAbsent(hostname.toLowerCase(), d, options); 171 74 } 172 75 173 /** 174 * Better than DataHelper.loadProps(), doesn't load the whole file into memory, 175 * and stops when it finds a match. 176 * 177 * @param host lower case 178 * @since 0.7.13 179 */ 180 private static String getKey(File file, String host) throws IOException { 181 BufferedReader in = null; 182 try { 183 in = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"), 16*1024); 184 String line = null; 185 while ( (line = in.readLine()) != null) { 186 if (!line.toLowerCase().startsWith(host + '=')) 187 continue; 188 if (line.indexOf('#') > 0) // trim off any end of line comment 189 line = line.substring(0, line.indexOf('#')).trim(); 190 int split = line.indexOf('='); 191 return line.substring(split+1); //.trim() ?????????????? 192 } 193 } finally { 194 if (in != null) try { in.close(); } catch (IOException ioe) {} 195 } 196 return null; 76 @Override 77 public boolean remove(String hostname, Properties options) { 78 return super.remove(hostname.toLowerCase(), options); 197 79 } 198 80 } -
core/java/src/net/i2p/client/naming/MetaNamingService.java
rb6a0426 rad24f14 3 3 import java.lang.reflect.Constructor; 4 4 import java.util.ArrayList; 5 import java.util.Collections; 5 6 import java.util.Iterator; 6 7 import java.util.List; 8 import java.util.Properties; 7 9 import java.util.StringTokenizer; 10 import java.util.concurrent.CopyOnWriteArrayList; 8 11 9 12 import net.i2p.I2PAppContext; 10 13 import net.i2p.data.Destination; 11 14 12 public class MetaNamingService extends NamingService { 15 /** 16 * A naming service of multiple naming services. 17 * Supports .b32.i2p and {b64} lookups. 18 * Supports caching. 19 */ 20 public class MetaNamingService extends DummyNamingService { 13 21 14 22 private final static String PROP_NAME_SERVICES = "i2p.nameservicelist"; 15 23 private final static String DEFAULT_NAME_SERVICES = 16 "net.i2p.client.naming.PetNameNamingService,net.i2p.client.naming.HostsTxtNamingService"; 17 private List _services; 24 "net.i2p.client.naming.HostsTxtNamingService"; 25 26 protected final List<NamingService> _services; 18 27 19 28 public MetaNamingService(I2PAppContext context) { 20 29 super(context); 21 22 30 String list = _context.getProperty(PROP_NAME_SERVICES, DEFAULT_NAME_SERVICES); 23 31 StringTokenizer tok = new StringTokenizer(list, ","); 24 _services = new ArrayList(tok.countTokens());32 _services = new CopyOnWriteArrayList(); 25 33 while (tok.hasMoreTokens()) { 26 34 try { 27 35 Class cls = Class.forName(tok.nextToken()); 28 36 Constructor con = cls.getConstructor(new Class[] { I2PAppContext.class }); 29 _services.add(con.newInstance(new Object[] { context }));37 addNamingService((NamingService)con.newInstance(new Object[] { context }), false); 30 38 } catch (Exception ex) { 31 _services.add(new DummyNamingService(context)); // fallback 39 } 40 } 41 } 42 43 /** 44 * @param if non-null, services to be added. If null, this will only handle b32 and b64. 45 * @since 0.8.5 46 */ 47 public MetaNamingService(I2PAppContext context, List<NamingService> services) { 48 super(context); 49 _services = new CopyOnWriteArrayList(); 50 if (services != null) { 51 for (NamingService ns : services) { 52 addNamingService(ns, false); 32 53 } 33 54 } … … 35 56 36 57 @Override 37 public Destination lookup(String hostname) { 38 Iterator iter = _services.iterator(); 39 while (iter.hasNext()) { 40 NamingService ns = (NamingService)iter.next(); 41 Destination dest = ns.lookup(hostname); 42 if (dest != null) { 43 return dest; 58 public boolean addNamingService(NamingService ns, boolean head) { 59 if (head) 60 _services.add(0, ns); 61 else 62 _services.add(ns); 63 return true; 64 } 65 66 @Override 67 public List<NamingService> getNamingServices() { 68 return Collections.unmodifiableList(_services); 69 } 70 71 @Override 72 public boolean removeNamingService(NamingService ns) { 73 return _services.remove(ns); 74 } 75 76 @Override 77 public void registerListener(NamingServiceListener nsl) { 78 for (NamingService ns : _services) { 79 ns.registerListener(nsl); 80 } 81 } 82 83 @Override 84 public void unregisterListener(NamingServiceListener nsl) { 85 for (NamingService ns : _services) { 86 ns.unregisterListener(nsl); 87 } 88 } 89 90 @Override 91 public Destination lookup(String hostname, Properties lookupOptions, Properties storedOptions) { 92 Destination d = super.lookup(hostname, null, null); 93 if (d != null) 94 return d; 95 96 for (NamingService ns : _services) { 97 d = ns.lookup(hostname, lookupOptions, storedOptions); 98 if (d != null) { 99 putCache(hostname, d); 100 return d; 44 101 } 45 102 } 46 return lookupBase64(hostname);103 return null; 47 104 } 48 105 49 106 @Override 50 public String reverseLookup(Destination dest) { 51 Iterator iter = _services.iterator(); 52 while (iter.hasNext()) { 53 NamingService ns = (NamingService)iter.next(); 54 String hostname = ns.reverseLookup(dest); 55 if (hostname != null) { 56 return hostname; 107 public String reverseLookup(Destination dest, Properties options) { 108 for (NamingService ns : _services) { 109 String host = ns.reverseLookup(dest, options); 110 if (host != null) { 111 return host; 57 112 } 58 113 } … … 60 115 } 61 116 117 /** 118 * Stores in the last service 119 */ 120 @Override 121 public boolean put(String hostname, Destination d, Properties options) { 122 if (_services.isEmpty()) 123 return false; 124 boolean rv = _services.get(_services.size() - 1).put(hostname, d, options); 125 // overwrite any previous entry in case it changed 126 if (rv) 127 putCache(hostname, d); 128 return rv; 129 } 130 131 /** 132 * Stores in the last service 133 */ 134 @Override 135 public boolean putIfAbsent(String hostname, Destination d, Properties options) { 136 if (_services.isEmpty()) 137 return false; 138 return _services.get(_services.size() - 1).putIfAbsent(hostname, d, options); 139 } 140 141 /** 142 * Removes from all services 143 */ 144 @Override 145 public boolean remove(String hostname, Properties options) { 146 boolean rv = false; 147 for (NamingService ns : _services) { 148 if (ns.remove(hostname, options)) 149 rv = true; 150 } 151 if (rv) 152 removeCache(hostname); 153 return rv; 154 } 62 155 } -
core/java/src/net/i2p/client/naming/NamingService.java
rb6a0426 rad24f14 10 10 import java.lang.reflect.Constructor; 11 11 import java.util.ArrayList; 12 import java.util. HashMap;12 import java.util.Collections; 13 13 import java.util.Iterator; 14 import java.util.List; 14 15 import java.util.Map; 16 import java.util.Properties; 17 import java.util.Set; 18 import java.util.concurrent.CopyOnWriteArraySet; 15 19 16 20 import net.i2p.I2PAppContext; … … 26 30 27 31 private final static Log _log = new Log(NamingService.class); 28 protected I2PAppContext _context;29 pr ivate /* FIXME final FIXME */ HashMap _cache;32 protected final I2PAppContext _context; 33 protected final Set<NamingServiceListener> _listeners; 30 34 31 35 /** what classname should be used as the naming service impl? */ 32 36 public static final String PROP_IMPL = "i2p.naming.impl"; 33 37 private static final String DEFAULT_IMPL = "net.i2p.client.naming.HostsTxtNamingService"; 34 35 protected static final int CACHE_MAX_SIZE = 16;36 37 38 38 39 /** … … 44 45 protected NamingService(I2PAppContext context) { 45 46 _context = context; 46 _cache = new HashMap(CACHE_MAX_SIZE); 47 } 48 private NamingService() { // nop 47 _listeners = new CopyOnWriteArraySet(); 49 48 } 50 49 … … 54 53 * <code>null</code> if name is unknown. 55 54 */ 56 public abstract Destination lookup(String hostname); 55 public Destination lookup(String hostname) { 56 return lookup(hostname, null, null); 57 } 57 58 58 59 /** … … 62 63 * <code>null</code> if no reverse lookup is possible. 63 64 */ 64 public String reverseLookup(Destination dest) { return null; }; 65 public String reverseLookup(Destination dest) { 66 return reverseLookup(dest, null); 67 } 65 68 66 69 /** @deprecated unused */ 67 public String reverseLookup(Hash h) { return null; } ;70 public String reverseLookup(Hash h) { return null; } 68 71 69 72 /** … … 83 86 } 84 87 88 ///// New API Starts Here 89 90 /** 91 * @return Class simple name by default 92 * @since 0.8.5 93 */ 94 public String getName() { 95 return getClass().getSimpleName(); 96 } 97 98 /** 99 * @return NamingService-specific options or null 100 * @since 0.8.5 101 */ 102 public Properties getConfiguration() { 103 return null; 104 } 105 106 /** 107 * @return success 108 * @since 0.8.5 109 */ 110 public boolean setConfiguration(Properties p) { 111 return true; 112 } 113 114 // These are for daisy chaining (MetaNamingService) 115 116 /** 117 * @return chained naming services or null 118 * @since 0.8.5 119 */ 120 public List<NamingService> getNamingServices() { 121 return null; 122 } 123 124 /** 125 * @return parent naming service or null if this is the root 126 * @since 0.8.5 127 */ 128 public NamingService getParent() { 129 return null; 130 } 131 132 /** 133 * Only for chaining-capable NamingServices. Add to end of the list. 134 * @return success 135 */ 136 public boolean addNamingService(NamingService ns) { 137 return addNamingService(ns, false); 138 } 139 140 141 /** 142 * Only for chaining-capable NamingServices 143 * @param head or tail 144 * @return success 145 */ 146 public boolean addNamingService(NamingService ns, boolean head) { 147 return false; 148 } 149 150 /** 151 * Only for chaining-capable NamingServices 152 * @return success 153 * @since 0.8.5 154 */ 155 public boolean removeNamingService(NamingService ns) { 156 return false; 157 } 158 159 // options would be used to specify public / private / master ... 160 // or should we just daisy chain 3 HostsTxtNamingServices ? 161 // that might be better... then addressbook only talks to the 'router' HostsTxtNamingService 162 163 /** 164 * @return number of entries or -1 if unknown 165 * @since 0.8.5 166 */ 167 public int size() { 168 return size(null); 169 } 170 171 /** 172 * @param options NamingService-specific, can be null 173 * @return number of entries (matching the options if non-null) or -1 if unknown 174 * @since 0.8.5 175 */ 176 public int size(Properties options) { 177 return -1; 178 } 179 180 /** 181 * @return all mappings 182 * or empty Map if none; 183 * Returned Map is not necessarily sorted, implementation dependent 184 * @since 0.8.5 185 */ 186 public Map<String, Destination> getEntries() { 187 return getEntries(null); 188 } 189 190 /** 191 * @param options NamingService-specific, can be null 192 * @return all mappings (matching the options if non-null) 193 * or empty Map if none; 194 * Returned Map is not necessarily sorted, implementation dependent 195 * @since 0.8.5 196 */ 197 public Map<String, Destination> getEntries(Properties options) { 198 return Collections.EMPTY_MAP; 199 } 200 201 /** 202 * This may be more or less efficient than getEntries() 203 * @param options NamingService-specific, can be null 204 * @return all mappings (matching the options if non-null) 205 * or empty Map if none; 206 * Returned Map is not necessarily sorted, implementation dependent 207 * @since 0.8.5 208 */ 209 public Map<String, String> getBase64Entries(Properties options) { 210 return Collections.EMPTY_MAP; 211 } 212 213 /** 214 * @return all known host names 215 * or empty Set if none; 216 * Returned Set is not necessarily sorted, implementation dependent 217 * @since 0.8.5 218 */ 219 public Set<String> getNames() { 220 return getNames(null); 221 } 222 223 /** 224 * @param options NamingService-specific, can be null 225 * @return all known host names (matching the options if non-null) 226 * or empty Set if none; 227 * Returned Set is not necessarily sorted, implementation dependent 228 * @since 0.8.5 229 */ 230 public Set<String> getNames(Properties options) { 231 return Collections.EMPTY_SET; 232 } 233 234 /** 235 * @return success 236 * @since 0.8.5 237 */ 238 public boolean put(String hostname, Destination d) { 239 return put(hostname, d, null); 240 } 241 242 /** 243 * @param options NamingService-specific, can be null 244 * @return success 245 * @since 0.8.5 246 */ 247 public boolean put(String hostname, Destination d, Properties options) { 248 return false; 249 } 250 251 /** 252 * Fails if entry previously exists 253 * @return success 254 * @since 0.8.5 255 */ 256 public boolean putIfAbsent(String hostname, Destination d) { 257 return putIfAbsent(hostname, d, null); 258 } 259 260 /** 261 * Fails if entry previously exists 262 * @param options NamingService-specific, can be null 263 * @return success 264 * @since 0.8.5 265 */ 266 public boolean putIfAbsent(String hostname, Destination d, Properties options) { 267 return false; 268 } 269 270 /** 271 * @param options NamingService-specific, can be null 272 * @return success 273 * @since 0.8.5 274 */ 275 public boolean putAll(Map<String, Destination> entries, Properties options) { 276 boolean rv = true; 277 for (Map.Entry<String, Destination> entry : entries.entrySet()) { 278 if (!put(entry.getKey(), entry.getValue(), options)) 279 rv = false; 280 } 281 return rv; 282 } 283 284 /** 285 * Fails if entry did not previously exist 286 * @param d may be null if only options are changing 287 * @param options NamingService-specific, can be null 288 * @return success 289 * @since 0.8.5 290 */ 291 public boolean update(String hostname, Destination d, Properties options) { 292 return false; 293 } 294 295 /** 296 * @return success 297 * @since 0.8.5 298 */ 299 public boolean remove(String hostname) { 300 return remove(hostname, null); 301 } 302 303 /** 304 * @param options NamingService-specific, can be null 305 * @return success 306 * @since 0.8.5 307 */ 308 public boolean remove(String hostname, Properties options) { 309 return false; 310 } 311 312 /** 313 * Ask the NamingService to update its database 314 * Should this be a separate interface? This is what addressbook needs 315 * @param options NamingService-specific, can be null 316 * @since 0.8.5 317 */ 318 public void requestUpdate(Properties options) {} 319 320 /** 321 * @since 0.8.5 322 */ 323 public void registerListener(NamingServiceListener nsl) { 324 _listeners.add(nsl); 325 } 326 327 /** 328 * @since 0.8.5 329 */ 330 public void unregisterListener(NamingServiceListener nsl) { 331 _listeners.remove(nsl); 332 } 333 334 /** 335 * Same as lookup(hostname) but with in and out options 336 * Note that whether this (and lookup(hostname)) resolve B32 addresses is 337 * NamingService-specific. 338 * @param lookupOptions input parameter, NamingService-specific, can be null 339 * @param storedOptions output parameter, NamingService-specific, any stored properties will be added if non-null 340 * @return dest or null 341 * @since 0.8.5 342 */ 343 public abstract Destination lookup(String hostname, Properties lookupOptions, Properties storedOptions); 344 345 /** 346 * Same as reverseLookup(dest) but with options 347 * @param options NamingService-specific, can be null 348 * @return host name or null 349 * @since 0.8.5 350 */ 351 public String reverseLookup(Destination d, Properties options) { 352 return null; 353 } 354 355 /** 356 * Lookup a Base 32 address. This may require the router to fetch the LeaseSet, 357 * which may take quite a while. 358 * @param hostname must be {52 chars}.b32.i2p 359 * @param timeout in seconds; <= 0 means use router default 360 * @return dest or null 361 * @since 0.8.5 362 */ 363 public Destination lookupBase32(String hostname, int timeout) { 364 return null; 365 } 366 367 /** 368 * Same as lookupB32 but with the SHA256 Hash precalculated 369 * @param timeout in seconds; <= 0 means use router default 370 * @return dest or null 371 * @since 0.8.5 372 */ 373 public Destination lookup(Hash hash, int timeout) { 374 return null; 375 } 376 377 /** 378 * Parent will call when added. 379 * If this is the root naming service, the core will start it. 380 * Should not be called by others. 381 * @since 0.8.5 382 */ 383 public void start() {} 384 385 /** 386 * Parent will call when removed. 387 * If this is the root naming service, the core will stop it. 388 * Should not be called by others. 389 * @since 0.8.5 390 */ 391 public void stop() {} 392 393 //// End New API 394 85 395 /** 86 396 * Get a naming service instance. This method ensures that there … … 97 407 instance = (NamingService)con.newInstance(new Object[] { context }); 98 408 } catch (Exception ex) { 99 _log.error("Cannot load Naming service implementation", ex);409 _log.error("Cannot load naming service " + impl, ex); 100 410 instance = new DummyNamingService(context); // fallback 101 411 } … … 103 413 } 104 414 105 /**106 * Provide basic caching for the service107 * The service may override the age and/or size limit108 */109 /** Don't know why a dest would ever change but keep this short anyway */110 protected static final long CACHE_MAX_AGE = 7*60*1000;111 112 private class CacheEntry {113 public Destination dest;114 public long exp;115 public CacheEntry(Destination d) {116 dest = d;117 exp = _context.clock().now() + CACHE_MAX_AGE;118 }119 public boolean isExpired() {120 return exp < _context.clock().now();121 }122 }123 124 /**125 * Clean up when full.126 * Don't bother removing old entries unless full.127 * Caller must synchronize on _cache.128 */129 private void cacheClean() {130 if (_cache.size() < CACHE_MAX_SIZE)131 return;132 boolean full = true;133 Object oldestKey = null;134 long oldestExp = Long.MAX_VALUE;135 ArrayList deleteList = new ArrayList(CACHE_MAX_SIZE);136 for (Iterator iter = _cache.entrySet().iterator(); iter.hasNext(); ) {137 Map.Entry entry = (Map.Entry) iter.next();138 CacheEntry ce = (CacheEntry) entry.getValue();139 if (ce.isExpired()) {140 deleteList.add(entry.getKey());141 full = false;142 continue;143 }144 if (oldestKey == null || ce.exp < oldestExp) {145 oldestKey = entry.getKey();146 oldestExp = ce.exp;147 }148 }149 if (full && oldestKey != null)150 deleteList.add(oldestKey);151 for (Iterator iter = deleteList.iterator(); iter.hasNext(); ) {152 _cache.remove(iter.next());153 }154 }155 156 protected void putCache(String s, Destination d) {157 if (d == null)158 return;159 synchronized (_cache) {160 _cache.put(s, new CacheEntry(d));161 cacheClean();162 }163 }164 165 protected Destination getCache(String s) {166 synchronized (_cache) {167 CacheEntry ce = (CacheEntry) _cache.get(s);168 if (ce == null)169 return null;170 if (ce.isExpired()) {171 _cache.remove(s);172 return null;173 }174 return ce.dest;175 }176 }177 178 /** @since 0.8.1 */179 public void clearCache() {180 synchronized (_cache) {181 _cache.clear();182 }183 }184 415 }
Note: See TracChangeset
for help on using the changeset viewer.