Files
i2p.itoopie/router/java/src/net/i2p/data/i2np/TunnelMessage.java

148 lines
6.4 KiB
Java
Raw Normal View History

2004-04-08 04:41:54 +00:00
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
2004-04-08 04:41:54 +00:00
* your children, but it might. Use at your own risk.
*
*/
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper;
import net.i2p.data.TunnelId;
import net.i2p.util.Log;
import net.i2p.I2PAppContext;
2004-04-08 04:41:54 +00:00
/**
* Defines the message sent between routers for tunnel delivery
*
* @author jrandom
*/
public class TunnelMessage extends I2NPMessageImpl {
private final static Log _log = new Log(TunnelMessage.class);
public final static int MESSAGE_TYPE = 8;
private TunnelId _tunnelId;
private long _size;
private byte[] _data;
private TunnelVerificationStructure _verification;
private byte[] _encryptedInstructions;
private final static int FLAG_INCLUDESTRUCTURE = 0;
private final static int FLAG_DONT_INCLUDESTRUCTURE = 1;
public TunnelMessage(I2PAppContext context) {
super(context);
setTunnelId(null);
setData(null);
setVerificationStructure(null);
setEncryptedDeliveryInstructions(null);
2004-04-08 04:41:54 +00:00
}
public TunnelId getTunnelId() { return _tunnelId; }
public void setTunnelId(TunnelId id) { _tunnelId = id; }
public byte[] getData() { return _data; }
public void setData(byte data[]) { _data = data; }
public TunnelVerificationStructure getVerificationStructure() { return _verification; }
public void setVerificationStructure(TunnelVerificationStructure verification) { _verification = verification; }
public byte[] getEncryptedDeliveryInstructions() { return _encryptedInstructions; }
public void setEncryptedDeliveryInstructions(byte instructions[]) { _encryptedInstructions = instructions; }
public void readMessage(InputStream in, int type) throws I2NPMessageException, IOException {
if (type != MESSAGE_TYPE) throw new I2NPMessageException("Message type is incorrect for this message");
2004-04-08 04:41:54 +00:00
try {
_tunnelId = new TunnelId();
_tunnelId.readBytes(in);
_log.debug("Read tunnel message for tunnel " + _tunnelId);
_size = DataHelper.readLong(in, 4);
_log.debug("Read tunnel message size: " + _size);
if (_size < 0) throw new I2NPMessageException("Invalid size in the structure: " + _size);
_data = new byte[(int)_size];
int read = read(in, _data);
if (read != _size)
throw new I2NPMessageException("Incorrect number of bytes read (" + read + ", expected " + _size);
int includeVerification = (int)DataHelper.readLong(in, 1);
if (includeVerification == FLAG_INCLUDESTRUCTURE) {
_verification = new TunnelVerificationStructure();
_verification.readBytes(in);
int len = (int)DataHelper.readLong(in, 2);
_encryptedInstructions = new byte[len];
read = read(in, _encryptedInstructions);
if (read != len)
throw new I2NPMessageException("Incorrect number of bytes read for instructions (" + read + ", expected " + len + ")");
}
2004-04-08 04:41:54 +00:00
} catch (DataFormatException dfe) {
throw new I2NPMessageException("Unable to load the message data", dfe);
}
}
protected byte[] writeMessage() throws I2NPMessageException, IOException {
if ( (_tunnelId == null) || (_data == null) || (_data.length <= 0) )
throw new I2NPMessageException("Not enough data to write out");
2004-04-08 04:41:54 +00:00
ByteArrayOutputStream os = new ByteArrayOutputStream(32);
try {
_tunnelId.writeBytes(os);
_log.debug("Writing tunnel message for tunnel " + _tunnelId);
DataHelper.writeLong(os, 4, _data.length);
_log.debug("Writing tunnel message length: " + _data.length);
os.write(_data);
_log.debug("Writing tunnel message data");
if ( (_verification == null) || (_encryptedInstructions == null) ) {
DataHelper.writeLong(os, 1, FLAG_DONT_INCLUDESTRUCTURE);
_log.debug("Writing DontIncludeStructure flag");
} else {
DataHelper.writeLong(os, 1, FLAG_INCLUDESTRUCTURE);
_log.debug("Writing IncludeStructure flag, then the verification structure, then the E(instr).length [" + _encryptedInstructions.length + "], then the E(instr)");
_verification.writeBytes(os);
DataHelper.writeLong(os, 2, _encryptedInstructions.length);
os.write(_encryptedInstructions);
}
2004-04-08 04:41:54 +00:00
} catch (DataFormatException dfe) {
throw new I2NPMessageException("Error writing out the message data", dfe);
}
byte rv[] = os.toByteArray();
_log.debug("Overall data being written: " + rv.length);
2004-04-08 04:41:54 +00:00
return rv;
}
public int getType() { return MESSAGE_TYPE; }
public int hashCode() {
return DataHelper.hashCode(getTunnelId()) +
DataHelper.hashCode(_data) +
DataHelper.hashCode(getVerificationStructure()) +
DataHelper.hashCode(getEncryptedDeliveryInstructions());
2004-04-08 04:41:54 +00:00
}
public boolean equals(Object object) {
if ( (object != null) && (object instanceof TunnelMessage) ) {
TunnelMessage msg = (TunnelMessage)object;
return DataHelper.eq(getTunnelId(),msg.getTunnelId()) &&
DataHelper.eq(getVerificationStructure(),msg.getVerificationStructure()) &&
DataHelper.eq(getData(),msg.getData()) &&
DataHelper.eq(getEncryptedDeliveryInstructions(), msg.getEncryptedDeliveryInstructions());
2004-04-08 04:41:54 +00:00
} else {
return false;
}
}
public String toString() {
2004-04-08 04:41:54 +00:00
StringBuffer buf = new StringBuffer();
buf.append("[TunnelMessage: ");
buf.append("\n\tTunnel ID: ").append(getTunnelId());
buf.append("\n\tVerification Structure: ").append(getVerificationStructure());
buf.append("\n\tEncrypted Instructions: ").append(getEncryptedDeliveryInstructions());
buf.append("\n\tData size: ").append(getData().length);
buf.append("]");
return buf.toString();
}
}