- Deprecate unused stream methods and I2NPMessageReader since
      all transports provide encapsulation.
    - Don't throw IOE from byte array methods
    - Use cached null cert in GarlicClove
    - Add method to limit size of buffer to read
    - Don't check checksum at input, in most cases
    - Reuse checksum at output, for unomodified pass-through messages
      (but recalculating it now and logging on a mismatch for testing)
    - Fix DatabaseLookupMessage to internally store the don't include peers as
      a List, not a Set, so it doesn't get reordered and break the checksum
    - Log cleanup
  * NTCP:
    - Zero-copy and limit size when handing buffer to I2NP
    - Log hex dump message on I2NPMessageException, like in SSU
    - Don't close connection on I2NPMessageException
This commit is contained in:
zzz
2011-12-11 21:04:43 +00:00
parent 032b7d8230
commit 8448001a17
22 changed files with 671 additions and 284 deletions

View File

@@ -8,9 +8,11 @@ package net.i2p.data.i2np;
*
*/
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import net.i2p.I2PAppContext;
@@ -25,13 +27,14 @@ import net.i2p.data.TunnelId;
*
* @author jrandom
*/
public class DatabaseLookupMessage extends I2NPMessageImpl {
public class DatabaseLookupMessage extends FastI2NPMessageImpl {
//private final static Log _log = new Log(DatabaseLookupMessage.class);
public final static int MESSAGE_TYPE = 2;
private Hash _key;
private Hash _fromHash;
private TunnelId _replyTunnel;
private Set<Hash> _dontIncludePeers;
/** this must be kept as a list to preserve the order and not break the checksum */
private List<Hash> _dontIncludePeers;
//private static volatile long _currentLookupPeriod = 0;
//private static volatile int _currentLookupCount = 0;
@@ -102,36 +105,109 @@ public class DatabaseLookupMessage extends I2NPMessageImpl {
* Defines the key being searched for
*/
public Hash getSearchKey() { return _key; }
public void setSearchKey(Hash key) { _key = key; }
/**
* @throws IllegalStateException if key previously set, to protect saved checksum
*/
public void setSearchKey(Hash key) {
if (_key != null)
throw new IllegalStateException();
_key = key;
}
/**
* Contains the router who requested this lookup
*
*/
public Hash getFrom() { return _fromHash; }
public void setFrom(Hash from) { _fromHash = from; }
/**
* @throws IllegalStateException if from previously set, to protect saved checksum
*/
public void setFrom(Hash from) {
if (_fromHash != null)
throw new IllegalStateException();
_fromHash = from;
}
/**
* Contains the tunnel ID a reply should be sent to
*
*/
public TunnelId getReplyTunnel() { return _replyTunnel; }
public void setReplyTunnel(TunnelId replyTunnel) { _replyTunnel = replyTunnel; }
/**
* @throws IllegalStateException if tunnel previously set, to protect saved checksum
*/
public void setReplyTunnel(TunnelId replyTunnel) {
if (_replyTunnel != null)
throw new IllegalStateException();
_replyTunnel = replyTunnel;
}
/**
* Set of peers that a lookup reply should NOT include
* Set of peers that a lookup reply should NOT include.
* WARNING - returns a copy.
*
* @return Set of Hash objects, each of which is the H(routerIdentity) to skip
* @return Set of Hash objects, each of which is the H(routerIdentity) to skip, or null
*/
public Set<Hash> getDontIncludePeers() { return _dontIncludePeers; }
public void setDontIncludePeers(Set peers) {
public Set<Hash> getDontIncludePeers() {
if (_dontIncludePeers == null)
return null;
return new HashSet(_dontIncludePeers);
}
/**
* Replace the dontInclude set with this set.
* WARNING - makes a copy.
* Invalidates the checksum.
*
* @param peers may be null
*/
public void setDontIncludePeers(Collection<Hash> peers) {
_hasChecksum = false;
if (peers != null)
_dontIncludePeers = new HashSet(peers);
_dontIncludePeers = new ArrayList(peers);
else
_dontIncludePeers = null;
}
/**
* Add to the set.
* Invalidates the checksum.
*
* @param peer non-null
* @since 0.8.12
*/
public void addDontIncludePeer(Hash peer) {
if (_dontIncludePeers == null)
_dontIncludePeers = new ArrayList();
else if (_dontIncludePeers.contains(peer))
return;
_hasChecksum = false;
_dontIncludePeers.add(peer);
}
/**
* Add to the set.
* Invalidates the checksum.
*
* @param peers non-null
* @since 0.8.12
*/
public void addDontIncludePeers(Collection<Hash> peers) {
_hasChecksum = false;
if (_dontIncludePeers == null) {
_dontIncludePeers = new ArrayList(peers);
} else {
for (Hash peer : peers) {
if (!_dontIncludePeers.contains(peer))
_dontIncludePeers.add(peer);
}
}
}
public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException, IOException {
public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException {
if (type != MESSAGE_TYPE) throw new I2NPMessageException("Message type is incorrect for this message");
int curIndex = offset;
@@ -170,7 +246,7 @@ public class DatabaseLookupMessage extends I2NPMessageImpl {
if ( (numPeers < 0) || (numPeers > MAX_NUM_PEERS) )
throw new I2NPMessageException("Invalid number of peers - " + numPeers);
Set<Hash> peers = new HashSet(numPeers);
List<Hash> peers = new ArrayList(numPeers);
for (int i = 0; i < numPeers; i++) {
//byte peer[] = new byte[Hash.HASH_LENGTH];
//System.arraycopy(data, curIndex, peer, 0, Hash.HASH_LENGTH);
@@ -220,8 +296,7 @@ public class DatabaseLookupMessage extends I2NPMessageImpl {
byte len[] = DataHelper.toLong(2, size);
out[curIndex++] = len[0];
out[curIndex++] = len[1];
for (Iterator<Hash> iter = _dontIncludePeers.iterator(); iter.hasNext(); ) {
Hash peer = iter.next();
for (Hash peer : _dontIncludePeers) {
System.arraycopy(peer.getData(), 0, out, curIndex, Hash.HASH_LENGTH);
curIndex += Hash.HASH_LENGTH;
}
@@ -233,9 +308,9 @@ public class DatabaseLookupMessage extends I2NPMessageImpl {
@Override
public int hashCode() {
return DataHelper.hashCode(getSearchKey()) +
DataHelper.hashCode(getFrom()) +
DataHelper.hashCode(getReplyTunnel()) +
return DataHelper.hashCode(_key) +
DataHelper.hashCode(_fromHash) +
DataHelper.hashCode(_replyTunnel) +
DataHelper.hashCode(_dontIncludePeers);
}
@@ -243,10 +318,10 @@ public class DatabaseLookupMessage extends I2NPMessageImpl {
public boolean equals(Object object) {
if ( (object != null) && (object instanceof DatabaseLookupMessage) ) {
DatabaseLookupMessage msg = (DatabaseLookupMessage)object;
return DataHelper.eq(getSearchKey(),msg.getSearchKey()) &&
DataHelper.eq(getFrom(),msg.getFrom()) &&
DataHelper.eq(getReplyTunnel(),msg.getReplyTunnel()) &&
DataHelper.eq(_dontIncludePeers,msg.getDontIncludePeers());
return DataHelper.eq(_key, msg._key) &&
DataHelper.eq(_fromHash, msg._fromHash) &&
DataHelper.eq(_replyTunnel, msg._replyTunnel) &&
DataHelper.eq(_dontIncludePeers, msg._dontIncludePeers);
} else {
return false;
}
@@ -256,9 +331,9 @@ public class DatabaseLookupMessage extends I2NPMessageImpl {
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append("[DatabaseLookupMessage: ");
buf.append("\n\tSearch Key: ").append(getSearchKey());
buf.append("\n\tFrom: ").append(getFrom());
buf.append("\n\tReply Tunnel: ").append(getReplyTunnel());
buf.append("\n\tSearch Key: ").append(_key);
buf.append("\n\tFrom: ").append(_fromHash);
buf.append("\n\tReply Tunnel: ").append(_replyTunnel);
buf.append("\n\tDont Include Peers: ");
if (_dontIncludePeers != null)
buf.append(_dontIncludePeers.size());