forked from I2P_Developers/i2p.i2p
* I2NP:
- 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:
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user