forked from I2P_Developers/i2p.i2p
- Add getRecordCount() to TunnelBuildMessage and TunnelBuildReplyMessage so they can be extended. - New I2NP Messages VariableTunnelBuildMessage and VariableTunnelBuildReplyMessage, which contain the number of request slots in them. - Convert all static assumptions of 8 slots to getRecordCount() - Use the new VTBM if all hops in the tunnel and the OBEP or IBGW of the reply tunnel support it, and the tunnel is 4 hops or shorter. - Reply to a VTBM with a VTBRM of the same size - Make BuildReplyHandler static - Convert the currentlyBuilding List to a ConcurrentHashMap to speed reply lookups and eliminate a global lock; don't put fallback tunnels in there - Add new tunnel.corruptBuildReply stat - Various cleanups and javadoc Tested as compatible with current network, new messages untested.
72 lines
2.7 KiB
Java
72 lines
2.7 KiB
Java
package net.i2p.data.i2np;
|
|
|
|
import java.io.IOException;
|
|
|
|
import net.i2p.I2PAppContext;
|
|
import net.i2p.data.ByteArray;
|
|
import net.i2p.data.DataHelper;
|
|
|
|
/**
|
|
* Transmitted from the new outbound endpoint to the creator through a
|
|
* reply tunnel
|
|
*
|
|
* @since 0.7.11
|
|
*/
|
|
public class VariableTunnelBuildReplyMessage extends TunnelBuildReplyMessage {
|
|
public static final int MESSAGE_TYPE = 24;
|
|
|
|
/** zero record count, will be set with readMessage() */
|
|
public VariableTunnelBuildReplyMessage(I2PAppContext context) {
|
|
super(context, 0);
|
|
}
|
|
|
|
public VariableTunnelBuildReplyMessage(I2PAppContext context, int records) {
|
|
super(context, records);
|
|
}
|
|
|
|
@Override
|
|
protected int calculateWrittenLength() { return 1 + super.calculateWrittenLength(); }
|
|
|
|
@Override
|
|
public int getType() { return MESSAGE_TYPE; }
|
|
|
|
public void readMessage(byte[] data, int offset, int dataSize, int type) throws I2NPMessageException, IOException {
|
|
if (type != MESSAGE_TYPE)
|
|
throw new I2NPMessageException("Message type is incorrect for this message");
|
|
if (dataSize != calculateWrittenLength())
|
|
throw new I2NPMessageException("Wrong length (expects " + calculateWrittenLength() + ", recv " + dataSize + ")");
|
|
|
|
int r = (int)DataHelper.fromLong(data, offset, 1);
|
|
if (r <= 0 || r > MAX_RECORD_COUNT)
|
|
throw new I2NPMessageException("Bad record count " + r);
|
|
RECORD_COUNT = r;
|
|
_records = new ByteArray[RECORD_COUNT];
|
|
super.readMessage(data, offset + 1, dataSize, TunnelBuildMessage.MESSAGE_TYPE);
|
|
}
|
|
|
|
protected int writeMessageBody(byte[] out, int curIndex) throws I2NPMessageException {
|
|
int remaining = out.length - (curIndex + calculateWrittenLength());
|
|
if (remaining < 0)
|
|
throw new I2NPMessageException("Not large enough (too short by " + remaining + ")");
|
|
if (RECORD_COUNT <= 0 || RECORD_COUNT > MAX_RECORD_COUNT)
|
|
throw new I2NPMessageException("Bad record count " + RECORD_COUNT);
|
|
DataHelper.toLong(out, curIndex, 1, RECORD_COUNT);
|
|
// can't call super, written length check will fail
|
|
//return super.writeMessageBody(out, curIndex + 1);
|
|
for (int i = 0; i < RECORD_COUNT; i++) {
|
|
System.arraycopy(_records[i].getData(), _records[i].getOffset(), out, curIndex, RECORD_SIZE);
|
|
curIndex += RECORD_SIZE;
|
|
}
|
|
return curIndex;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
StringBuilder buf = new StringBuilder(64);
|
|
buf.append("[VariableTunnelBuildReplyMessage: " +
|
|
"\n\tRecords: ").append(getRecordCount())
|
|
.append(']');
|
|
return buf.toString();
|
|
}
|
|
}
|