diff --git a/core/java/src/net/i2p/data/DataHelper.java b/core/java/src/net/i2p/data/DataHelper.java index c393cbf4c1..aebe83f2e6 100644 --- a/core/java/src/net/i2p/data/DataHelper.java +++ b/core/java/src/net/i2p/data/DataHelper.java @@ -139,18 +139,23 @@ public class DataHelper { * * As of 0.9.18, throws DataFormatException on duplicate key * - * @param props the Properties to load into + * @param props The Properties to load into. + * As of 0.9.38, if null, a new OrderedProperties will be created. * @param rawStream stream to read the mapping from * @throws DataFormatException if the format is invalid * @throws IOException if there is a problem reading the data - * @return the parameter props + * @return the parameter props, or (as of 0.9.38) a new OrderedProperties if props is null, + * and an immutable EmptyProperties if empty. * @since 0.8.13 */ public static Properties readProperties(InputStream rawStream, Properties props) throws DataFormatException, IOException { int size = (int) readLong(rawStream, 2); - if (size == 0) - return props; + if (size == 0) { + return (props != null) ? props : EmptyProperties.INSTANCE; + } + if (props == null) + props = new OrderedProperties(); byte data[] = new byte[size]; // full read guaranteed read(rawStream, data); @@ -454,7 +459,7 @@ public class DataHelper { public static void loadProps(Properties props, InputStream inStr, boolean forceLowerCase) throws IOException { BufferedReader in = null; try { - in = new BufferedReader(new InputStreamReader(inStr, "UTF-8"), 16*1024); + in = new BufferedReader(new InputStreamReader(inStr, "UTF-8"), 4*1024); String line = null; while ( (line = in.readLine()) != null) { if (line.trim().length() <= 0) continue; diff --git a/core/java/src/net/i2p/data/EmptyProperties.java b/core/java/src/net/i2p/data/EmptyProperties.java new file mode 100644 index 0000000000..56f79dee8e --- /dev/null +++ b/core/java/src/net/i2p/data/EmptyProperties.java @@ -0,0 +1,61 @@ +package net.i2p.data; + +import java.io.InputStream; +import java.io.Reader; +import java.util.Map; + +import net.i2p.util.OrderedProperties; + +/** + * Immutable OrderedProperties, to reduce object churn + * in LS2 where it's expected to be empty. + * Returned from DataHelper.readProperties(in, null). + * + * All methods that modify will throw UnsupportedOperationException, + * except clear() and remove() which do nothing. + * + * @since 0.9.38 + */ +public class EmptyProperties extends OrderedProperties { + + public static final EmptyProperties INSTANCE = new EmptyProperties(); + + private EmptyProperties() { + super(); + } + + @Override + public String getProperty(String key) { + return null; + } + + @Override + public void load(InputStream inStream) { + throw new UnsupportedOperationException(); + } + + @Override + public void load(Reader reader) { + throw new UnsupportedOperationException(); + } + + @Override + public void loadFromXML(InputStream in) { + throw new UnsupportedOperationException(); + } + + @Override + public Object put(Object key, Object value) { + throw new UnsupportedOperationException(); + } + + @Override + public void putAll(Map t) { + throw new UnsupportedOperationException(); + } + + @Override + public Object setProperty(String key, String value) { + throw new UnsupportedOperationException(); + } +} diff --git a/core/java/src/net/i2p/data/Lease2.java b/core/java/src/net/i2p/data/Lease2.java index bac163f8cf..902f97ebc5 100644 --- a/core/java/src/net/i2p/data/Lease2.java +++ b/core/java/src/net/i2p/data/Lease2.java @@ -6,12 +6,16 @@ import java.io.OutputStream; import java.util.Date; /** - * Like Lease but with 4-byte timestamps + * Like Lease but with 4-byte timestamps. + * Length is 40. + * * PRELIMINARY - Subject to change - see proposal 123 * * @since 0.9.38 */ public class Lease2 extends Lease { + + public static final int LENGTH = 40; @Override public void readBytes(InputStream in) throws DataFormatException, IOException { diff --git a/core/java/src/net/i2p/data/LeaseSet.java b/core/java/src/net/i2p/data/LeaseSet.java index 18aa3609bf..8af1af2f68 100644 --- a/core/java/src/net/i2p/data/LeaseSet.java +++ b/core/java/src/net/i2p/data/LeaseSet.java @@ -142,9 +142,8 @@ public class LeaseSet extends DatabaseEntry { /** * The revocation key. - * @deprecated unused + * Undeprecated as of 0.9.38, used for the blinded key in EncryptedLeaseSet. */ - @Deprecated public SigningPublicKey getSigningKey() { return _signingKey; } diff --git a/core/java/src/net/i2p/data/LeaseSet2.java b/core/java/src/net/i2p/data/LeaseSet2.java index 50d311ca8a..353c05906a 100644 --- a/core/java/src/net/i2p/data/LeaseSet2.java +++ b/core/java/src/net/i2p/data/LeaseSet2.java @@ -227,7 +227,8 @@ public class LeaseSet2 extends LeaseSet { // LS2 header readHeader(in); // LS2 part - _options = DataHelper.readProperties(in); + // null arg to get an EmptyProperties back + _options = DataHelper.readProperties(in, null); int numKeys = in.read(); if (numKeys <= 0 || numKeys > MAX_KEYS) throw new DataFormatException("Bad key count: " + numKeys); @@ -369,7 +370,7 @@ public class LeaseSet2 extends LeaseSet { public int size() { int rv = _destination.size() + 10 - + (_leases.size() * 40); + + (_leases.size() * Lease2.LENGTH); for (PublicKey key : getEncryptionKeys()) { rv += 4; rv += key.length(); diff --git a/core/java/src/net/i2p/data/MetaLease.java b/core/java/src/net/i2p/data/MetaLease.java index 3c85a5b44f..dad2a344c7 100644 --- a/core/java/src/net/i2p/data/MetaLease.java +++ b/core/java/src/net/i2p/data/MetaLease.java @@ -18,7 +18,10 @@ import java.util.Date; */ public class MetaLease extends Lease { + public static final int LENGTH = 40; + private int _cost; + private int _type; public int getCost() { return _cost; @@ -28,6 +31,14 @@ public class MetaLease extends Lease { _cost = cost; } + public int getType() { + return _type; + } + + public void setType(int type) { + _type = type; + } + /** * @throws UnsupportedOperationException always */ @@ -48,7 +59,8 @@ public class MetaLease extends Lease { public void readBytes(InputStream in) throws DataFormatException, IOException { _gateway = Hash.create(in); // flags - DataHelper.skip(in, 3); + DataHelper.skip(in, 2); + _type = in.read(); _cost = in.read(); _end = new Date(DataHelper.readLong(in, 4) * 1000); } @@ -59,7 +71,8 @@ public class MetaLease extends Lease { throw new DataFormatException("Not enough data to write out a Lease"); _gateway.writeBytes(out); // flags - DataHelper.writeLong(out, 3, 0); + DataHelper.writeLong(out, 2, 0); + out.write(_type); out.write(_cost); DataHelper.writeLong(out, 4, _end.getTime() / 1000); } @@ -70,6 +83,7 @@ public class MetaLease extends Lease { if ((object == null) || !(object instanceof MetaLease)) return false; MetaLease lse = (MetaLease) object; return DataHelper.eq(_end, lse.getEndDate()) + && _type == lse._type && _cost == lse._cost && DataHelper.eq(_gateway, lse.getGateway()); } @@ -87,6 +101,7 @@ public class MetaLease extends Lease { buf.append("\n\tEnd Date: ").append(_end); buf.append("\n\tTarget: ").append(_gateway); buf.append("\n\tCost: ").append(_cost); + buf.append("\n\tType: ").append(_type); buf.append("]"); return buf.toString(); } diff --git a/core/java/src/net/i2p/data/MetaLeaseSet.java b/core/java/src/net/i2p/data/MetaLeaseSet.java index 24b4ba7eee..e20736913d 100644 --- a/core/java/src/net/i2p/data/MetaLeaseSet.java +++ b/core/java/src/net/i2p/data/MetaLeaseSet.java @@ -53,7 +53,8 @@ public class MetaLeaseSet extends LeaseSet2 { // LS2 header readHeader(in); // Meta LS2 part - _options = DataHelper.readProperties(in); + // null arg to get an EmptyProperties back + _options = DataHelper.readProperties(in, null); int numLeases = in.read(); //if (numLeases > MAX_META_LEASES) // throw new DataFormatException("Too many leases - max is " + MAX_META_LEASES); @@ -106,7 +107,7 @@ public class MetaLeaseSet extends LeaseSet2 { public int size() { int rv = _destination.size() + 10 - + (_leases.size() * 40); + + (_leases.size() * MetaLease.LENGTH); if (isOffline()) rv += 6 + _transientSigningPublicKey.length() + _offlineSignature.length(); if (_options != null && !_options.isEmpty()) { @@ -209,11 +210,12 @@ public class MetaLeaseSet extends LeaseSet2 { rand.nextBytes(gw); l2.setGateway(new Hash(gw)); l2.setCost(i * 5); + l2.setType(((i & 0x01) == 0) ? KEY_TYPE_LS2 : KEY_TYPE_META_LS2); ls2.addLease(l2); } java.util.Properties opts = new java.util.Properties(); - opts.setProperty("foo", "bar"); - opts.setProperty("test", "bazzle"); + //opts.setProperty("foo", "bar"); + //opts.setProperty("test", "bazzle"); ls2.setOptions(opts); ls2.setDestination(pkf.getDestination()); SigningPrivateKey spk = pkf.getSigningPrivKey();