forked from I2P_Developers/i2p.i2p
First pass of the UDP transport. No where near ready for use, but it does
the basics (negotiate a session and send I2NP messages back and forth). Lots, lots more left.
This commit is contained in:
@@ -61,6 +61,7 @@ public interface I2NPMessage extends DataStructure {
|
||||
* Replay resistent message Id
|
||||
*/
|
||||
public long getUniqueId();
|
||||
public void setUniqueId(long id);
|
||||
|
||||
/**
|
||||
* Date after which the message should be dropped (and the associated uniqueId forgotten)
|
||||
@@ -72,7 +73,20 @@ public interface I2NPMessage extends DataStructure {
|
||||
|
||||
/** How large the message is, including any checksums */
|
||||
public int getMessageSize();
|
||||
/** How large the raw message is */
|
||||
public int getRawMessageSize();
|
||||
|
||||
|
||||
/** 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,
|
||||
* expiration, unique id, as well as a checksum bundled along.
|
||||
*/
|
||||
public int toByteArray(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.
|
||||
*/
|
||||
public int toRawByteArray(byte buffer[]);
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ public class I2NPMessageHandler {
|
||||
try {
|
||||
int type = (int)DataHelper.readLong(in, 1);
|
||||
_lastReadBegin = System.currentTimeMillis();
|
||||
I2NPMessage msg = createMessage(type);
|
||||
I2NPMessage msg = I2NPMessageImpl.createMessage(_context, type);
|
||||
if (msg == null)
|
||||
throw new I2NPMessageException("The type "+ type + " is an unknown I2NP message");
|
||||
try {
|
||||
@@ -94,7 +94,7 @@ public class I2NPMessageHandler {
|
||||
int type = (int)DataHelper.fromLong(data, cur, 1);
|
||||
cur++;
|
||||
_lastReadBegin = System.currentTimeMillis();
|
||||
I2NPMessage msg = createMessage(type);
|
||||
I2NPMessage msg = I2NPMessageImpl.createMessage(_context, type);
|
||||
if (msg == null)
|
||||
throw new I2NPMessageException("The type "+ type + " is an unknown I2NP message");
|
||||
try {
|
||||
@@ -118,39 +118,6 @@ public class I2NPMessageHandler {
|
||||
public long getLastReadTime() { return _lastReadEnd - _lastReadBegin; }
|
||||
public int getLastSize() { return _lastSize; }
|
||||
|
||||
/**
|
||||
* Yes, this is fairly ugly, but its the only place it ever happens.
|
||||
*
|
||||
*/
|
||||
private I2NPMessage createMessage(int type) throws I2NPMessageException {
|
||||
switch (type) {
|
||||
case DatabaseStoreMessage.MESSAGE_TYPE:
|
||||
return new DatabaseStoreMessage(_context);
|
||||
case DatabaseLookupMessage.MESSAGE_TYPE:
|
||||
return new DatabaseLookupMessage(_context);
|
||||
case DatabaseSearchReplyMessage.MESSAGE_TYPE:
|
||||
return new DatabaseSearchReplyMessage(_context);
|
||||
case DeliveryStatusMessage.MESSAGE_TYPE:
|
||||
return new DeliveryStatusMessage(_context);
|
||||
case DateMessage.MESSAGE_TYPE:
|
||||
return new DateMessage(_context);
|
||||
case GarlicMessage.MESSAGE_TYPE:
|
||||
return new GarlicMessage(_context);
|
||||
case TunnelDataMessage.MESSAGE_TYPE:
|
||||
return new TunnelDataMessage(_context);
|
||||
case TunnelGatewayMessage.MESSAGE_TYPE:
|
||||
return new TunnelGatewayMessage(_context);
|
||||
case DataMessage.MESSAGE_TYPE:
|
||||
return new DataMessage(_context);
|
||||
case TunnelCreateMessage.MESSAGE_TYPE:
|
||||
return new TunnelCreateMessage(_context);
|
||||
case TunnelCreateStatusMessage.MESSAGE_TYPE:
|
||||
return new TunnelCreateStatusMessage(_context);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
try {
|
||||
I2NPMessage msg = new I2NPMessageHandler(I2PAppContext.getGlobalContext()).readMessage(new FileInputStream(args[0]));
|
||||
|
||||
@@ -35,6 +35,8 @@ public abstract class I2NPMessageImpl extends DataStructureImpl implements I2NPM
|
||||
public final static long DEFAULT_EXPIRATION_MS = 1*60*1000; // 1 minute by default
|
||||
public final static int CHECKSUM_LENGTH = 1; //Hash.HASH_LENGTH;
|
||||
|
||||
private static final boolean RAW_FULL_SIZE = true;
|
||||
|
||||
public I2NPMessageImpl(I2PAppContext context) {
|
||||
_context = context;
|
||||
_log = context.logManager().getLog(I2NPMessageImpl.class);
|
||||
@@ -165,7 +167,13 @@ public abstract class I2NPMessageImpl extends DataStructureImpl implements I2NPM
|
||||
public void setMessageExpiration(long exp) { _expiration = exp; }
|
||||
|
||||
public synchronized int getMessageSize() {
|
||||
return calculateWrittenLength()+15 + CHECKSUM_LENGTH; // 47 bytes in the header
|
||||
return calculateWrittenLength()+15 + CHECKSUM_LENGTH; // 16 bytes in the header
|
||||
}
|
||||
public synchronized int getRawMessageSize() {
|
||||
if (RAW_FULL_SIZE)
|
||||
return getMessageSize();
|
||||
else
|
||||
return calculateWrittenLength()+5;
|
||||
}
|
||||
|
||||
public byte[] toByteArray() {
|
||||
@@ -248,4 +256,83 @@ public abstract class I2NPMessageImpl extends DataStructureImpl implements I2NPM
|
||||
return curIndex;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
public int toRawByteArray(byte buffer[]) {
|
||||
if (RAW_FULL_SIZE)
|
||||
return toByteArray(buffer);
|
||||
try {
|
||||
int off = 0;
|
||||
DataHelper.toLong(buffer, off, 1, getType());
|
||||
off += 1;
|
||||
DataHelper.toLong(buffer, off, 4, _expiration/1000); // seconds
|
||||
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().getName()
|
||||
+ "): " + ime.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static I2NPMessage fromRawByteArray(I2PAppContext ctx, byte buffer[], int offset, int len) throws I2NPMessageException {
|
||||
int type = (int)DataHelper.fromLong(buffer, offset, 1);
|
||||
offset++;
|
||||
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;
|
||||
}
|
||||
|
||||
long expiration = DataHelper.fromLong(buffer, offset, 4) * 1000; // seconds
|
||||
offset += 4;
|
||||
int dataSize = len - 1 - 4;
|
||||
try {
|
||||
msg.readMessage(buffer, offset, dataSize, type);
|
||||
msg.setMessageExpiration(expiration);
|
||||
return msg;
|
||||
} catch (IOException ioe) {
|
||||
throw new I2NPMessageException("IO error reading raw message", ioe);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Yes, this is fairly ugly, but its the only place it ever happens.
|
||||
*
|
||||
*/
|
||||
public static I2NPMessage createMessage(I2PAppContext context, int type) throws I2NPMessageException {
|
||||
switch (type) {
|
||||
case DatabaseStoreMessage.MESSAGE_TYPE:
|
||||
return new DatabaseStoreMessage(context);
|
||||
case DatabaseLookupMessage.MESSAGE_TYPE:
|
||||
return new DatabaseLookupMessage(context);
|
||||
case DatabaseSearchReplyMessage.MESSAGE_TYPE:
|
||||
return new DatabaseSearchReplyMessage(context);
|
||||
case DeliveryStatusMessage.MESSAGE_TYPE:
|
||||
return new DeliveryStatusMessage(context);
|
||||
case DateMessage.MESSAGE_TYPE:
|
||||
return new DateMessage(context);
|
||||
case GarlicMessage.MESSAGE_TYPE:
|
||||
return new GarlicMessage(context);
|
||||
case TunnelDataMessage.MESSAGE_TYPE:
|
||||
return new TunnelDataMessage(context);
|
||||
case TunnelGatewayMessage.MESSAGE_TYPE:
|
||||
return new TunnelGatewayMessage(context);
|
||||
case DataMessage.MESSAGE_TYPE:
|
||||
return new DataMessage(context);
|
||||
case TunnelCreateMessage.MESSAGE_TYPE:
|
||||
return new TunnelCreateMessage(context);
|
||||
case TunnelCreateStatusMessage.MESSAGE_TYPE:
|
||||
return new TunnelCreateStatusMessage(context);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user