Tunnels: Simplify TunnelId and HopConfig to save space

and reduce object churn and duplication
Fixup tests, javadocs, logging as required
This commit is contained in:
zzz
2020-11-07 13:40:48 +00:00
parent e18708bdbe
commit 5bafdd05a9
14 changed files with 134 additions and 114 deletions

View File

@ -138,17 +138,19 @@ class TunnelRenderer {
if (++displayed > DISPLAY_LIMIT)
continue;
out.write("<tr>");
if (cfg.getReceiveTunnel() != null)
long recv = cfg.getReceiveTunnelId();
if (recv != 0)
out.write("<td class=\"cells\" align=\"center\" title=\"" + _t("Tunnel identity") + "\"><span class=\"tunnel_id\">" +
cfg.getReceiveTunnel().getTunnelId() + "</span></td>");
recv + "</span></td>");
else
out.write("<td class=\"cells\" align=\"center\">n/a</td>");
if (cfg.getReceiveFrom() != null)
out.write("<td class=\"cells\" align=\"center\"><span class=\"tunnel_peer\">" + netDbLink(cfg.getReceiveFrom()) +"</span></td>");
else
out.write("<td class=\"cells\">&nbsp;</td>");
if (cfg.getSendTunnel() != null)
out.write("<td class=\"cells\" align=\"center\" title=\"" + _t("Tunnel identity") + "\"><span class=\"tunnel_id\">" + cfg.getSendTunnel().getTunnelId() +"</span></td>");
long send = cfg.getSendTunnelId();
if (send != 0)
out.write("<td class=\"cells\" align=\"center\" title=\"" + _t("Tunnel identity") + "\"><span class=\"tunnel_id\">" + send +"</span></td>");
else
out.write("<td class=\"cells\">&nbsp;</td>");
if (cfg.getSendTo() != null)

View File

