diff --git a/router/java/src/net/i2p/data/i2np/GarlicClove.java b/router/java/src/net/i2p/data/i2np/GarlicClove.java index 834412065e1d35de64ec537c624e4cc2d5254d12..3145284466aa297f40c591e2ff80c9335ad697d3 100644 --- a/router/java/src/net/i2p/data/i2np/GarlicClove.java +++ b/router/java/src/net/i2p/data/i2np/GarlicClove.java @@ -13,11 +13,11 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.Date; +import net.i2p.I2PAppContext; import net.i2p.data.Certificate; import net.i2p.data.DataFormatException; import net.i2p.data.DataHelper; import net.i2p.data.DataStructureImpl; -import net.i2p.router.RouterContext; import net.i2p.util.Log; /** @@ -29,19 +29,17 @@ import net.i2p.util.Log; * @author jrandom */ public class GarlicClove extends DataStructureImpl { - private final Log _log; - //private final RouterContext _context; + //private final Log _log; + private final I2PAppContext _context; private DeliveryInstructions _instructions; private I2NPMessage _msg; private long _cloveId; private Date _expiration; private Certificate _certificate; - private final I2NPMessageHandler _handler; - public GarlicClove(RouterContext context) { - //_context = context; - _log = context.logManager().getLog(GarlicClove.class); - _handler = new I2NPMessageHandler(context); + public GarlicClove(I2PAppContext context) { + _context = context; + //_log = context.logManager().getLog(GarlicClove.class); _cloveId = -1; } @@ -58,8 +56,11 @@ public class GarlicClove extends DataStructureImpl { /** * @deprecated unused, use byte array method to avoid copying + * @throws UnsupportedOperationException always */ public void readBytes(InputStream in) throws DataFormatException, IOException { + throw new UnsupportedOperationException(); +/**** _instructions = new DeliveryInstructions(); _instructions.readBytes(in); if (_log.shouldLog(Log.DEBUG)) @@ -78,17 +79,22 @@ public class GarlicClove extends DataStructureImpl { _certificate = Certificate.create(in); if (_log.shouldLog(Log.DEBUG)) _log.debug("Read cert: " + _certificate); +****/ } + /** + * + */ public int readBytes(byte source[], int offset) throws DataFormatException { int cur = offset; _instructions = new DeliveryInstructions(); cur += _instructions.readBytes(source, cur); - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Read instructions: " + _instructions); + //if (_log.shouldLog(Log.DEBUG)) + // _log.debug("Read instructions: " + _instructions); try { - cur += _handler.readMessage(source, cur); - _msg = _handler.lastRead(); + I2NPMessageHandler handler = new I2NPMessageHandler(_context); + cur += handler.readMessage(source, cur); + _msg = handler.lastRead(); } catch (I2NPMessageException ime) { throw new DataFormatException("Unable to read the message from a garlic clove", ime); } @@ -96,21 +102,24 @@ public class GarlicClove extends DataStructureImpl { cur += 4; _expiration = DataHelper.fromDate(source, cur); cur += DataHelper.DATE_LENGTH; - if (_log.shouldLog(Log.DEBUG)) - _log.debug("CloveID read: " + _cloveId + " expiration read: " + _expiration); + //if (_log.shouldLog(Log.DEBUG)) + // _log.debug("CloveID read: " + _cloveId + " expiration read: " + _expiration); //_certificate = new Certificate(); //cur += _certificate.readBytes(source, cur); _certificate = Certificate.create(source, cur); cur += _certificate.size(); - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Read cert: " + _certificate); + //if (_log.shouldLog(Log.DEBUG)) + // _log.debug("Read cert: " + _certificate); return cur - offset; } /** * @deprecated unused, use byte array method to avoid copying + * @throws UnsupportedOperationException always */ public void writeBytes(OutputStream out) throws DataFormatException, IOException { + throw new UnsupportedOperationException(); +/**** StringBuilder error = null; if (_instructions == null) { if (error == null) error = new StringBuilder(); @@ -158,15 +167,19 @@ public class GarlicClove extends DataStructureImpl { _certificate.writeBytes(out); if (_log.shouldLog(Log.DEBUG)) _log.debug("Written cert: " + _certificate); +****/ } + /** + * + */ @Override public byte[] toByteArray() { byte rv[] = new byte[estimateSize()]; int offset = 0; offset += _instructions.writeBytes(rv, offset); - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Wrote instructions: " + _instructions); + //if (_log.shouldLog(Log.DEBUG)) + // _log.debug("Wrote instructions: " + _instructions); //offset += _msg.toByteArray(rv); try { byte m[] = _msg.toByteArray(); @@ -178,8 +191,10 @@ public class GarlicClove extends DataStructureImpl { DataHelper.toDate(rv, offset, _expiration.getTime()); offset += DataHelper.DATE_LENGTH; offset += _certificate.writeBytes(rv, offset); - if (offset != rv.length) - _log.log(Log.CRIT, "Clove offset: " + offset + " but estimated length: " + rv.length); + if (offset != rv.length) { + Log log = I2PAppContext.getGlobalContext().logManager().getLog(GarlicClove.class); + log.error("Clove offset: " + offset + " but estimated length: " + rv.length); + } return rv; } @@ -196,31 +211,31 @@ public class GarlicClove extends DataStructureImpl { if ( (obj == null) || !(obj instanceof GarlicClove)) return false; GarlicClove clove = (GarlicClove)obj; - return DataHelper.eq(getCertificate(), clove.getCertificate()) && - _cloveId == clove.getCloveId() && - DataHelper.eq(getData(), clove.getData()) && - DataHelper.eq(getExpiration(), clove.getExpiration()) && - DataHelper.eq(getInstructions(), clove.getInstructions()); + return DataHelper.eq(_certificate, clove._certificate) && + _cloveId == clove._cloveId && + DataHelper.eq(_msg, clove._msg) && + DataHelper.eq(_expiration, clove._expiration) && + DataHelper.eq(_instructions, clove._instructions); } @Override public int hashCode() { - return DataHelper.hashCode(getCertificate()) + - (int)getCloveId() + - DataHelper.hashCode(getData()) + - DataHelper.hashCode(getExpiration()) + - DataHelper.hashCode(getInstructions()); + return DataHelper.hashCode(_certificate) ^ + (int) _cloveId ^ + DataHelper.hashCode(_msg) ^ + DataHelper.hashCode(_expiration) ^ + DataHelper.hashCode(_instructions); } @Override public String toString() { StringBuilder buf = new StringBuilder(128); buf.append("[GarlicClove: "); - buf.append("\n\tInstructions: ").append(getInstructions()); - buf.append("\n\tCertificate: ").append(getCertificate()); - buf.append("\n\tClove ID: ").append(getCloveId()); - buf.append("\n\tExpiration: ").append(getExpiration()); - buf.append("\n\tData: ").append(getData()); + buf.append("\n\tInstructions: ").append(_instructions); + buf.append("\n\tCertificate: ").append(_certificate); + buf.append("\n\tClove ID: ").append(_cloveId); + buf.append("\n\tExpiration: ").append(_expiration); + buf.append("\n\tData: ").append(_msg); buf.append("]"); return buf.toString(); } diff --git a/router/java/src/net/i2p/router/message/CloveSet.java b/router/java/src/net/i2p/router/message/CloveSet.java index caa5e1bff3bfb76b5e7a535afa2b5261915c700d..d03289931a165f719193098f0a7f9411192e5e54 100644 --- a/router/java/src/net/i2p/router/message/CloveSet.java +++ b/router/java/src/net/i2p/router/message/CloveSet.java @@ -8,45 +8,47 @@ package net.i2p.router.message; * */ -import java.util.ArrayList; -import java.util.List; - import net.i2p.data.Certificate; import net.i2p.data.i2np.GarlicClove; /** - * Wrap up the data contained in a CloveMessage after being decrypted + * Wrap up the data contained in a GarlicMessage after being decrypted * */ class CloveSet { - private final List<GarlicClove> _cloves; - private Certificate _cert; - private long _msgId; - private long _expiration; + private final GarlicClove[] _cloves; + private final Certificate _cert; + private final long _msgId; + private final long _expiration; - public CloveSet() { - _cloves = new ArrayList<GarlicClove>(4); - _msgId = -1; - _expiration = -1; + /** + * @param cloves non-null, all entries non-null + * @param cert non-null + */ + public CloveSet(GarlicClove[] cloves, Certificate cert, long msgId, long expiration) { + _cloves = cloves; + _cert = cert; + _msgId = msgId; + _expiration = expiration; } - public int getCloveCount() { return _cloves.size(); } - public void addClove(GarlicClove clove) { _cloves.add(clove); } - public GarlicClove getClove(int index) { return _cloves.get(index); } + public int getCloveCount() { return _cloves.length; } + + /** @throws AIOOBE */ + public GarlicClove getClove(int index) { return _cloves[index]; } public Certificate getCertificate() { return _cert; } - public void setCertificate(Certificate cert) { _cert = cert; } + public long getMessageId() { return _msgId; } - public void setMessageId(long id) { _msgId = id; } + public long getExpiration() { return _expiration; } - public void setExpiration(long expiration) { _expiration = expiration; } @Override public String toString() { StringBuilder buf = new StringBuilder(128); buf.append("{"); - for (int i = 0; i < _cloves.size(); i++) { - GarlicClove clove = _cloves.get(i); + for (int i = 0; i < _cloves.length; i++) { + GarlicClove clove = _cloves[i]; if (clove.getData() != null) buf.append(clove.getData().getClass().getName()).append(", "); else diff --git a/router/java/src/net/i2p/router/message/GarlicMessageParser.java b/router/java/src/net/i2p/router/message/GarlicMessageParser.java index 083ffd8c3759968356d8d5b85460b93809ebc059..11b0d40c9ed69eb8513aa3a95a5997389610a68f 100644 --- a/router/java/src/net/i2p/router/message/GarlicMessageParser.java +++ b/router/java/src/net/i2p/router/message/GarlicMessageParser.java @@ -28,6 +28,12 @@ class GarlicMessageParser { private final Log _log; private final RouterContext _context; + /** + * Huge limit just to reduce chance of trouble. Typ. usage is 3. + * As of 0.9.12. Was 255. + */ + private static final int MAX_CLOVES = 32; + public GarlicMessageParser(RouterContext context) { _context = context; _log = _context.logManager().getLog(GarlicMessageParser.class); @@ -64,18 +70,19 @@ class GarlicMessageParser { private CloveSet readCloveSet(byte data[]) throws DataFormatException { int offset = 0; - CloveSet set = new CloveSet(); - int numCloves = (int)DataHelper.fromLong(data, offset, 1); offset++; if (_log.shouldLog(Log.DEBUG)) _log.debug("# cloves to read: " + numCloves); + if (numCloves <= 0 || numCloves > MAX_CLOVES) + throw new DataFormatException("bad clove count " + numCloves); + GarlicClove[] cloves = new GarlicClove[numCloves]; for (int i = 0; i < numCloves; i++) { //if (_log.shouldLog(Log.DEBUG)) // _log.debug("Reading clove " + i); GarlicClove clove = new GarlicClove(_context); offset += clove.readBytes(data, offset); - set.addClove(clove); + cloves[i] = clove; //if (_log.shouldLog(Log.DEBUG)) // _log.debug("After reading clove " + i); } @@ -85,11 +92,10 @@ class GarlicMessageParser { offset += cert.size(); long msgId = DataHelper.fromLong(data, offset, 4); offset += 4; - Date expiration = DataHelper.fromDate(data, offset); + //Date expiration = DataHelper.fromDate(data, offset); + long expiration = DataHelper.fromLong(data, offset, 8); - set.setCertificate(cert); - set.setMessageId(msgId); - set.setExpiration(expiration.getTime()); + CloveSet set = new CloveSet(cloves, cert, msgId, expiration); return set; } }