package net.i2p.router.message;
/*
* 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.util.ArrayList;
import java.util.Date;
import java.util.List;
import net.i2p.data.Certificate;
import net.i2p.data.PublicKey;
import net.i2p.data.router.RouterInfo;
import net.i2p.data.i2np.DeliveryInstructions;
/**
* Define the contents of a garlic chunk that contains 1 or more sub garlics.
*
* This is the top-level config for a Garlic Message that contains cloves.
* For cloves themselves, see PayloadGarlicConfig.
* Note that this is somewhat misnamed as it contains the actual cloves, not just the config.
*/
class GarlicConfig {
private RouterInfo _recipient;
private PublicKey _recipientPublicKey;
private Certificate _cert;
private long _id;
private long _expiration;
private final List<GarlicConfig> _cloveConfigs;
private DeliveryInstructions _instructions;
// unused
//private boolean _requestAck;
//private RouterInfo _replyThroughRouter; // router through which any replies will be sent before delivery to us
//private DeliveryInstructions _replyInstructions; // how the message will be sent from the replyThroughRouter to us
// unused and undocumented
//private Certificate _replyBlockCertificate;
//private long _replyBlockMessageId;
//private long _replyBlockExpiration;
public GarlicConfig() {
this(new ArrayList<GarlicConfig>(4));
}
protected GarlicConfig(List<GarlicConfig> cloveConfigs) {
_id = -1;
_expiration = -1;
_cloveConfigs = cloveConfigs;
//_replyBlockMessageId = -1;
//_replyBlockExpiration = -1;
}
/**
* Router to receive and process this clove - the router that will open the
* delivery instructions and decide what to do process it locally as an I2NPMessage,
* forward it as an I2NPMessage to a router, forward it as an I2NPMessage to a Destination,
* or forward it as an I2NPMessage to a tunnel.
*
* Used only if recipient public key is not set.
*
*/
public void setRecipient(RouterInfo info) { _recipient = info; }
public RouterInfo getRecipient() { return _recipient; }
/**
* Public key of the router to receive and process this clove. This is useful
* for garlic routed messages encrypted to the router at the end of a tunnel,
* as their RouterIdentity is not known, but a PublicKey they handle is exposed
* via the LeaseSet
*
*/
public void setRecipientPublicKey(PublicKey recipientPublicKey) { _recipientPublicKey = recipientPublicKey; }
public PublicKey getRecipientPublicKey() { return _recipientPublicKey; }
/**
* Certificate for the getRecipient() to pay for their processing
*
*/
public void setCertificate(Certificate cert) { _cert = cert; }
public Certificate getCertificate() { return _cert; }
/**
* Unique ID of the clove
*
*/
public void setId(long id) { _id = id; }
public long getId() { return _id; }
/**
* Expiration of the clove, after which it should be dropped
*
*/
public void setExpiration(long expiration) { _expiration = expiration; }
public long getExpiration() { return _expiration; }
/**
* Specify how the I2NPMessage in the clove should be handled.
*
*/
public void setDeliveryInstructions(DeliveryInstructions instructions) { _instructions = instructions; }
public DeliveryInstructions getDeliveryInstructions() { return _instructions; }
/**
* If true, the recipient of this clove is requested to send a DeliveryStatusMessage
* back via the replyThroughRouter using the getId() value for the status' message Id.
* Since those reply blocks are good for one use only, this flag should only be set if
* no reply is expected.
*
*/
/****
public void setRequestAck(boolean request) { _requestAck = request; }
public boolean getRequestAck() { return _requestAck; }
****/
/**
* Specify the router through which a reply to this clove can be sent. The
* getReplyInstructions() are passed to this router during the reply process
* and it them uses those to send the reply to this router.
*
*/
/****
public void setReplyThroughRouter(RouterInfo replyThroughRouter) { _replyThroughRouter = replyThroughRouter; }
public RouterInfo getReplyThroughRouter() { return _replyThroughRouter; }
****/
/**
* Specify how any reply will be routed so that it reaches this router after being
* delivered to the getReplyThroughRouter. These instructions are not exposed to the
* router who receives this garlic message in cleartext - they are instead encrypted to
* the replyThrough router
*
*/
/****
public void setReplyInstructions(DeliveryInstructions instructions) { _replyInstructions = instructions; }
public DeliveryInstructions getReplyInstructions() { return _replyInstructions; }
****/
/****
public long getReplyBlockMessageId() { return _replyBlockMessageId; }
public void setReplyBlockMessageId(long id) { _replyBlockMessageId = id; }
public Certificate getReplyBlockCertificate() { return _replyBlockCertificate; }
public void setReplyBlockCertificate(Certificate cert) { _replyBlockCertificate = cert; }
public long getReplyBlockExpiration() { return _replyBlockExpiration; }
public void setReplyBlockExpiration(long expiration) { _replyBlockExpiration = expiration; }
****/
/**
* Add a clove to the current message - if any cloves are added, an I2NP message
* cannot be specified via setPayload. This means that the resulting GarlicClove
* represented by this GarlicConfig must be a GarlicMessage itself
*
*/
public void addClove(GarlicConfig config) {
if (config != null) {
_cloveConfigs.add(config);
}
}
public int getCloveCount() { return _cloveConfigs.size(); }
public GarlicConfig getClove(int index) { return _cloveConfigs.get(index); }
public void clearCloves() { _cloveConfigs.clear(); }
protected String getSubData() { return ""; }
private final static String NL = System.getProperty("line.separator");
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append("<garlicConfig>").append(NL);
buf.append("<certificate>").append(getCertificate()).append("</certificate>").append(NL);
buf.append("<instructions>").append(getDeliveryInstructions()).append("</instructions>").append(NL);
buf.append("<expiration>").append(new Date(getExpiration())).append("</expiration>").append(NL);
buf.append("<garlicId>").append(getId()).append("</garlicId>").append(NL);
buf.append("<recipient>").append(getRecipient()).append("</recipient>").append(NL);
buf.append("<recipientPublicKey>").append(getRecipientPublicKey()).append("</recipientPublicKey>").append(NL);
//buf.append("<replyBlockCertificate>").append(getReplyBlockCertificate()).append("</replyBlockCertificate>").append(NL);
//buf.append("<replyBlockExpiration>").append(new Date(getReplyBlockExpiration())).append("</replyBlockExpiration>").append(NL);
//buf.append("<replyBlockMessageId>").append(getReplyBlockMessageId()).append("</replyBlockMessageId>").append(NL);
//buf.append("<replyInstructions>").append(getReplyInstructions()).append("</replyInstructions>").append(NL);
//buf.append("<replyThroughRouter>").append(getReplyThroughRouter()).append("</replyThroughRouter>").append(NL);
//buf.append("<requestAck>").append(getRequestAck()).append("</requestAck>").append(NL);
buf.append(getSubData());
buf.append("<subcloves>").append(NL);
for (int i = 0; i < getCloveCount(); i++)
buf.append("<clove>").append(getClove(i)).append("</clove>").append(NL);
buf.append("</subcloves>").append(NL);
buf.append("</garlicConfig>").append(NL);
return buf.toString();
}
}