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(); } }