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