I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Verified Commit 3bec2b5c authored by zzz's avatar zzz
Browse files

I2NP: New build messages part 2 (prop. 157)

Rename ShortTunnelBuildReplyMessage to OutboundTunnelBuildReplyMessage (type 26)
Add InboundTunnelBuildMessage (type 27)
Add methods for plaintext record
Update readMessage() and writeMessageBody()
Fix calculateWrittenLength()
Update javadocs
WIP, untested, not hooked in yet
parent 1d2dbb3c
No related branches found
No related tags found
No related merge requests found
package net.i2p.data.i2np;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
/**
* Sent from the tunnel creator to the IBGW via an outbound tunnel.
* Contains one plaintext variable-sized request record for the IBGW
* and a variable number of encrypted records for the following hops.
* This message must be garlic-encrypted to hide the contents from the OBEP.
*
* Preliminary, see proposal 157.
*
* @since 0.9.50
*/
public class InboundTunnelBuildMessage extends TunnelBuildMessage {
public static final int MESSAGE_TYPE = 27;
public static final int SHORT_RECORD_SIZE = ShortTunnelBuildMessage.SHORT_RECORD_SIZE;
public static final int MAX_PLAINTEXT_RECORD_SIZE = OutboundTunnelBuildReplyMessage.MAX_PLAINTEXT_RECORD_SIZE;
private int _plaintextSlot;
private byte[] _plaintextRecord;
/** zero record count, will be set with readMessage() */
public InboundTunnelBuildMessage(I2PAppContext context) {
super(context, 0);
}
public InboundTunnelBuildMessage(I2PAppContext context, int records) {
super(context, records);
}
/**
* Set the slot and data for the plaintext record.
* @throws IllegalArgumentException on bad slot or data length.
*/
public void setPlaintextRecord(int slot, byte[] data) {
if (slot < 0 || slot >= RECORD_COUNT || data.length == 0 || data.length > MAX_PLAINTEXT_RECORD_SIZE)
throw new IllegalArgumentException();
_plaintextSlot = slot;
_plaintextRecord = data;
}
/**
* Get the slot for the plaintext record.
* getRecord() for this slot will return null.
*/
public int getPlaintextSlot() {
return _plaintextSlot;
}
/**
* Get the data for the plaintext record.
*/
public byte[] getPlaintextRecord() {
return _plaintextRecord;
}
@Override
protected int calculateWrittenLength() { return 4 + _plaintextRecord.length + ((RECORD_COUNT - 1) * SHORT_RECORD_SIZE); }
@Override
public int getType() { return MESSAGE_TYPE; }
@Override
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 r = data[offset++] & 0xff;
if (r <= 0 || r > MAX_RECORD_COUNT)
throw new I2NPMessageException("Bad record count " + r);
RECORD_COUNT = r;
int _plaintextSlot = data[offset++] & 0xff;
if (_plaintextSlot < 0 || _plaintextSlot >= r)
throw new I2NPMessageException("Bad slot " + _plaintextSlot);
int size = (int) DataHelper.fromLong(data, offset, 2);
if (size <= 0 || size > MAX_PLAINTEXT_RECORD_SIZE)
throw new I2NPMessageException("Bad size " + size);
offset += 2;
_plaintextRecord = new byte[size];
System.arraycopy(data, offset, _plaintextRecord, 0, size);
offset += size;
if (dataSize != calculateWrittenLength())
throw new I2NPMessageException("Wrong length (expects " + calculateWrittenLength() + ", recv " + dataSize + ")");
_records = new EncryptedBuildRecord[RECORD_COUNT];
for (int i = 0; i < RECORD_COUNT; i++) {
if (i == _plaintextSlot)
continue;
byte rec[] = new byte[SHORT_RECORD_SIZE];
System.arraycopy(data, offset, rec, 0, SHORT_RECORD_SIZE);
setRecord(i, new ShortEncryptedBuildRecord(rec));
offset += SHORT_RECORD_SIZE;
}
}
@Override
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);
out[curIndex++] = (byte) RECORD_COUNT;
out[curIndex++] = (byte) _plaintextSlot;
DataHelper.toLong(out, curIndex, 2, _plaintextRecord.length);
curIndex += 2;
System.arraycopy(_plaintextRecord, 0, out, curIndex, _plaintextRecord.length);
curIndex += _plaintextRecord.length;
for (int i = 0; i < RECORD_COUNT; i++) {
if (i == _plaintextSlot)
continue;
System.arraycopy(_records[i].getData(), 0, out, curIndex, SHORT_RECORD_SIZE);
curIndex += SHORT_RECORD_SIZE;
}
return curIndex;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder(64);
buf.append("[InboundTunnelBuildMessage: " +
"\n\tRecords: ").append(getRecordCount())
.append(']');
return buf.toString();
}
}
...@@ -4,28 +4,60 @@ import net.i2p.I2PAppContext; ...@@ -4,28 +4,60 @@ import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
/** /**
* Transmitted from the new outbound endpoint to the creator through a * Sent from the OBEP to the tunnel creator via an inbound tunnel.
* reply tunnel. * Contains one plaintext variable-sized reply record for the creator
* Variable size, small records. * and a variable number of encrypted records for the following hops.
* This message must be garlic-encrypted to hide the contents from the OBGW.
*
* Preliminary, see proposal 157. * Preliminary, see proposal 157.
* *
* @since 0.9.49 * @since 0.9.50
*/ */
public class ShortTunnelBuildReplyMessage extends TunnelBuildReplyMessage { public class OutboundTunnelBuildReplyMessage extends TunnelBuildReplyMessage {
public static final int MESSAGE_TYPE = 26; public static final int MESSAGE_TYPE = 26;
public static final int SHORT_RECORD_SIZE = ShortTunnelBuildMessage.SHORT_RECORD_SIZE; public static final int SHORT_RECORD_SIZE = ShortTunnelBuildMessage.SHORT_RECORD_SIZE;
public static final int MAX_PLAINTEXT_RECORD_SIZE = 172;
private int _plaintextSlot;
private byte[] _plaintextRecord;
/** zero record count, will be set with readMessage() */ /** zero record count, will be set with readMessage() */
public ShortTunnelBuildReplyMessage(I2PAppContext context) { public OutboundTunnelBuildReplyMessage(I2PAppContext context) {
super(context, 0); super(context, 0);
} }
public ShortTunnelBuildReplyMessage(I2PAppContext context, int records) { public OutboundTunnelBuildReplyMessage(I2PAppContext context, int records) {
super(context, records); super(context, records);
} }
/**
* Set the slot and data for the plaintext record.
* @throws IllegalArgumentException on bad slot or data length.
*/
public void setPlaintextRecord(int slot, byte[] data) {
if (slot < 0 || slot >= RECORD_COUNT || data.length == 0 || data.length > MAX_PLAINTEXT_RECORD_SIZE)
throw new IllegalArgumentException();
_plaintextSlot = slot;
_plaintextRecord = data;
}
/**
* Get the slot for the plaintext record.
* getRecord() for this slot will return null.
*/
public int getPlaintextSlot() {
return _plaintextSlot;
}
/**
* Get the data for the plaintext record.
*/
public byte[] getPlaintextRecord() {
return _plaintextRecord;
}
@Override @Override
protected int calculateWrittenLength() { return 1 + super.calculateWrittenLength(); } protected int calculateWrittenLength() { return 4 + _plaintextRecord.length + ((RECORD_COUNT - 1) * SHORT_RECORD_SIZE); }
@Override @Override
public int getType() { return MESSAGE_TYPE; } public int getType() { return MESSAGE_TYPE; }
...@@ -34,15 +66,27 @@ public class ShortTunnelBuildReplyMessage extends TunnelBuildReplyMessage { ...@@ -34,15 +66,27 @@ public class ShortTunnelBuildReplyMessage extends TunnelBuildReplyMessage {
public void readMessage(byte[] data, int offset, int dataSize, int type) throws I2NPMessageException { public void readMessage(byte[] data, int offset, int dataSize, int type) throws I2NPMessageException {
if (type != MESSAGE_TYPE) if (type != MESSAGE_TYPE)
throw new I2NPMessageException("Message type is incorrect for this message"); throw new I2NPMessageException("Message type is incorrect for this message");
int r = data[offset] & 0xff; int r = data[offset++] & 0xff;
if (r <= 0 || r > MAX_RECORD_COUNT) if (r <= 0 || r > MAX_RECORD_COUNT)
throw new I2NPMessageException("Bad record count " + r); throw new I2NPMessageException("Bad record count " + r);
RECORD_COUNT = r; RECORD_COUNT = r;
_plaintextSlot = data[offset++] & 0xff;
if (_plaintextSlot < 0 || _plaintextSlot >= r)
throw new I2NPMessageException("Bad slot " + _plaintextSlot);
int size = (int) DataHelper.fromLong(data, offset, 2);
if (size <= 0 || size > MAX_PLAINTEXT_RECORD_SIZE)
throw new I2NPMessageException("Bad size " + size);
offset += 2;
_plaintextRecord = new byte[size];
System.arraycopy(data, offset, _plaintextRecord, 0, size);
offset += size;
if (dataSize != calculateWrittenLength()) if (dataSize != calculateWrittenLength())
throw new I2NPMessageException("Wrong length (expects " + calculateWrittenLength() + ", recv " + dataSize + ")"); throw new I2NPMessageException("Wrong length (expects " + calculateWrittenLength() + ", recv " + dataSize + ")");
_records = new EncryptedBuildRecord[RECORD_COUNT]; _records = new EncryptedBuildRecord[RECORD_COUNT];
offset++;
for (int i = 0; i < RECORD_COUNT; i++) { for (int i = 0; i < RECORD_COUNT; i++) {
if (i == _plaintextSlot)
continue;
byte rec[] = new byte[SHORT_RECORD_SIZE]; byte rec[] = new byte[SHORT_RECORD_SIZE];
System.arraycopy(data, offset, rec, 0, SHORT_RECORD_SIZE); System.arraycopy(data, offset, rec, 0, SHORT_RECORD_SIZE);
setRecord(i, new ShortEncryptedBuildRecord(rec)); setRecord(i, new ShortEncryptedBuildRecord(rec));
...@@ -58,7 +102,14 @@ public class ShortTunnelBuildReplyMessage extends TunnelBuildReplyMessage { ...@@ -58,7 +102,14 @@ public class ShortTunnelBuildReplyMessage extends TunnelBuildReplyMessage {
if (RECORD_COUNT <= 0 || RECORD_COUNT > MAX_RECORD_COUNT) if (RECORD_COUNT <= 0 || RECORD_COUNT > MAX_RECORD_COUNT)
throw new I2NPMessageException("Bad record count " + RECORD_COUNT); throw new I2NPMessageException("Bad record count " + RECORD_COUNT);
out[curIndex++] = (byte) RECORD_COUNT; out[curIndex++] = (byte) RECORD_COUNT;
out[curIndex++] = (byte) _plaintextSlot;
DataHelper.toLong(out, curIndex, 2, _plaintextRecord.length);
curIndex += 2;
System.arraycopy(_plaintextRecord, 0, out, curIndex, _plaintextRecord.length);
curIndex += _plaintextRecord.length;
for (int i = 0; i < RECORD_COUNT; i++) { for (int i = 0; i < RECORD_COUNT; i++) {
if (i == _plaintextSlot)
continue;
System.arraycopy(_records[i].getData(), 0, out, curIndex, SHORT_RECORD_SIZE); System.arraycopy(_records[i].getData(), 0, out, curIndex, SHORT_RECORD_SIZE);
curIndex += SHORT_RECORD_SIZE; curIndex += SHORT_RECORD_SIZE;
} }
...@@ -68,7 +119,7 @@ public class ShortTunnelBuildReplyMessage extends TunnelBuildReplyMessage { ...@@ -68,7 +119,7 @@ public class ShortTunnelBuildReplyMessage extends TunnelBuildReplyMessage {
@Override @Override
public String toString() { public String toString() {
StringBuilder buf = new StringBuilder(64); StringBuilder buf = new StringBuilder(64);
buf.append("[ShortTunnelBuildReplyMessage: " + buf.append("[OutboundTunnelBuildReplyMessage: " +
"\n\tRecords: ").append(getRecordCount()) "\n\tRecords: ").append(getRecordCount())
.append(']'); .append(']');
return buf.toString(); return buf.toString();
......
...@@ -22,7 +22,7 @@ public class ShortTunnelBuildMessage extends TunnelBuildMessage { ...@@ -22,7 +22,7 @@ public class ShortTunnelBuildMessage extends TunnelBuildMessage {
} }
@Override @Override
protected int calculateWrittenLength() { return 1 + super.calculateWrittenLength(); } protected int calculateWrittenLength() { return 1 + (RECORD_COUNT * SHORT_RECORD_SIZE); }
@Override @Override
public int getType() { return MESSAGE_TYPE; } public int getType() { return MESSAGE_TYPE; }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment