forked from I2P_Developers/i2p.i2p
if I'm making this backwards incompatible, I might as well clean up the rest, 'eh?
* removed SourceRouteBlock & SourceRouteReplyMessage, as they're a redundant concept that 1) takes up bandwidth 2) takes up CPU 3) smell funny. now the TunnelCreateMessage includes a replyTag, replyKey, replyTunnel, and replyGateway that they garlic encrypt their ACK/NACK through and with. * tunnelCreateMessage doesn't need a seperate ACK - either we get a TunnelCreateStatusMessage back or we don't. * message structure mods for unique tunnel ID per hop (though currently all hops have the same tunnel ID)
This commit is contained in:
@@ -144,7 +144,8 @@ public class DatabaseStoreMessage extends I2NPMessageImpl {
|
||||
byte compressed[] = new byte[compressedSize];
|
||||
int read = DataHelper.read(in, compressed);
|
||||
if (read != compressedSize)
|
||||
throw new I2NPMessageException("Invalid compressed data size");
|
||||
throw new I2NPMessageException("Invalid compressed data size (expected "
|
||||
+ compressedSize + " read " + read + ")");
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(DataHelper.decompress(compressed));
|
||||
_info.readBytes(bais);
|
||||
} else {
|
||||
|
||||
@@ -34,25 +34,8 @@ public class GarlicClove extends DataStructureImpl {
|
||||
private long _cloveId;
|
||||
private Date _expiration;
|
||||
private Certificate _certificate;
|
||||
private int _replyAction;
|
||||
private SourceRouteBlock _sourceRouteBlock;
|
||||
private I2NPMessageHandler _handler;
|
||||
|
||||
/** No action requested with the source route block */
|
||||
public final static int ACTION_NONE = 0;
|
||||
/**
|
||||
* A DeliveryStatusMessage is requested with the source route block using
|
||||
* the cloveId as the id received
|
||||
*
|
||||
*/
|
||||
public final static int ACTION_STATUS = 1;
|
||||
/**
|
||||
* No DeliveryStatusMessage is requested, but the source route block is
|
||||
* included for message specific replies
|
||||
*
|
||||
*/
|
||||
public final static int ACTION_MESSAGE_SPECIFIC = 2;
|
||||
|
||||
public GarlicClove(RouterContext context) {
|
||||
_context = context;
|
||||
_log = context.logManager().getLog(GarlicClove.class);
|
||||
@@ -62,8 +45,6 @@ public class GarlicClove extends DataStructureImpl {
|
||||
setCloveId(-1);
|
||||
setExpiration(null);
|
||||
setCertificate(null);
|
||||
setSourceRouteBlockAction(ACTION_NONE);
|
||||
setSourceRouteBlock(null);
|
||||
}
|
||||
|
||||
public DeliveryInstructions getInstructions() { return _instructions; }
|
||||
@@ -76,10 +57,6 @@ public class GarlicClove extends DataStructureImpl {
|
||||
public void setExpiration(Date exp) { _expiration = exp; }
|
||||
public Certificate getCertificate() { return _certificate; }
|
||||
public void setCertificate(Certificate cert) { _certificate = cert; }
|
||||
public int getSourceRouteBlockAction() { return _replyAction; }
|
||||
public void setSourceRouteBlockAction(int action) { _replyAction = action; }
|
||||
public SourceRouteBlock getSourceRouteBlock() { return _sourceRouteBlock; }
|
||||
public void setSourceRouteBlock(SourceRouteBlock block) { _sourceRouteBlock = block; }
|
||||
|
||||
public void readBytes(InputStream in) throws DataFormatException, IOException {
|
||||
_instructions = new DeliveryInstructions();
|
||||
@@ -99,12 +76,6 @@ public class GarlicClove extends DataStructureImpl {
|
||||
_certificate.readBytes(in);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Read cert: " + _certificate);
|
||||
int replyStyle = (int)DataHelper.readLong(in, 1);
|
||||
setSourceRouteBlockAction(replyStyle);
|
||||
if (replyStyle != ACTION_NONE) {
|
||||
_sourceRouteBlock = new SourceRouteBlock();
|
||||
_sourceRouteBlock.readBytes(in);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeBytes(OutputStream out) throws DataFormatException, IOException {
|
||||
@@ -119,28 +90,23 @@ public class GarlicClove extends DataStructureImpl {
|
||||
error.append("Expiration is null ");
|
||||
if (_certificate == null)
|
||||
error.append("Certificate is null ");
|
||||
if (_replyAction < 0)
|
||||
error.append("Reply action is < 0 [").append(_replyAction).append("] ");;
|
||||
if (error.length() > 0)
|
||||
throw new DataFormatException(error.toString());
|
||||
if ( (_replyAction != 0) && (_sourceRouteBlock == null) )
|
||||
throw new DataFormatException("Source route block must be specified for non-null action");
|
||||
_instructions.writeBytes(out);
|
||||
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Wrote instructions: " + _instructions);
|
||||
_msg.writeBytes(out);
|
||||
DataHelper.writeLong(out, 4, _cloveId);
|
||||
DataHelper.writeDate(out, _expiration);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("CloveID written: " + _cloveId + " expiration written: "
|
||||
+ _expiration);
|
||||
_certificate.writeBytes(out);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Written cert: " + _certificate);
|
||||
DataHelper.writeLong(out, 1, _replyAction);
|
||||
if ( (_replyAction != 0) && (_sourceRouteBlock != null) )
|
||||
_sourceRouteBlock.writeBytes(out);
|
||||
|
||||
if (error.length() > 0)
|
||||
throw new DataFormatException(error.toString());
|
||||
|
||||
_instructions.writeBytes(out);
|
||||
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Wrote instructions: " + _instructions);
|
||||
_msg.writeBytes(out);
|
||||
DataHelper.writeLong(out, 4, _cloveId);
|
||||
DataHelper.writeDate(out, _expiration);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("CloveID written: " + _cloveId + " expiration written: "
|
||||
+ _expiration);
|
||||
_certificate.writeBytes(out);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Written cert: " + _certificate);
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
@@ -148,22 +114,18 @@ public class GarlicClove extends DataStructureImpl {
|
||||
return false;
|
||||
GarlicClove clove = (GarlicClove)obj;
|
||||
return DataHelper.eq(getCertificate(), clove.getCertificate()) &&
|
||||
DataHelper.eq(getCloveId(), clove.getCloveId()) &&
|
||||
DataHelper.eq(getData(), clove.getData()) &&
|
||||
DataHelper.eq(getExpiration(), clove.getExpiration()) &&
|
||||
DataHelper.eq(getInstructions(), clove.getInstructions()) &&
|
||||
DataHelper.eq(getSourceRouteBlock(), clove.getSourceRouteBlock()) &&
|
||||
(getSourceRouteBlockAction() == clove.getSourceRouteBlockAction());
|
||||
DataHelper.eq(getCloveId(), clove.getCloveId()) &&
|
||||
DataHelper.eq(getData(), clove.getData()) &&
|
||||
DataHelper.eq(getExpiration(), clove.getExpiration()) &&
|
||||
DataHelper.eq(getInstructions(), clove.getInstructions());
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return DataHelper.hashCode(getCertificate()) +
|
||||
(int)getCloveId() +
|
||||
DataHelper.hashCode(getData()) +
|
||||
DataHelper.hashCode(getExpiration()) +
|
||||
DataHelper.hashCode(getInstructions()) +
|
||||
DataHelper.hashCode(getSourceRouteBlock()) +
|
||||
getSourceRouteBlockAction();
|
||||
(int)getCloveId() +
|
||||
DataHelper.hashCode(getData()) +
|
||||
DataHelper.hashCode(getExpiration()) +
|
||||
DataHelper.hashCode(getInstructions());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
@@ -173,8 +135,6 @@ public class GarlicClove extends DataStructureImpl {
|
||||
buf.append("\n\tCertificate: ").append(getCertificate());
|
||||
buf.append("\n\tClove ID: ").append(getCloveId());
|
||||
buf.append("\n\tExpiration: ").append(getExpiration());
|
||||
buf.append("\n\tSource route style: ").append(getSourceRouteBlockAction());
|
||||
buf.append("\n\tSource route block: ").append(getSourceRouteBlock());
|
||||
buf.append("\n\tData: ").append(getData());
|
||||
buf.append("]");
|
||||
return buf.toString();
|
||||
|
||||
@@ -73,8 +73,6 @@ public class I2NPMessageHandler {
|
||||
return new TunnelMessage(_context);
|
||||
case DataMessage.MESSAGE_TYPE:
|
||||
return new DataMessage(_context);
|
||||
case SourceRouteReplyMessage.MESSAGE_TYPE:
|
||||
return new SourceRouteReplyMessage(_context);
|
||||
case TunnelCreateMessage.MESSAGE_TYPE:
|
||||
return new TunnelCreateMessage(_context);
|
||||
case TunnelCreateStatusMessage.MESSAGE_TYPE:
|
||||
|
||||
@@ -1,228 +0,0 @@
|
||||
package net.i2p.data.i2np;
|
||||
/*
|
||||
* free (adj.): unencumbered; not under the control of others
|
||||
* Written by jrandom in 2003 and released into the public domain
|
||||
* with no warranty of any kind, either expressed or implied.
|
||||
* It probably won't make your computer catch on fire, or eat
|
||||
* your children, but it might. Use at your own risk.
|
||||
*
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Date;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.data.Certificate;
|
||||
import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.data.DataStructureImpl;
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.data.PublicKey;
|
||||
import net.i2p.data.SessionKey;
|
||||
import net.i2p.data.SessionTag;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
|
||||
/**
|
||||
* Defines a single hop of a source routed message, as usable for building a
|
||||
* SourceRouteReplyMessage
|
||||
*
|
||||
* @author jrandom
|
||||
*/
|
||||
public class SourceRouteBlock extends DataStructureImpl {
|
||||
private final static Log _log = new Log(SourceRouteBlock.class);
|
||||
private Hash _router;
|
||||
private byte[] _data;
|
||||
private SessionKey _key;
|
||||
private byte[] _tag;
|
||||
private DeliveryInstructions _decryptedInstructions;
|
||||
private long _decryptedMessageId;
|
||||
private Certificate _decryptedCertificate;
|
||||
private long _decryptedExpiration;
|
||||
|
||||
public SourceRouteBlock() {
|
||||
setRouter(null);
|
||||
setData(null);
|
||||
setKey(null);
|
||||
setTag((byte[])null);
|
||||
_decryptedInstructions = null;
|
||||
_decryptedMessageId = -1;
|
||||
_decryptedCertificate = null;
|
||||
_decryptedExpiration = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the router through which replies using this source route block must
|
||||
* be sent (as the getData() is encrypted for their eyes only)
|
||||
*
|
||||
*/
|
||||
public Hash getRouter() { return _router; }
|
||||
public void setRouter(Hash router) { _router= router; }
|
||||
/**
|
||||
* Get the encrypted header. After decryption (via ElGamal+AES as defined
|
||||
* in the data structures spec), this array contains:
|
||||
* DeliveryInstructions
|
||||
* 4 byte Integer for a message ID
|
||||
* Certificate
|
||||
* Date of expiration for replies
|
||||
*
|
||||
*/
|
||||
public byte[] getData() { return _data; }
|
||||
private void setData(byte data[]) { _data = data; }
|
||||
/**
|
||||
* Retrieve the session key which may be used in conjunction with the tag
|
||||
* to encrypt a garlic message and send it as a reply to this message.
|
||||
* The encryption would follow scenario 2 of the ElGamal+AES encryption method
|
||||
* defined in the data structures spec.
|
||||
*
|
||||
*/
|
||||
public SessionKey getKey() { return _key; }
|
||||
public void setKey(SessionKey key) { _key = key; }
|
||||
/**
|
||||
* Get the tag made available for use in conjunction with the getKey() to
|
||||
* ElGamal+AES encrypt a garlic message without knowing the public key to
|
||||
* which the message is destined
|
||||
*
|
||||
*/
|
||||
public byte[] getTag() { return _tag; }
|
||||
public void setTag(SessionTag tag) { setTag(tag.getData()); }
|
||||
public void setTag(byte tag[]) {
|
||||
if ( (tag != null) && (tag.length != SessionTag.BYTE_LENGTH) )
|
||||
throw new IllegalArgumentException("Tag must be either null or 32 bytes");
|
||||
_tag = tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* After decryptData, this contains the delivery instructions for this block
|
||||
*/
|
||||
public DeliveryInstructions getDecryptedInstructions() { return _decryptedInstructions; }
|
||||
/**
|
||||
* After decryptData, this contains the message ID to be used with this block
|
||||
*/
|
||||
public long getDecryptedMessageId() { return _decryptedMessageId; }
|
||||
/**
|
||||
* After decryptData, this contains the Certificate 'paying' for the forwarding according to
|
||||
* this block
|
||||
*/
|
||||
public Certificate getDecryptedCertificate() { return _decryptedCertificate; }
|
||||
/**
|
||||
* After decryptData, this contains the date after which this block should not be forwarded
|
||||
*/
|
||||
public long getDecryptedExpiration() { return _decryptedExpiration; }
|
||||
|
||||
/**
|
||||
* Set the raw data with the formatted and encrypted options specified
|
||||
*
|
||||
* @param instructions Where a message bearing this block should be sent
|
||||
* @param messageId ID of the message for this block (not repeatable)
|
||||
* @param expiration date after which this block expires
|
||||
* @param replyThrough Encryption key of the router to whom this block is specified (not
|
||||
* the router specified in the delivery instructions!)
|
||||
*
|
||||
* @throws DataFormatException if the data is invalid or could not be encrypted
|
||||
*/
|
||||
public void setData(I2PAppContext ctx, DeliveryInstructions instructions,
|
||||
long messageId, Certificate cert, long expiration,
|
||||
PublicKey replyThrough) throws DataFormatException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(64);
|
||||
|
||||
_decryptedInstructions = instructions;
|
||||
_decryptedMessageId = messageId;
|
||||
_decryptedCertificate = cert;
|
||||
_decryptedExpiration = expiration;
|
||||
|
||||
instructions.writeBytes(baos);
|
||||
DataHelper.writeLong(baos, 4, messageId);
|
||||
cert.writeBytes(baos);
|
||||
DataHelper.writeDate(baos, new Date(expiration));
|
||||
|
||||
int paddedSize = 256;
|
||||
SessionKey sessKey = null;
|
||||
SessionTag tag = null;
|
||||
if (instructions.getDelayRequested()) {
|
||||
// always use a new key if we're delaying, since the reply block may not be used within the
|
||||
// window of a session
|
||||
sessKey = ctx.keyGenerator().generateSessionKey();
|
||||
tag = null;
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Delay requested - creating a new session key");
|
||||
} else {
|
||||
sessKey = ctx.sessionKeyManager().getCurrentKey(replyThrough);
|
||||
if (sessKey == null) {
|
||||
sessKey = ctx.keyGenerator().generateSessionKey();
|
||||
tag = null;
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("No delay requested, but no session key is known");
|
||||
} else {
|
||||
tag = ctx.sessionKeyManager().consumeNextAvailableTag(replyThrough, sessKey);
|
||||
}
|
||||
}
|
||||
byte encData[] = ctx.elGamalAESEngine().encrypt(baos.toByteArray(), replyThrough,
|
||||
sessKey, null, tag, paddedSize);
|
||||
setData(encData);
|
||||
} catch (IOException ioe) {
|
||||
throw new DataFormatException("Error writing out the source route block data", ioe);
|
||||
} catch (DataFormatException dfe) {
|
||||
throw new DataFormatException("Error writing out the source route block data", dfe);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void readBytes(InputStream in) throws DataFormatException, IOException {
|
||||
_router = new Hash();
|
||||
_router.readBytes(in);
|
||||
int size = (int)DataHelper.readLong(in, 2);
|
||||
_data = new byte[size];
|
||||
int read = read(in, _data);
|
||||
if (read != _data.length)
|
||||
throw new DataFormatException("Incorrect # of bytes read for source route block: " + read);
|
||||
_key = new SessionKey();
|
||||
_key.readBytes(in);
|
||||
_tag = new byte[32];
|
||||
read = read(in, _tag);
|
||||
if (read != _tag.length)
|
||||
throw new DataFormatException("Incorrect # of bytes read for session tag: " + read);
|
||||
}
|
||||
|
||||
public void writeBytes(OutputStream out) throws DataFormatException, IOException {
|
||||
if ( (_router == null) || (_data == null) || (_key == null) || (_tag == null) || (_tag.length != 32) )
|
||||
throw new DataFormatException("Insufficient data to write");
|
||||
_router.writeBytes(out);
|
||||
DataHelper.writeLong(out, 2, _data.length);
|
||||
out.write(_data);
|
||||
_key.writeBytes(out);
|
||||
out.write(_tag);
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if ( (obj == null) || !(obj instanceof SourceRouteBlock))
|
||||
return false;
|
||||
SourceRouteBlock block = (SourceRouteBlock)obj;
|
||||
return DataHelper.eq(getRouter(), block.getRouter()) &&
|
||||
DataHelper.eq(getData(), block.getData()) &&
|
||||
DataHelper.eq(getKey(), block.getKey()) &&
|
||||
DataHelper.eq(getTag(), block.getTag());
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return DataHelper.hashCode(getRouter()) +
|
||||
DataHelper.hashCode(getData()) +
|
||||
DataHelper.hashCode(getKey()) +
|
||||
DataHelper.hashCode(getTag());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer buf = new StringBuffer(128);
|
||||
buf.append("[SourceRouteBlock: ");
|
||||
buf.append("\n\tRouter: ").append(getRouter());
|
||||
buf.append("\n\tData: ").append(DataHelper.toString(getData(), getData().length));
|
||||
buf.append("\n\tTag: ").append(DataHelper.toString(getTag(), (getTag() != null ? getTag().length : 0)));
|
||||
buf.append("\n\tKey: ").append(getKey());
|
||||
buf.append("]");
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
package net.i2p.data.i2np;
|
||||
/*
|
||||
* free (adj.): unencumbered; not under the control of others
|
||||
* Written by jrandom in 2003 and released into the public domain
|
||||
* with no warranty of any kind, either expressed or implied.
|
||||
* It probably won't make your computer catch on fire, or eat
|
||||
* your children, but it might. Use at your own risk.
|
||||
*
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.data.Certificate;
|
||||
import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.data.PrivateKey;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
* Defines a message directed by a source route block to deliver a message to an
|
||||
* unknown location.
|
||||
*
|
||||
* @author jrandom
|
||||
*/
|
||||
public class SourceRouteReplyMessage extends I2NPMessageImpl {
|
||||
private final static Log _log = new Log(SourceRouteReplyMessage.class);
|
||||
public final static int MESSAGE_TYPE = 13;
|
||||
private byte _encryptedHeader[];
|
||||
private I2NPMessage _message;
|
||||
private DeliveryInstructions _decryptedInstructions;
|
||||
private long _decryptedMessageId;
|
||||
private Certificate _decryptedCertificate;
|
||||
private long _decryptedExpiration;
|
||||
private I2NPMessageHandler _handler;
|
||||
|
||||
public SourceRouteReplyMessage(I2PAppContext context) {
|
||||
super(context);
|
||||
_handler = new I2NPMessageHandler(context);
|
||||
_encryptedHeader = null;
|
||||
_message = null;
|
||||
_decryptedInstructions = null;
|
||||
_decryptedMessageId = -1;
|
||||
_decryptedCertificate = null;
|
||||
_decryptedExpiration = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the message being sent as a reply
|
||||
*/
|
||||
public I2NPMessage getMessage() { return _message; }
|
||||
public void setMessage(I2NPMessage message) { _message = message; }
|
||||
|
||||
public void setEncryptedHeader(byte header[]) { _encryptedHeader = header; }
|
||||
|
||||
/**
|
||||
* After decryptHeader, this contains the delivery instructions for this block
|
||||
*/
|
||||
public DeliveryInstructions getDecryptedInstructions() { return _decryptedInstructions; }
|
||||
/**
|
||||
* After decryptHeader, this contains the message ID to be used with this block
|
||||
*/
|
||||
public long getDecryptedMessageId() { return _decryptedMessageId; }
|
||||
/**
|
||||
* After decryptHeader, this contains the Certificate 'paying' for the forwarding according to
|
||||
* this block
|
||||
*/
|
||||
public Certificate getDecryptedCertificate() { return _decryptedCertificate; }
|
||||
/**
|
||||
* After decryptHeader, this contains the date after which this block should not be forwarded
|
||||
*/
|
||||
public long getDecryptedExpiration() { return _decryptedExpiration; }
|
||||
|
||||
/**
|
||||
* Decrypt the header and store it in the various getDecryptedXYZ() properties
|
||||
*
|
||||
* @throws DataFormatException if the decryption fails or if the data is somehow malformed
|
||||
*/
|
||||
public void decryptHeader(PrivateKey key) throws DataFormatException {
|
||||
if ( (_encryptedHeader == null) || (_encryptedHeader.length <= 0) )
|
||||
throw new DataFormatException("No header to decrypt");
|
||||
|
||||
byte decr[] = _context.elGamalAESEngine().decrypt(_encryptedHeader, key);
|
||||
|
||||
if (decr == null)
|
||||
throw new DataFormatException("Decrypted data is null");
|
||||
|
||||
try {
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(decr);
|
||||
|
||||
_decryptedInstructions = new DeliveryInstructions();
|
||||
_decryptedInstructions.readBytes(bais);
|
||||
_decryptedMessageId = DataHelper.readLong(bais, 4);
|
||||
_decryptedCertificate = new Certificate();
|
||||
_decryptedCertificate.readBytes(bais);
|
||||
_decryptedExpiration = DataHelper.readDate(bais).getTime();
|
||||
|
||||
} catch (IOException ioe) {
|
||||
throw new DataFormatException("Error reading the source route reply header", ioe);
|
||||
} catch (DataFormatException dfe) {
|
||||
throw new DataFormatException("Error reading the source route reply header", dfe);
|
||||
}
|
||||
}
|
||||
|
||||
public void readMessage(InputStream in, int type) throws I2NPMessageException, IOException {
|
||||
if (type != MESSAGE_TYPE)
|
||||
throw new I2NPMessageException("Message type is incorrect for this message");
|
||||
try {
|
||||
int headerSize = (int)DataHelper.readLong(in, 2);
|
||||
_encryptedHeader = new byte[headerSize];
|
||||
int read = read(in, _encryptedHeader);
|
||||
if (read != headerSize)
|
||||
throw new DataFormatException("Not enough bytes to read the header (read = " + read
|
||||
+ ", required = " + headerSize + ")");
|
||||
_message = _handler.readMessage(in);
|
||||
} catch (DataFormatException dfe) {
|
||||
throw new I2NPMessageException("Unable to load the message data", dfe);
|
||||
}
|
||||
}
|
||||
|
||||
protected byte[] writeMessage() throws I2NPMessageException, IOException {
|
||||
if ( (_encryptedHeader == null) || (_message == null) )
|
||||
throw new I2NPMessageException("Not enough data to write out");
|
||||
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
|
||||
try {
|
||||
DataHelper.writeLong(os, 2, _encryptedHeader.length);
|
||||
os.write(_encryptedHeader);
|
||||
_message.writeBytes(os);
|
||||
} catch (DataFormatException dfe) {
|
||||
throw new I2NPMessageException("Error writing out the message data", dfe);
|
||||
}
|
||||
return os.toByteArray();
|
||||
}
|
||||
|
||||
public int getType() { return MESSAGE_TYPE; }
|
||||
|
||||
public int hashCode() {
|
||||
return DataHelper.hashCode(_encryptedHeader) +
|
||||
DataHelper.hashCode(_message);
|
||||
}
|
||||
|
||||
public boolean equals(Object object) {
|
||||
if ( (object != null) && (object instanceof SourceRouteReplyMessage) ) {
|
||||
SourceRouteReplyMessage msg = (SourceRouteReplyMessage)object;
|
||||
return DataHelper.eq(_message,msg._message) &&
|
||||
DataHelper.eq(_encryptedHeader,msg._encryptedHeader);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append("[SourceRouteReplyMessage: ");
|
||||
buf.append("\n\tHeader: ").append(DataHelper.toString(_encryptedHeader, 64));
|
||||
buf.append("\n\tMessage: ").append(_message);
|
||||
buf.append("]");
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,8 @@ import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.data.TunnelId;
|
||||
import net.i2p.data.SessionKey;
|
||||
import net.i2p.data.SessionTag;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
@@ -30,8 +32,9 @@ public class TunnelCreateMessage extends I2NPMessageImpl {
|
||||
private final static Log _log = new Log(TunnelCreateMessage.class);
|
||||
public final static int MESSAGE_TYPE = 6;
|
||||
private int _participantType;
|
||||
private Hash _nextRouter;
|
||||
private TunnelId _tunnelId;
|
||||
private Hash _nextRouter;
|
||||
private TunnelId _nextTunnelId;
|
||||
private long _tunnelDuration;
|
||||
private TunnelConfigurationSessionKey _configKey;
|
||||
private long _maxPeakMessagesPerMin;
|
||||
@@ -44,7 +47,10 @@ public class TunnelCreateMessage extends I2NPMessageImpl {
|
||||
private TunnelSigningPrivateKey _verificationPrivKey;
|
||||
private TunnelSessionKey _tunnelKey;
|
||||
private Certificate _certificate;
|
||||
private SourceRouteBlock _replyBlock;
|
||||
private SessionTag _replyTag;
|
||||
private SessionKey _replyKey;
|
||||
private TunnelId _replyTunnel;
|
||||
private Hash _replyPeer;
|
||||
|
||||
public static final int PARTICIPANT_TYPE_GATEWAY = 1;
|
||||
public static final int PARTICIPANT_TYPE_ENDPOINT = 2;
|
||||
@@ -57,6 +63,7 @@ public class TunnelCreateMessage extends I2NPMessageImpl {
|
||||
super(context);
|
||||
setParticipantType(-1);
|
||||
setNextRouter(null);
|
||||
setNextTunnelId(null);
|
||||
setTunnelId(null);
|
||||
setTunnelDurationSeconds(-1);
|
||||
setConfigurationKey(null);
|
||||
@@ -70,13 +77,18 @@ public class TunnelCreateMessage extends I2NPMessageImpl {
|
||||
setVerificationPrivateKey(null);
|
||||
setTunnelKey(null);
|
||||
setCertificate(null);
|
||||
setReplyBlock(null);
|
||||
setReplyTag(null);
|
||||
setReplyKey(null);
|
||||
setReplyTunnel(null);
|
||||
setReplyPeer(null);
|
||||
}
|
||||
|
||||
public void setParticipantType(int type) { _participantType = type; }
|
||||
public int getParticipantType() { return _participantType; }
|
||||
public void setNextRouter(Hash routerIdentityHash) { _nextRouter = routerIdentityHash; }
|
||||
public Hash getNextRouter() { return _nextRouter; }
|
||||
public void setNextTunnelId(TunnelId id) { _nextTunnelId = id; }
|
||||
public TunnelId getNextTunnelId() { return _nextTunnelId; }
|
||||
public void setTunnelId(TunnelId id) { _tunnelId = id; }
|
||||
public TunnelId getTunnelId() { return _tunnelId; }
|
||||
public void setTunnelDurationSeconds(long durationSeconds) { _tunnelDuration = durationSeconds; }
|
||||
@@ -103,8 +115,14 @@ public class TunnelCreateMessage extends I2NPMessageImpl {
|
||||
public TunnelSessionKey getTunnelKey() { return _tunnelKey; }
|
||||
public void setCertificate(Certificate cert) { _certificate = cert; }
|
||||
public Certificate getCertificate() { return _certificate; }
|
||||
public void setReplyBlock(SourceRouteBlock block) { _replyBlock = block; }
|
||||
public SourceRouteBlock getReplyBlock() { return _replyBlock; }
|
||||
public void setReplyTag(SessionTag tag) { _replyTag = tag; }
|
||||
public SessionTag getReplyTag() { return _replyTag; }
|
||||
public void setReplyKey(SessionKey key) { _replyKey = key; }
|
||||
public SessionKey getReplyKey() { return _replyKey; }
|
||||
public void setReplyTunnel(TunnelId id) { _replyTunnel = id; }
|
||||
public TunnelId getReplyTunnel() { return _replyTunnel; }
|
||||
public void setReplyPeer(Hash peer) { _replyPeer = peer; }
|
||||
public Hash getReplyPeer() { return _replyPeer; }
|
||||
|
||||
public void readMessage(InputStream in, int type) throws I2NPMessageException, IOException {
|
||||
if (type != MESSAGE_TYPE) throw new I2NPMessageException("Message type is incorrect for this message");
|
||||
@@ -113,6 +131,8 @@ public class TunnelCreateMessage extends I2NPMessageImpl {
|
||||
if (_participantType != PARTICIPANT_TYPE_ENDPOINT) {
|
||||
_nextRouter = new Hash();
|
||||
_nextRouter.readBytes(in);
|
||||
_nextTunnelId = new TunnelId();
|
||||
_nextTunnelId.readBytes(in);
|
||||
}
|
||||
_tunnelId = new TunnelId();
|
||||
_tunnelId.readBytes(in);
|
||||
@@ -140,8 +160,14 @@ public class TunnelCreateMessage extends I2NPMessageImpl {
|
||||
}
|
||||
_certificate = new Certificate();
|
||||
_certificate.readBytes(in);
|
||||
_replyBlock = new SourceRouteBlock();
|
||||
_replyBlock.readBytes(in);
|
||||
_replyTag = new SessionTag();
|
||||
_replyTag.readBytes(in);
|
||||
_replyKey = new SessionKey();
|
||||
_replyKey.readBytes(in);
|
||||
_replyTunnel = new TunnelId();
|
||||
_replyTunnel.readBytes(in);
|
||||
_replyPeer = new Hash();
|
||||
_replyPeer.readBytes(in);
|
||||
} catch (DataFormatException dfe) {
|
||||
throw new I2NPMessageException("Unable to load the message data", dfe);
|
||||
}
|
||||
@@ -153,6 +179,7 @@ public class TunnelCreateMessage extends I2NPMessageImpl {
|
||||
DataHelper.writeLong(os, 1, _participantType);
|
||||
if (_participantType != PARTICIPANT_TYPE_ENDPOINT) {
|
||||
_nextRouter.writeBytes(os);
|
||||
_nextTunnelId.writeBytes(os);
|
||||
}
|
||||
_tunnelId.writeBytes(os);
|
||||
DataHelper.writeLong(os, 4, _tunnelDuration);
|
||||
@@ -174,7 +201,10 @@ public class TunnelCreateMessage extends I2NPMessageImpl {
|
||||
_tunnelKey.writeBytes(os);
|
||||
}
|
||||
_certificate.writeBytes(os);
|
||||
_replyBlock.writeBytes(os);
|
||||
_replyTag.writeBytes(os);
|
||||
_replyKey.writeBytes(os);
|
||||
_replyTunnel.writeBytes(os);
|
||||
_replyPeer.writeBytes(os);
|
||||
} catch (Throwable t) {
|
||||
throw new I2NPMessageException("Error writing out the message data", t);
|
||||
}
|
||||
@@ -201,21 +231,23 @@ public class TunnelCreateMessage extends I2NPMessageImpl {
|
||||
|
||||
public int hashCode() {
|
||||
return (int)(DataHelper.hashCode(getCertificate()) +
|
||||
DataHelper.hashCode(getConfigurationKey()) +
|
||||
DataHelper.hashCode(getNextRouter()) +
|
||||
DataHelper.hashCode(getReplyBlock()) +
|
||||
DataHelper.hashCode(getTunnelId()) +
|
||||
DataHelper.hashCode(getTunnelKey()) +
|
||||
DataHelper.hashCode(getVerificationPrivateKey()) +
|
||||
DataHelper.hashCode(getVerificationPublicKey()) +
|
||||
(getIncludeDummyTraffic() ? 1 : 0) +
|
||||
getMaxAvgBytesPerMin() +
|
||||
getMaxAvgMessagesPerMin() +
|
||||
getMaxPeakBytesPerMin() +
|
||||
getMaxPeakMessagesPerMin() +
|
||||
getParticipantType() +
|
||||
(getReorderMessages() ? 1 : 0) +
|
||||
getTunnelDurationSeconds());
|
||||
DataHelper.hashCode(getConfigurationKey()) +
|
||||
DataHelper.hashCode(getNextRouter()) +
|
||||
DataHelper.hashCode(getNextTunnelId()) +
|
||||
DataHelper.hashCode(getReplyPeer()) +
|
||||
DataHelper.hashCode(getReplyTunnel()) +
|
||||
DataHelper.hashCode(getTunnelId()) +
|
||||
DataHelper.hashCode(getTunnelKey()) +
|
||||
DataHelper.hashCode(getVerificationPrivateKey()) +
|
||||
DataHelper.hashCode(getVerificationPublicKey()) +
|
||||
(getIncludeDummyTraffic() ? 1 : 0) +
|
||||
getMaxAvgBytesPerMin() +
|
||||
getMaxAvgMessagesPerMin() +
|
||||
getMaxPeakBytesPerMin() +
|
||||
getMaxPeakMessagesPerMin() +
|
||||
getParticipantType() +
|
||||
(getReorderMessages() ? 1 : 0) +
|
||||
getTunnelDurationSeconds());
|
||||
}
|
||||
|
||||
public boolean equals(Object object) {
|
||||
@@ -224,7 +256,11 @@ public class TunnelCreateMessage extends I2NPMessageImpl {
|
||||
return DataHelper.eq(getCertificate(), msg.getCertificate()) &&
|
||||
DataHelper.eq(getConfigurationKey(), msg.getConfigurationKey()) &&
|
||||
DataHelper.eq(getNextRouter(), msg.getNextRouter()) &&
|
||||
DataHelper.eq(getReplyBlock(), msg.getReplyBlock()) &&
|
||||
DataHelper.eq(getNextTunnelId(), msg.getNextTunnelId()) &&
|
||||
DataHelper.eq(getReplyTag(), msg.getReplyTag()) &&
|
||||
DataHelper.eq(getReplyKey(), msg.getReplyKey()) &&
|
||||
DataHelper.eq(getReplyTunnel(), msg.getReplyTunnel()) &&
|
||||
DataHelper.eq(getReplyPeer(), msg.getReplyPeer()) &&
|
||||
DataHelper.eq(getTunnelId(), msg.getTunnelId()) &&
|
||||
DataHelper.eq(getTunnelKey(), msg.getTunnelKey()) &&
|
||||
DataHelper.eq(getVerificationPrivateKey(), msg.getVerificationPrivateKey()) &&
|
||||
@@ -249,7 +285,11 @@ public class TunnelCreateMessage extends I2NPMessageImpl {
|
||||
buf.append("\n\tCertificate: ").append(getCertificate());
|
||||
buf.append("\n\tConfiguration Key: ").append(getConfigurationKey());
|
||||
buf.append("\n\tNext Router: ").append(getNextRouter());
|
||||
buf.append("\n\tReply Block: ").append(getReplyBlock());
|
||||
buf.append("\n\tNext Tunnel: ").append(getNextTunnelId());
|
||||
buf.append("\n\tReply Tag: ").append(getReplyTag());
|
||||
buf.append("\n\tReply Key: ").append(getReplyKey());
|
||||
buf.append("\n\tReply Tunnel: ").append(getReplyTunnel());
|
||||
buf.append("\n\tReply Peer: ").append(getReplyPeer());
|
||||
buf.append("\n\tTunnel ID: ").append(getTunnelId());
|
||||
buf.append("\n\tTunnel Key: ").append(getTunnelKey());
|
||||
buf.append("\n\tVerification Private Key: ").append(getVerificationPrivateKey());
|
||||
|
||||
Reference in New Issue
Block a user