package net.i2p.router.tunnel;
import net.i2p.data.DataHelper;
import net.i2p.data.Hash;
import net.i2p.data.SessionKey;
import net.i2p.data.TunnelId;
/**
* Defines the general configuration for a hop in a tunnel.
*
*/
public class HopConfig {
private byte _receiveTunnelId[];
private TunnelId _receiveTunnel;
private Hash _receiveFrom;
private byte _sendTunnelId[];
private TunnelId _sendTunnel;
private Hash _sendTo;
private SessionKey _layerKey;
private SessionKey _ivKey;
private SessionKey _replyKey;
private byte[] _replyIV;
private long _creation;
private long _expiration;
//private Map _options;
// these 4 were longs, let's save some space
// 2 billion * 1KB / 10 minutes = 3 GBps in a single tunnel
// we use synchronization instead of an AtomicInteger here to save space
private int _messagesProcessed;
private int _oldMessagesProcessed;
//private int _messagesSent;
//private int _oldMessagesSent;
/** IV length for {@link #getReplyIV} */
public static final int REPLY_IV_LENGTH = 16;
public HopConfig() {
_creation = -1;
_expiration = -1;
}
/** what tunnel ID are we receiving on? */
public byte[] getReceiveTunnelId() { return _receiveTunnelId; }
public TunnelId getReceiveTunnel() {
if (_receiveTunnel == null)
_receiveTunnel = getTunnel(_receiveTunnelId);
return _receiveTunnel;
}
public void setReceiveTunnelId(byte id[]) { _receiveTunnelId = id; }
public void setReceiveTunnelId(TunnelId id) { _receiveTunnelId = DataHelper.toLong(4, id.getTunnelId()); }
/** what is the previous peer in the tunnel (null if gateway) */
public Hash getReceiveFrom() { return _receiveFrom; }
public void setReceiveFrom(Hash from) { _receiveFrom = from; }
/** what is the next tunnel ID we are sending to? (null if endpoint) */
public byte[] getSendTunnelId() { return _sendTunnelId; }
/** what is the next tunnel we are sending to? (null if endpoint) */
public TunnelId getSendTunnel() {
if (_sendTunnel == null)
_sendTunnel = getTunnel(_sendTunnelId);
return _sendTunnel;
}
public void setSendTunnelId(byte id[]) { _sendTunnelId = id; }
private static TunnelId getTunnel(byte id[]) {
if (id == null)
return null;
else
return new TunnelId(DataHelper.fromLong(id, 0, id.length));
}
/** what is the next peer in the tunnel (null if endpoint) */
public Hash getSendTo() { return _sendTo; }
public void setSendTo(Hash to) { _sendTo = to; }
/** what key should we use to encrypt the layer before passing it on? */
public SessionKey getLayerKey() { return _layerKey; }
public void setLayerKey(SessionKey key) { _layerKey = key; }
/** what key should we use to encrypt the preIV before passing it on? */
public SessionKey getIVKey() { return _ivKey; }
public void setIVKey(SessionKey key) { _ivKey = key; }
/** key to encrypt the reply sent for the new tunnel creation crypto */
public SessionKey getReplyKey() { return _replyKey; }
public void setReplyKey(SessionKey key) { _replyKey = key; }
/**
* IV used to encrypt the reply sent for the new tunnel creation crypto
*
* @return 16 bytes
*/
public byte[] getReplyIV() { return _replyIV; }
/**
* IV used to encrypt the reply sent for the new tunnel creation crypto
*
* @throws IllegalArgumentException if not 16 bytes
*/
public void setReplyIV(byte[] iv) {
if (iv.length != REPLY_IV_LENGTH)
throw new IllegalArgumentException();
_replyIV = iv;
}
/** when does this tunnel expire (in ms since the epoch)? */
public long getExpiration() { return _expiration; }
public void setExpiration(long when) { _expiration = when; }
/** when was this tunnel created (in ms since the epoch)? */
public long getCreation() { return _creation; }
public void setCreation(long when) { _creation = when; }
/**
* what are the configuration options for this tunnel (if any). keys to
* this map should be strings and values should be Objects of an
* option-specific type (e.g. "maxMessages" would be an Integer, "shouldPad"
* would be a Boolean, etc).
*
*/
//public Map getOptions() { return _options; }
//public void setOptions(Map options) { _options = options; }
/**
* Take note of a message being pumped through this tunnel.
* "processed" is for incoming and "sent" is for outgoing (could be dropped in between)
* We use synchronization instead of an AtomicInteger here to save space.
*/
public synchronized void incrementProcessedMessages() { _messagesProcessed++; }
public synchronized int getProcessedMessagesCount() { return _messagesProcessed; }
/**
* This returns the number of processed messages since
* the last time getAndResetRecentMessagesCount() was called.
* As of 0.9.23, does NOT reset the count, see getAndResetRecentMessagesCount().
*/
public synchronized int getRecentMessagesCount() {
return _messagesProcessed - _oldMessagesProcessed;
}
/**
* This returns the number of processed messages since the last time this was called,
* and resets the count. It should only be called by code that updates the router stats.
* See TunnelDispatcher.updateParticipatingStats().
*
* @since 0.9.23
*/
synchronized int getAndResetRecentMessagesCount() {
int rv = _messagesProcessed - _oldMessagesProcessed;
_oldMessagesProcessed = _messagesProcessed;
return rv;
}
/**
* Take note of a message being pumped through this tunnel.
* "processed" is for incoming and "sent" is for outgoing (could be dropped in between)
*/
/****
public void incrementSentMessages() { _messagesSent++; }
public int getSentMessagesCount() { return _messagesSent; }
public int getRecentSentMessagesCount() {
int rv = _messagesSent - _oldMessagesSent;
_oldMessagesSent = _messagesSent;
return rv;
}
****/
/** */
@Override
public String toString() {
StringBuilder buf = new StringBuilder(64);
if (_receiveTunnelId != null) {
buf.append("recv on ");
buf.append(DataHelper.fromLong(_receiveTunnelId, 0, 4));
buf.append(' ');
}
if (_sendTo != null) {
buf.append("send to ").append(_sendTo.toBase64().substring(0,4)).append(":");
if (_sendTunnelId != null)
buf.append(DataHelper.fromLong(_sendTunnelId, 0, 4));
}
buf.append(" exp. ").append(TunnelCreatorConfig.format(_expiration));
int messagesProcessed = getProcessedMessagesCount();
if (messagesProcessed > 0)
buf.append(" used ").append(messagesProcessed).append("KB");
return buf.toString();
}
}