@ -22,9 +22,15 @@ import java.io.OutputStream;
* as the DatabaseStoreMessage uses a zero ID to request
* a direct reply.
*
* 4 bytes, usually of random data.
*
* Not recommended for external use, subject to change.
*
* As of 0.9.48, does NOT extend DataStructureImpl, to save space
*
* @author jrandom
*/
public class TunnelId extends DataStructureImpl {
public class TunnelId {
private long _tunnelId;
public static final long MAX_ID_VALUE = 0xffffffffL;
@ -62,26 +68,6 @@ public class TunnelId extends DataStructureImpl {
DataHelper.writeLong(out, 4, _tunnelId);
}
/**
* Overridden for efficiency.
*/
@Override
public byte[] toByteArray() {
return DataHelper.toLong(4, _tunnelId);
}
/**
* Overridden for efficiency.
* @param data non-null
* @throws DataFormatException if null or wrong length
*/
@Override
public void fromByteArray(byte data[]) throws DataFormatException {
if (data == null) throw new DataFormatException("Null data passed in");
if (data.length != 4) throw new DataFormatException("Bad data length");
_tunnelId = (int) DataHelper.fromLong(data, 0, 4);
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;

View File

@ -16,9 +16,21 @@ package net.i2p.data;
*/
public class TunnelIdTest extends StructureTest {
public DataStructure createDataStructure() throws DataFormatException {
TunnelId id = new TunnelId();
TunnelIdStructure id = new TunnelIdStructure();
id.setTunnelId(42);
return id;
}
public DataStructure createStructureToRead() { return new TunnelId(); }
public DataStructure createStructureToRead() { return new TunnelIdStructure(); }
/**
* so we can test it as a structure
* @since 0.9.48 TunnelId no longer extends DataStructureImpl
*/
private class TunnelIdStructure extends TunnelId implements DataStructure {
public Hash calculateHash() { return null; }
public void fromByteArray(byte[] in) {}
public byte[] toByteArray() { return null; }
public void fromBase64(String in) {}
public String toBase64() { return null; }
}
}

View File

@ -48,20 +48,24 @@ class BatchedRouterPreprocessor extends BatchedPreprocessor {
private static String getName(HopConfig cfg) {
if (cfg == null) return "IB??";
if (cfg.getReceiveTunnel() != null)
return "IB " + cfg.getReceiveTunnel().getTunnelId();
else if (cfg.getSendTunnel() != null)
return "IB " + cfg.getSendTunnel().getTunnelId();
long id = cfg.getReceiveTunnelId();
if (id != 0)
return "IB " + id;
id = cfg.getSendTunnelId();
if (id != 0)
return "IB " + id;
else
return "IB??";
}
private static String getName(TunnelCreatorConfig cfg) {
if (cfg == null) return "OB??";
if (cfg.getReceiveTunnelId(0) != null)
return "OB " + cfg.getReceiveTunnelId(0).getTunnelId();
else if (cfg.getSendTunnelId(0) != null)
return "OB " + cfg.getSendTunnelId(0).getTunnelId();
long id = cfg.getConfig(0).getReceiveTunnelId();
if (id != 0)
return "OB " + id;
id = cfg.getConfig(0).getSendTunnelId();
if (id != 0)
return "OB " + id;
else
return "OB??";
}

View File

@ -15,10 +15,8 @@ import net.i2p.data.TunnelId;
* TunnelCreatorConfig to save space.
*/
public class HopConfig {
private byte _receiveTunnelId[];
private TunnelId _receiveTunnel;
private Hash _receiveFrom;
private byte _sendTunnelId[];
private TunnelId _sendTunnel;
private Hash _sendTo;
private SessionKey _layerKey;
@ -42,41 +40,67 @@ public class HopConfig {
_expiration = -1;
}
/** what tunnel ID are we receiving on? */
public byte[] getReceiveTunnelId() { return _receiveTunnelId; }
/**
* What tunnel ID are we receiving on? (0 if uninitialized)
*/
public long getReceiveTunnelId() { return (_receiveTunnel != null) ? _receiveTunnel.getTunnelId() : 0; }
/**
* What tunnel ID are we receiving on? (null if uninitialized)
*/
public TunnelId getReceiveTunnel() {
if (_receiveTunnel == null)
_receiveTunnel = getTunnel(_receiveTunnelId);
return _receiveTunnel;
}
public void setReceiveTunnelId(byte id[]) { _receiveTunnelId = id; }
public void setReceiveTunnelId(TunnelId id) { _receiveTunnelId = DataHelper.toLong(4, id.getTunnelId()); }
public void setReceiveTunnelId(TunnelId id) { _receiveTunnel = id; }
/**
* @param id 1 to 0xffffffff
* @throws IllegalArgumentException if less than or equal to zero or greater than max value
* @since 0.9.48
*/
public void setReceiveTunnelId(long id) { _receiveTunnel = new TunnelId(id); }
/** what is the previous peer in the tunnel (null if gateway) */
public Hash getReceiveFrom() { return _receiveFrom; }
/**
* Do not set for gateway
*/
public void setReceiveFrom(Hash from) { _receiveFrom = from; }
/** what is the next tunnel ID we are sending to? (null if endpoint) */
public byte[] getSendTunnelId() { return _sendTunnelId; }
/**
* What is the next tunnel ID we are sending to? (0 if endpoint)
*/
public long getSendTunnelId() { return (_sendTunnel != null) ? _sendTunnel.getTunnelId() : 0; }
/** what is the next tunnel we are sending to? (null if endpoint) */
/**
* What is the next tunnel ID we are sending to? (null if endpoint)
*/
public TunnelId getSendTunnel() {
if (_sendTunnel == null)
_sendTunnel = getTunnel(_sendTunnelId);
return _sendTunnel;
}
public void setSendTunnelId(byte id[]) { _sendTunnelId = id; }
private static TunnelId getTunnel(byte id[]) {
if (id == null)
return null;
else
return new TunnelId(DataHelper.fromLong(id, 0, id.length));
}
/**
* Do not set for endpoint
* @since 0.9.48
*/
public void setSendTunnelId(TunnelId id) { _sendTunnel = id; }
/**
* Do not set for endpoint
* @param id 1 to 0xffffffff
* @throws IllegalArgumentException if less than or equal to zero or greater than max value
* @since 0.9.48
*/
public void setSendTunnelId(long id) { _sendTunnel = new TunnelId(id); }
/** what is the next peer in the tunnel (null if endpoint) */
public Hash getSendTo() { return _sendTo; }
/**
* Do not set for endpoint
*/
public void setSendTo(Hash to) { _sendTo = to; }
/** what key should we use to encrypt the layer before passing it on? */
@ -156,16 +180,16 @@ public class HopConfig {
@Override
public String toString() {
StringBuilder buf = new StringBuilder(64);
if (_receiveTunnelId != null) {
if (_receiveTunnel != null) {
buf.append("recv on ");
buf.append(DataHelper.fromLong(_receiveTunnelId, 0, 4));
buf.append(_receiveTunnel.getTunnelId());
buf.append(' ');
}
if (_sendTo != null) {
buf.append("send to ").append(_sendTo.toBase64().substring(0,4)).append(":");
if (_sendTunnelId != null)
buf.append(DataHelper.fromLong(_sendTunnelId, 0, 4));
if (_sendTunnel != null)
buf.append(_sendTunnel.getTunnelId());
}
buf.append(" exp. ").append(new Date(_expiration));

View File

@ -79,6 +79,6 @@ class OutboundTunnelEndpoint {
/** @since 0.9.8 */
@Override
public String toString() {
return "OBEP " + _config.getReceiveTunnel();
return "OBEP " + _config.getReceiveTunnelId();
}
}

View File

@ -48,6 +48,6 @@ class ThrottledPumpedTunnelGateway extends PumpedTunnelGateway {
/** @since 0.9.8 */
@Override
public String toString() {
return "IBGW " + _config.getReceiveTunnel();
return "IBGW " + _config.getReceiveTunnelId();
}
}

View File

@ -96,12 +96,14 @@ public abstract class TunnelCreatorConfig implements TunnelInfo {
* hop 0.
*/
public HopConfig getConfig(int hop) { return _config[hop]; }
/**
* retrieve the tunnelId that the given hop receives messages on.
* the gateway is hop 0.
*
*/
public TunnelId getReceiveTunnelId(int hop) { return _config[hop].getReceiveTunnel(); }
/**
* retrieve the tunnelId that the given hop sends messages on.
* the gateway is hop 0.
@ -354,13 +356,15 @@ public abstract class TunnelCreatorConfig implements TunnelInfo {
for (int i = 0; i < _peers.length; i++) {
buf.append(_peers[i].toBase64().substring(0,4));
buf.append(isEC(i) ? " EC:" : " ElG:");
if (_config[i].getReceiveTunnel() != null)
buf.append(_config[i].getReceiveTunnel());
long id = _config[i].getReceiveTunnelId();
if (id != 0)
buf.append(id);
else
buf.append("me");
if (_config[i].getSendTunnel() != null) {
id = _config[i].getSendTunnelId();
if (id != 0) {
buf.append('.');
buf.append(_config[i].getSendTunnel());
buf.append(id);
} else if (_isInbound || i == 0) {
buf.append(".me");
}

View File

@ -392,13 +392,13 @@ public class TunnelDispatcher implements Service {
* does not fully prevent joinOutbound() from failing later.
* @since 0.9.5
*/
public long getNewOBGWID() {
long rv;
TunnelId tid;
public TunnelId getNewOBGWID() {
long id;
TunnelId rv;
do {
rv = 1 + _context.random().nextLong(TunnelId.MAX_ID_VALUE);
tid = new TunnelId(rv);
} while (_outboundGateways.containsKey(tid));
id = 1 + _context.random().nextLong(TunnelId.MAX_ID_VALUE);
rv = new TunnelId(id);
} while (_outboundGateways.containsKey(rv));
return rv;
}
@ -409,13 +409,13 @@ public class TunnelDispatcher implements Service {
* does not fully prevent joinInbound() from failing later.
* @since 0.9.5
*/
public long getNewIBEPID() {
long rv;
TunnelId tid;
public TunnelId getNewIBEPID() {
long id;
TunnelId rv;
do {
rv = 1 + _context.random().nextLong(TunnelId.MAX_ID_VALUE);
tid = new TunnelId(rv);
} while (_participants.containsKey(tid));
id = 1 + _context.random().nextLong(TunnelId.MAX_ID_VALUE);
rv = new TunnelId(id);
} while (_participants.containsKey(rv));
return rv;
}
@ -426,13 +426,13 @@ public class TunnelDispatcher implements Service {
* does not fully prevent joinInbound() from failing later.
* @since 0.9.5
*/
public long getNewIBZeroHopID() {
long rv;
TunnelId tid;
public TunnelId getNewIBZeroHopID() {
long id;
TunnelId rv;
do {
rv = 1 + _context.random().nextLong(TunnelId.MAX_ID_VALUE);
tid = new TunnelId(rv);
} while (_inboundGateways.containsKey(tid));
id = 1 + _context.random().nextLong(TunnelId.MAX_ID_VALUE);
rv = new TunnelId(id);
} while (_inboundGateways.containsKey(rv));
return rv;
}

View File

@ -864,14 +864,14 @@ class BuildHandler implements Runnable {
return;
}
}
cfg.setReceiveTunnelId(DataHelper.toLong(4, ourId));
cfg.setReceiveTunnelId(ourId);
if (isOutEnd) {
// default
//cfg.setSendTo(null);
//cfg.setSendTunnelId(null);
} else {
cfg.setSendTo(nextPeer);
cfg.setSendTunnelId(DataHelper.toLong(4, nextId));
cfg.setSendTunnelId(nextId);
}
// now "actually" join

View File

@ -89,18 +89,18 @@ abstract class BuildRequestor {
if ( (!isIB) && (i == 0) ) {
// outbound gateway (us) doesn't receive on a tunnel id
if (len <= 1) { // zero hop, pretend to have a send id
long id = ctx.tunnelDispatcher().getNewOBGWID();
hop.setSendTunnelId(DataHelper.toLong(4, id));
TunnelId id = ctx.tunnelDispatcher().getNewOBGWID();
hop.setSendTunnelId(id);
}
} else {
long id;
TunnelId id;
if (isIB && len == 1)
id = ctx.tunnelDispatcher().getNewIBZeroHopID();
else if (isIB && i == len - 1)
id = ctx.tunnelDispatcher().getNewIBEPID();
else
id = 1 + ctx.random().nextLong(TunnelId.MAX_ID_VALUE);
hop.setReceiveTunnelId(DataHelper.toLong(4, id));
id = new TunnelId(1 + ctx.random().nextLong(TunnelId.MAX_ID_VALUE));
hop.setReceiveTunnelId(id);
}
if (i > 0)

View File

@ -14,6 +14,7 @@ import static org.junit.Assert.assertTrue;
import net.i2p.data.DataHelper;
import net.i2p.data.Hash;
import net.i2p.data.TunnelId;
import net.i2p.router.RouterContext;
/**
@ -56,12 +57,12 @@ public class InboundTest extends TestCase {
private TunnelCreatorConfig prepareConfig(int numHops) {
Hash peers[] = new Hash[numHops];
byte tunnelIds[][] = new byte[numHops][4];
long tunnelIds[] = new long[numHops];
for (int i = 0; i < numHops; i++) {
peers[i] = new Hash();
peers[i].setData(new byte[Hash.HASH_LENGTH]);
_context.random().nextBytes(peers[i].getData());
_context.random().nextBytes(tunnelIds[i]);
tunnelIds[i] = 1 + _context.random().nextLong(TunnelId.MAX_ID_VALUE);
}
TunnelCreatorConfig config = new TCConfig(_context, numHops, false);
@ -73,15 +74,10 @@ public class InboundTest extends TestCase {
cfg.setLayerKey(_context.keyGenerator().generateSessionKey());
if (i > 0)
cfg.setReceiveFrom(peers[i-1]);
else
cfg.setReceiveFrom(null);
cfg.setReceiveTunnelId(tunnelIds[i]);
if (i < numHops - 1) {
cfg.setSendTo(peers[i+1]);
cfg.setSendTunnelId(tunnelIds[i+1]);
} else {
cfg.setSendTo(null);
cfg.setSendTunnelId(null);
}
}
return config;

View File

@ -12,6 +12,7 @@ import junit.framework.TestCase;
import net.i2p.data.DataHelper;
import net.i2p.data.Hash;
import net.i2p.data.TunnelId;
import net.i2p.router.RouterContext;
/**
@ -55,12 +56,12 @@ public class OutboundTest extends TestCase{
private TunnelCreatorConfig prepareConfig(int numHops) {
Hash peers[] = new Hash[numHops];
byte tunnelIds[][] = new byte[numHops][4];
long tunnelIds[] = new long[numHops];
for (int i = 0; i < numHops; i++) {
peers[i] = new Hash();
peers[i].setData(new byte[Hash.HASH_LENGTH]);
_context.random().nextBytes(peers[i].getData());
_context.random().nextBytes(tunnelIds[i]);
tunnelIds[i] = 1 + _context.random().nextLong(TunnelId.MAX_ID_VALUE);
}
TunnelCreatorConfig config = new TCConfig(_context, numHops, false);
@ -72,15 +73,10 @@ public class OutboundTest extends TestCase{
cfg.setLayerKey(_context.keyGenerator().generateSessionKey());
if (i > 0)
cfg.setReceiveFrom(peers[i-1]);
else
cfg.setReceiveFrom(null);
cfg.setReceiveTunnelId(tunnelIds[i]);
if (i < numHops - 1) {
cfg.setSendTo(peers[i+1]);
cfg.setSendTunnelId(tunnelIds[i+1]);
} else {
cfg.setSendTo(null);
cfg.setSendTunnelId(null);
}
}
return config;

View File

@ -1,6 +1,7 @@
package net.i2p.router.tunnel;
import net.i2p.data.Hash;
import net.i2p.data.TunnelId;
import net.i2p.data.router.RouterIdentity;
import net.i2p.data.router.RouterInfo;
import net.i2p.router.Router;
@ -34,12 +35,12 @@ public abstract class RouterITBase {
private static TunnelCreatorConfig prepareConfig(int numHops) {
Hash peers[] = new Hash[numHops];
byte tunnelIds[][] = new byte[numHops][4];
long tunnelIds[] = new long[numHops];
for (int i = 0; i < numHops; i++) {
peers[i] = new Hash();
peers[i].setData(new byte[Hash.HASH_LENGTH]);
_context.random().nextBytes(peers[i].getData());
_context.random().nextBytes(tunnelIds[i]);
tunnelIds[i] = 1 + _context.random().nextLong(TunnelId.MAX_ID_VALUE);
}
TunnelCreatorConfig config = new TCConfig(_context, numHops, false);
@ -51,15 +52,10 @@ public abstract class RouterITBase {
cfg.setLayerKey(_context.keyGenerator().generateSessionKey());
if (i > 0)
cfg.setReceiveFrom(peers[i-1]);
else
cfg.setReceiveFrom(null);
cfg.setReceiveTunnelId(tunnelIds[i]);
if (i < numHops - 1) {
cfg.setSendTo(peers[i+1]);
cfg.setSendTunnelId(tunnelIds[i+1]);
} else {
cfg.setSendTo(null);
cfg.setSendTunnelId(null);
}
}
return config;