package net.i2p.router.message;
import java.util.HashSet;
import java.util.Set;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
import net.i2p.data.LeaseSet;
import net.i2p.data.Payload;
import net.i2p.data.TunnelId;
import net.i2p.router.ClientMessage;
import net.i2p.router.RouterContext;
/**
* Good ol' fashioned struct with the send status
*
*/
class OutboundClientMessageStatus {
private RouterContext _context;
private ClientMessage _msg;
private PayloadGarlicConfig _clove;
private LeaseSet _leaseSet;
private final Set<Tunnel> _sent;
private int _numLookups;
private boolean _success;
private boolean _failure;
private long _start;
private int _previousSent;
public OutboundClientMessageStatus(RouterContext ctx, ClientMessage msg) {
_context = ctx;
_msg = msg;
_clove = null;
_leaseSet = null;
_sent = new HashSet<Tunnel>(4);
_success = false;
_failure = false;
_numLookups = 0;
_previousSent = 0;
_start = ctx.clock().now();
}
/** raw payload */
public Payload getPayload() { return _msg.getPayload(); }
/** clove, if we've built it */
public PayloadGarlicConfig getClove() { return _clove; }
public void setClove(PayloadGarlicConfig clove) { _clove = clove; }
public ClientMessage getMessage() { return _msg; }
/** date we started the process on */
public long getStart() { return _start; }
public int getNumLookups() { return _numLookups; }
public void incrementLookups() { _numLookups++; }
public void clearAlreadySent() {
synchronized (_sent) {
_previousSent += _sent.size();
_sent.clear();
}
}
/** who sent the message? */
public Destination getFrom() { return _msg.getFromDestination(); }
/** who is the message going to? */
public Destination getTo() { return _msg.getDestination(); }
/** what is the target's current leaseSet (or null if we don't know yet) */
public LeaseSet getLeaseSet() { return _leaseSet; }
public void setLeaseSet(LeaseSet ls) { _leaseSet = ls; }
/** have we already sent the message down this tunnel? */
public boolean alreadySent(Hash gateway, TunnelId tunnelId) {
Tunnel t = new Tunnel(gateway, tunnelId);
synchronized (_sent) {
return _sent.contains(t);
}
}
public void sent(Hash gateway, TunnelId tunnelId) {
Tunnel t = new Tunnel(gateway, tunnelId);
synchronized (_sent) {
_sent.add(t);
}
}
/** how many messages have we sent through various leases? */
public int getNumSent() {
synchronized (_sent) {
return _sent.size() + _previousSent;
}
}
/** did we totally fail? */
public boolean getFailure() { return _failure; }
/** we failed. returns true if we had already failed before */
public boolean failed() {
boolean already = _failure;
_failure = true;
return already;
}
/** have we totally succeeded? */
public boolean getSuccess() { return _success; }
/** we succeeded. returns true if we had already succeeded before */
public boolean success() {
boolean already = _success;
_success = true;
return already;
}
/** represent a unique tunnel at any given time */
private class Tunnel {
private Hash _gateway;
private TunnelId _tunnel;
public Tunnel(Hash tunnelGateway, TunnelId tunnel) {
_gateway = tunnelGateway;
_tunnel = tunnel;
}
public Hash getGateway() { return _gateway; }
public TunnelId getTunnel() { return _tunnel; }
@Override
public int hashCode() {
int rv = 0;
if (_gateway != null)
rv += _gateway.hashCode();
if (_tunnel != null)
rv += 7*_tunnel.getTunnelId();
return rv;
}
@Override
public boolean equals(Object o) {
if (o == null) return false;
if (o.getClass() != Tunnel.class) return false;
Tunnel t = (Tunnel)o;
return (getTunnel() == t.getTunnel()) &&
getGateway().equals(t.getGateway());
}
}
}