forked from I2P_Developers/i2p.i2p
NTCP2: I2NP support, fixes, cleanups
This commit is contained in:
@ -127,15 +127,43 @@ public interface I2NPMessage extends DataStructure {
|
|||||||
* write the message to the buffer, returning the number of bytes written.
|
* write the message to the buffer, returning the number of bytes written.
|
||||||
* the data is formatted so as to be self contained, with the type, size,
|
* the data is formatted so as to be self contained, with the type, size,
|
||||||
* expiration, unique id, as well as a checksum bundled along.
|
* expiration, unique id, as well as a checksum bundled along.
|
||||||
* Full 16 byte header.
|
* Full 16 byte header for NTCP 1.
|
||||||
|
*
|
||||||
|
* @return the length written
|
||||||
*/
|
*/
|
||||||
public int toByteArray(byte buffer[]);
|
public int toByteArray(byte buffer[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write the message to the buffer, returning the number of bytes written.
|
||||||
|
* the data is formatted so as to be self contained, with the type, size,
|
||||||
|
* expiration, unique id, as well as a checksum bundled along.
|
||||||
|
* Full 16 byte header for NTCP 1.
|
||||||
|
*
|
||||||
|
* @param off the offset to start writing at
|
||||||
|
* @return the new offset (NOT the length)
|
||||||
|
* @since 0.9.36
|
||||||
|
*/
|
||||||
|
public int toByteArray(byte buffer[], int off);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* write the message to the buffer, returning the number of bytes written.
|
* write the message to the buffer, returning the number of bytes written.
|
||||||
* the data is is not self contained - it does not include the size,
|
* the data is is not self contained - it does not include the size,
|
||||||
* unique id, or any checksum, but does include the type and expiration.
|
* unique id, or any checksum, but does include the type and expiration.
|
||||||
* Short 5 byte header.
|
* Short 5 byte header for SSU.
|
||||||
|
*
|
||||||
|
* @return the length written
|
||||||
*/
|
*/
|
||||||
public int toRawByteArray(byte buffer[]);
|
public int toRawByteArray(byte buffer[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write the message to the buffer, returning the number of bytes written.
|
||||||
|
* the data is is not self contained - it does not include the size,
|
||||||
|
* unique id, or any checksum, but does include the type and expiration.
|
||||||
|
* Short 9 byte header for NTCP 2.
|
||||||
|
*
|
||||||
|
* @param off the offset to start writing at
|
||||||
|
* @return the new offset (NOT the length)
|
||||||
|
* @since 0.9.36
|
||||||
|
*/
|
||||||
|
public int toRawByteArrayNTCP2(byte buffer[], int off);
|
||||||
}
|
}
|
||||||
|
@ -53,9 +53,6 @@ public class I2NPMessageHandler {
|
|||||||
int type = (int)DataHelper.readLong(in, 1);
|
int type = (int)DataHelper.readLong(in, 1);
|
||||||
_lastReadBegin = System.currentTimeMillis();
|
_lastReadBegin = System.currentTimeMillis();
|
||||||
I2NPMessage msg = I2NPMessageImpl.createMessage(_context, type);
|
I2NPMessage msg = I2NPMessageImpl.createMessage(_context, type);
|
||||||
// can't be null
|
|
||||||
//if (msg == null)
|
|
||||||
// throw new I2NPMessageException("The type "+ type + " is an unknown I2NP message");
|
|
||||||
try {
|
try {
|
||||||
_lastSize = msg.readBytes(in, type, _messageBuffer);
|
_lastSize = msg.readBytes(in, type, _messageBuffer);
|
||||||
} catch (I2NPMessageException ime) {
|
} catch (I2NPMessageException ime) {
|
||||||
@ -114,19 +111,6 @@ public class I2NPMessageHandler {
|
|||||||
cur++;
|
cur++;
|
||||||
_lastReadBegin = System.currentTimeMillis();
|
_lastReadBegin = System.currentTimeMillis();
|
||||||
I2NPMessage msg = I2NPMessageImpl.createMessage(_context, type);
|
I2NPMessage msg = I2NPMessageImpl.createMessage(_context, type);
|
||||||
// can't be null
|
|
||||||
//if (msg == null) {
|
|
||||||
// int sz = data.length-offset;
|
|
||||||
// boolean allZero = false;
|
|
||||||
// for (int i = offset; i < data.length; i++) {
|
|
||||||
// if (data[i] != 0) {
|
|
||||||
// allZero = false;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// throw new I2NPMessageException("The type "+ type + " is an unknown I2NP message (remaining sz="
|
|
||||||
// + sz + " all zeros? " + allZero + ")");
|
|
||||||
//}
|
|
||||||
try {
|
try {
|
||||||
_lastSize = msg.readBytes(data, type, cur, maxLen - 1);
|
_lastSize = msg.readBytes(data, type, cur, maxLen - 1);
|
||||||
cur += _lastSize;
|
cur += _lastSize;
|
||||||
|
@ -50,10 +50,6 @@ public abstract class I2NPMessageImpl extends DataStructureImpl implements I2NPM
|
|||||||
+ 2 // payload length
|
+ 2 // payload length
|
||||||
+ CHECKSUM_LENGTH;
|
+ CHECKSUM_LENGTH;
|
||||||
|
|
||||||
// Whether SSU used the full header or a truncated header.
|
|
||||||
// We are stuck with the short header, can't change it now.
|
|
||||||
//private static final boolean RAW_FULL_SIZE = false;
|
|
||||||
|
|
||||||
/** unused */
|
/** unused */
|
||||||
private static final Map<Integer, Builder> _builders = new ConcurrentHashMap<Integer, Builder>(1);
|
private static final Map<Integer, Builder> _builders = new ConcurrentHashMap<Integer, Builder>(1);
|
||||||
|
|
||||||
@ -292,9 +288,6 @@ public abstract class I2NPMessageImpl extends DataStructureImpl implements I2NPM
|
|||||||
* Used by SSU only!
|
* Used by SSU only!
|
||||||
*/
|
*/
|
||||||
public synchronized int getRawMessageSize() {
|
public synchronized int getRawMessageSize() {
|
||||||
//if (RAW_FULL_SIZE)
|
|
||||||
// return getMessageSize();
|
|
||||||
//else
|
|
||||||
return calculateWrittenLength()+5;
|
return calculateWrittenLength()+5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,16 +303,38 @@ public abstract class I2NPMessageImpl extends DataStructureImpl implements I2NPM
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write the message to the buffer, returning the number of bytes written.
|
||||||
|
* the data is formatted so as to be self contained, with the type, size,
|
||||||
|
* expiration, unique id, as well as a checksum bundled along.
|
||||||
|
* Full 16 byte header for NTCP 1.
|
||||||
|
*
|
||||||
|
* @return the length written
|
||||||
|
*/
|
||||||
public int toByteArray(byte buffer[]) {
|
public int toByteArray(byte buffer[]) {
|
||||||
try {
|
return toByteArray(buffer, 0);
|
||||||
int writtenLen = writeMessageBody(buffer, HEADER_LENGTH);
|
}
|
||||||
int payloadLen = writtenLen - HEADER_LENGTH;
|
|
||||||
byte[] h = SimpleByteCache.acquire(Hash.HASH_LENGTH);
|
/**
|
||||||
_context.sha().calculateHash(buffer, HEADER_LENGTH, payloadLen, h, 0);
|
* write the message to the buffer, returning the number of bytes written.
|
||||||
|
* the data is formatted so as to be self contained, with the type, size,
|
||||||
|
* expiration, unique id, as well as a checksum bundled along.
|
||||||
|
* Full 16 byte header for NTCP 1.
|
||||||
|
*
|
||||||
|
* @param off the offset to start writing at
|
||||||
|
* @return the new offset (NOT the length)
|
||||||
|
* @since 0.9.36 with off param
|
||||||
|
*/
|
||||||
|
public int toByteArray(byte buffer[], int off) {
|
||||||
|
int start = off;
|
||||||
|
try {
|
||||||
|
int rv = writeMessageBody(buffer, off + HEADER_LENGTH);
|
||||||
|
int payloadLen = rv - (off + HEADER_LENGTH);
|
||||||
|
byte[] h = SimpleByteCache.acquire(Hash.HASH_LENGTH);
|
||||||
|
_context.sha().calculateHash(buffer, off + HEADER_LENGTH, payloadLen, h, 0);
|
||||||
|
|
||||||
int off = 0;
|
|
||||||
DataHelper.toLong(buffer, off, 1, getType());
|
DataHelper.toLong(buffer, off, 1, getType());
|
||||||
off += 1;
|
off++;
|
||||||
|
|
||||||
// Lazy initialization of value
|
// Lazy initialization of value
|
||||||
if (_uniqueId < 0) {
|
if (_uniqueId < 0) {
|
||||||
@ -335,7 +350,7 @@ public abstract class I2NPMessageImpl extends DataStructureImpl implements I2NPM
|
|||||||
System.arraycopy(h, 0, buffer, off, CHECKSUM_LENGTH);
|
System.arraycopy(h, 0, buffer, off, CHECKSUM_LENGTH);
|
||||||
SimpleByteCache.release(h);
|
SimpleByteCache.release(h);
|
||||||
|
|
||||||
return writtenLen;
|
return rv;
|
||||||
} catch (I2NPMessageException ime) {
|
} catch (I2NPMessageException ime) {
|
||||||
_context.logManager().getLog(getClass()).log(Log.CRIT, "Error writing", ime);
|
_context.logManager().getLog(getClass()).log(Log.CRIT, "Error writing", ime);
|
||||||
throw new IllegalStateException("Unable to serialize the message " + getClass().getSimpleName(), ime);
|
throw new IllegalStateException("Unable to serialize the message " + getClass().getSimpleName(), ime);
|
||||||
@ -347,38 +362,18 @@ public abstract class I2NPMessageImpl extends DataStructureImpl implements I2NPM
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* write the message body to the output array, starting at the given index.
|
* write the message body to the output array, starting at the given index.
|
||||||
* @return the index into the array after the last byte written
|
* @return the index into the array after the last byte written (NOT the length)
|
||||||
*/
|
*/
|
||||||
protected abstract int writeMessageBody(byte out[], int curIndex) throws I2NPMessageException;
|
protected abstract int writeMessageBody(byte out[], int curIndex) throws I2NPMessageException;
|
||||||
|
|
||||||
/*
|
|
||||||
protected int toByteArray(byte out[], byte[][] prefix, byte[][] suffix) throws I2NPMessageException {
|
|
||||||
int curIndex = 0;
|
|
||||||
for (int i = 0; i < prefix.length; i++) {
|
|
||||||
System.arraycopy(prefix[i], 0, out, curIndex, prefix[i].length);
|
|
||||||
curIndex += prefix[i].length;
|
|
||||||
}
|
|
||||||
|
|
||||||
curIndex = writeMessageBody(out, curIndex);
|
|
||||||
|
|
||||||
for (int i = 0; i < suffix.length; i++) {
|
|
||||||
System.arraycopy(suffix[i], 0, out, curIndex, suffix[i].length);
|
|
||||||
curIndex += suffix[i].length;
|
|
||||||
}
|
|
||||||
|
|
||||||
return curIndex;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the message with a short 5-byte header.
|
* Write the message with a short 5-byte header.
|
||||||
* THe header consists of a one-byte type and a 4-byte expiration in seconds only.
|
* THe header consists of a one-byte type and a 4-byte expiration in seconds only.
|
||||||
* Used by SSU only!
|
* Used by SSU only!
|
||||||
|
*
|
||||||
|
* @return the new written length
|
||||||
*/
|
*/
|
||||||
public int toRawByteArray(byte buffer[]) {
|
public int toRawByteArray(byte buffer[]) {
|
||||||
//if (RAW_FULL_SIZE)
|
|
||||||
// return toByteArray(buffer);
|
|
||||||
try {
|
try {
|
||||||
int off = 0;
|
int off = 0;
|
||||||
DataHelper.toLong(buffer, off, 1, getType());
|
DataHelper.toLong(buffer, off, 1, getType());
|
||||||
@ -394,6 +389,37 @@ public abstract class I2NPMessageImpl extends DataStructureImpl implements I2NPM
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write the message to the buffer, returning the number of bytes written.
|
||||||
|
* the data is is not self contained - it does not include the size,
|
||||||
|
* unique id, or any checksum, but does include the type and expiration.
|
||||||
|
* Short 9 byte header for NTCP 2.
|
||||||
|
*
|
||||||
|
* @param off the offset to start writing at
|
||||||
|
* @return the new offset (NOT the length)
|
||||||
|
* @since 0.9.36
|
||||||
|
*/
|
||||||
|
public int toRawByteArrayNTCP2(byte buffer[], int off) {
|
||||||
|
try {
|
||||||
|
DataHelper.toLong(buffer, off, 1, getType());
|
||||||
|
off += 1;
|
||||||
|
// Lazy initialization of value
|
||||||
|
if (_uniqueId < 0) {
|
||||||
|
_uniqueId = _context.random().nextLong(MAX_ID_VALUE);
|
||||||
|
}
|
||||||
|
DataHelper.toLong(buffer, off, 4, _uniqueId);
|
||||||
|
off += 4;
|
||||||
|
// January 19 2038? No, unsigned, good until Feb. 7 2106
|
||||||
|
// in seconds, round up so we don't lose time every hop
|
||||||
|
DataHelper.toLong(buffer, off, 4, (_expiration + 500) / 1000);
|
||||||
|
off += 4;
|
||||||
|
return writeMessageBody(buffer, off);
|
||||||
|
} catch (I2NPMessageException ime) {
|
||||||
|
_context.logManager().getLog(getClass()).log(Log.CRIT, "Error writing", ime);
|
||||||
|
throw new IllegalStateException("Unable to serialize the message " + getClass().getSimpleName(), ime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void readMessage(byte data[], int offset, int dataSize, int type, I2NPMessageHandler handler) throws I2NPMessageException {
|
public void readMessage(byte data[], int offset, int dataSize, int type, I2NPMessageHandler handler) throws I2NPMessageException {
|
||||||
// ignore the handler (overridden in subclasses if necessary
|
// ignore the handler (overridden in subclasses if necessary
|
||||||
try {
|
try {
|
||||||
@ -420,16 +446,6 @@ public abstract class I2NPMessageImpl extends DataStructureImpl implements I2NPM
|
|||||||
int type = buffer[offset] & 0xff;
|
int type = buffer[offset] & 0xff;
|
||||||
offset++;
|
offset++;
|
||||||
I2NPMessage msg = createMessage(ctx, type);
|
I2NPMessage msg = createMessage(ctx, type);
|
||||||
if (msg == null)
|
|
||||||
throw new I2NPMessageException("Unknown message type: " + type);
|
|
||||||
//if (RAW_FULL_SIZE) {
|
|
||||||
// try {
|
|
||||||
// msg.readBytes(buffer, type, offset);
|
|
||||||
// } catch (IOException ioe) {
|
|
||||||
// throw new I2NPMessageException("Error reading the " + msg, ioe);
|
|
||||||
// }
|
|
||||||
// return msg;
|
|
||||||
//}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// January 19 2038? No, unsigned, good until Feb. 7 2106
|
// January 19 2038? No, unsigned, good until Feb. 7 2106
|
||||||
@ -456,8 +472,6 @@ public abstract class I2NPMessageImpl extends DataStructureImpl implements I2NPM
|
|||||||
int type = buffer[offset] & 0xff;
|
int type = buffer[offset] & 0xff;
|
||||||
offset++;
|
offset++;
|
||||||
I2NPMessage msg = createMessage(ctx, type);
|
I2NPMessage msg = createMessage(ctx, type);
|
||||||
if (msg == null)
|
|
||||||
throw new I2NPMessageException("Unknown message type: " + type);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
long id = DataHelper.fromLong(buffer, offset, 4);
|
long id = DataHelper.fromLong(buffer, offset, 4);
|
||||||
|
Reference in New Issue
Block a user