use of net.i2p.router.TunnelInfo in project i2p.i2p by i2p.
the class TunnelPoolManager method selectOutboundExploratoryTunnel.
/**
* Pick the outbound exploratory tunnel with the endpoint closest to the given hash.
* By using this instead of the random selectTunnel(),
* we force some locality in OBEP-IBGW connections to minimize
* those connections network-wide.
*
* @param closestTo non-null
* @return null if none
* @since 0.8.10
*/
public TunnelInfo selectOutboundExploratoryTunnel(Hash closestTo) {
TunnelInfo info = _outboundExploratory.selectTunnel(closestTo);
if (info == null) {
_outboundExploratory.buildFallback();
// still can be null, but probably not
info = _outboundExploratory.selectTunnel();
}
return info;
}
use of net.i2p.router.TunnelInfo in project i2p.i2p by i2p.
the class ClientPeerSelector method selectPeers.
/**
* Returns ENDPOINT FIRST, GATEWAY LAST!!!!
* In: us .. closest .. middle .. IBGW
* Out: OBGW .. middle .. closest .. us
*
* @return ordered list of Hash objects (one per peer) specifying what order
* they should appear in a tunnel (ENDPOINT FIRST). This includes
* the local router in the list. If there are no tunnels or peers
* to build through, and the settings reject 0 hop tunnels, this will
* return null.
*/
public List<Hash> selectPeers(TunnelPoolSettings settings) {
int length = getLength(settings);
if (length < 0)
return null;
if ((length == 0) && (settings.getLength() + settings.getLengthVariance() > 0))
return null;
List<Hash> rv;
boolean isInbound = settings.isInbound();
if (length > 0) {
// special cases
boolean v6Only = isIPv6Only();
boolean ntcpDisabled = isNTCPDisabled();
boolean ssuDisabled = isSSUDisabled();
boolean checkClosestHop = v6Only || ntcpDisabled || ssuDisabled;
boolean hidden = ctx.router().isHidden() || ctx.router().getRouterInfo().getAddressCount() <= 0;
boolean hiddenInbound = hidden && isInbound;
boolean hiddenOutbound = hidden && !isInbound;
if (shouldSelectExplicit(settings))
return selectExplicit(settings, length);
Set<Hash> exclude = getExclude(isInbound, false);
Set<Hash> matches = new HashSet<Hash>(length);
if (length == 1) {
// closest-hop restrictions
if (checkClosestHop) {
Set<Hash> moreExclude = getClosestHopExclude(isInbound);
if (moreExclude != null)
exclude.addAll(moreExclude);
}
if (hiddenInbound) {
// SANFP adds all not-connected to exclude, so make a copy
Set<Hash> SANFPExclude = new HashSet<Hash>(exclude);
ctx.profileOrganizer().selectActiveNotFailingPeers(1, SANFPExclude, matches);
}
if (matches.isEmpty()) {
// ANFP does not fall back to non-connected
ctx.profileOrganizer().selectFastPeers(length, exclude, matches, 0);
}
matches.remove(ctx.routerHash());
rv = new ArrayList<Hash>(matches);
} else {
// build a tunnel using 4 subtiers.
// For a 2-hop tunnel, the first hop comes from subtiers 0-1 and the last from subtiers 2-3.
// For a longer tunnels, the first hop comes from subtier 0, the middle from subtiers 2-3, and the last from subtier 1.
rv = new ArrayList<Hash>(length + 1);
Hash randomKey = settings.getRandomKey();
// OBEP or IB last hop
// group 0 or 1 if two hops, otherwise group 0
Set<Hash> lastHopExclude;
if (isInbound) {
// closest-hop restrictions
if (checkClosestHop) {
Set<Hash> moreExclude = getClosestHopExclude(false);
if (moreExclude != null) {
moreExclude.addAll(exclude);
lastHopExclude = moreExclude;
} else {
lastHopExclude = exclude;
}
} else {
lastHopExclude = exclude;
}
} else {
lastHopExclude = exclude;
}
if (hiddenInbound) {
// IB closest hop
if (log.shouldInfo())
log.info("CPS SANFP closest IB exclude " + lastHopExclude.size());
// SANFP adds all not-connected to exclude, so make a copy
Set<Hash> SANFPExclude = new HashSet<Hash>(lastHopExclude);
ctx.profileOrganizer().selectActiveNotFailingPeers(1, SANFPExclude, matches);
if (matches.isEmpty()) {
if (log.shouldInfo())
log.info("CPS SFP closest IB exclude " + lastHopExclude.size());
// ANFP does not fall back to non-connected
ctx.profileOrganizer().selectFastPeers(1, lastHopExclude, matches, randomKey, length == 2 ? SLICE_0_1 : SLICE_0);
}
} else if (hiddenOutbound) {
// OBEP
// check for hidden and outbound, and the paired (inbound) tunnel is zero-hop
// if so, we need the OBEP to be connected to us, so we get the build reply back
// This should be rare except at startup
TunnelManagerFacade tmf = ctx.tunnelManager();
TunnelPool tp = tmf.getInboundPool(settings.getDestination());
boolean pickFurthest;
if (tp != null) {
pickFurthest = true;
TunnelPoolSettings tps = tp.getSettings();
int len = tps.getLength();
if (len <= 0 || tps.getLengthOverride() == 0 || len + tps.getLengthVariance() <= 0) {
// leave it true
} else {
List<TunnelInfo> tunnels = tp.listTunnels();
if (!tunnels.isEmpty()) {
for (TunnelInfo ti : tp.listTunnels()) {
if (ti.getLength() > 1) {
pickFurthest = false;
break;
}
}
} else {
// no tunnels in the paired tunnel pool
// BuildRequester will be using exploratory
tp = tmf.getInboundExploratoryPool();
tps = tp.getSettings();
len = tps.getLength();
if (len <= 0 || tps.getLengthOverride() == 0 || len + tps.getLengthVariance() <= 0) {
// leave it true
} else {
tunnels = tp.listTunnels();
if (!tunnels.isEmpty()) {
for (TunnelInfo ti : tp.listTunnels()) {
if (ti.getLength() > 1) {
pickFurthest = false;
break;
}
}
}
}
}
}
} else {
// shouldn't happen
pickFurthest = false;
}
if (pickFurthest) {
if (log.shouldInfo())
log.info("CPS SANFP OBEP exclude " + lastHopExclude.size());
// SANFP adds all not-connected to exclude, so make a copy
Set<Hash> SANFPExclude = new HashSet<Hash>(lastHopExclude);
ctx.profileOrganizer().selectActiveNotFailingPeers(1, SANFPExclude, matches);
if (matches.isEmpty()) {
// ANFP does not fall back to non-connected
if (log.shouldInfo())
log.info("CPS SFP OBEP exclude " + lastHopExclude.size());
ctx.profileOrganizer().selectFastPeers(1, lastHopExclude, matches, randomKey, length == 2 ? SLICE_0_1 : SLICE_0);
}
} else {
ctx.profileOrganizer().selectFastPeers(1, lastHopExclude, matches, randomKey, length == 2 ? SLICE_0_1 : SLICE_0);
}
} else {
// TODO exclude IPv6-only at OBEP? Caught in checkTunnel() below
ctx.profileOrganizer().selectFastPeers(1, lastHopExclude, matches, randomKey, length == 2 ? SLICE_0_1 : SLICE_0);
}
matches.remove(ctx.routerHash());
exclude.addAll(matches);
rv.addAll(matches);
matches.clear();
if (length > 2) {
// middle hop(s)
// group 2 or 3
ctx.profileOrganizer().selectFastPeers(length - 2, exclude, matches, randomKey, SLICE_2_3);
matches.remove(ctx.routerHash());
if (matches.size() > 1) {
// order the middle peers for tunnels >= 4 hops
List<Hash> ordered = new ArrayList<Hash>(matches);
orderPeers(ordered, randomKey);
rv.addAll(ordered);
} else {
rv.addAll(matches);
}
exclude.addAll(matches);
matches.clear();
}
// group 2 or 3 if two hops, otherwise group 1
if (!isInbound) {
// closest-hop restrictions
if (checkClosestHop) {
Set<Hash> moreExclude = getClosestHopExclude(true);
if (moreExclude != null)
exclude.addAll(moreExclude);
}
}
// TODO exclude IPv6-only at IBGW? Caught in checkTunnel() below
ctx.profileOrganizer().selectFastPeers(1, exclude, matches, randomKey, length == 2 ? SLICE_2_3 : SLICE_1);
matches.remove(ctx.routerHash());
rv.addAll(matches);
}
} else {
rv = new ArrayList<Hash>(1);
}
// log.debug("EPS result: " + DataHelper.toString(rv));
if (isInbound)
rv.add(0, ctx.routerHash());
else
rv.add(ctx.routerHash());
if (rv.size() > 1) {
if (!checkTunnel(isInbound, rv))
rv = null;
}
return rv;
}
use of net.i2p.router.TunnelInfo in project i2p.i2p by i2p.
the class SearchJob method resend.
/**
* Resend the leaseSet to the peer who had previously failed to
* provide us with the data when we asked them.
*/
private boolean resend(RouterInfo toPeer, LeaseSet ls) {
Hash to = toPeer.getIdentity().getHash();
DatabaseStoreMessage msg = new DatabaseStoreMessage(getContext());
msg.setEntry(ls);
msg.setMessageExpiration(getContext().clock().now() + RESEND_TIMEOUT);
TunnelInfo outTunnel = getContext().tunnelManager().selectOutboundExploratoryTunnel(to);
if (outTunnel != null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("resending leaseSet out to " + to + " through " + outTunnel + ": " + msg);
// TODO pass a priority to the dispatcher
getContext().tunnelDispatcher().dispatchOutbound(msg, outTunnel.getSendTunnelId(0), null, to);
return true;
} else {
if (_log.shouldLog(Log.WARN))
_log.warn("unable to resend a leaseSet - no outbound exploratory tunnels!");
return false;
}
}
use of net.i2p.router.TunnelInfo in project i2p.i2p by i2p.
the class SearchJob method sendLeaseSearch.
/**
* we're (probably) searching for a LeaseSet, so to be (overly) cautious, we're sending
* the request out through a tunnel w/ reply back through another tunnel.
*/
protected void sendLeaseSearch(RouterInfo router) {
Hash to = router.getIdentity().getHash();
TunnelInfo inTunnel = getContext().tunnelManager().selectInboundExploratoryTunnel(to);
if (inTunnel == null) {
_log.warn("No tunnels to get search replies through!");
getContext().jobQueue().addJob(new FailedJob(getContext(), router));
return;
}
TunnelId inTunnelId = inTunnel.getReceiveTunnelId(0);
// this will fail if we've banlisted our inbound gateway, but the gw may not necessarily
// be banlisted by whomever needs to contact them, so we don't need to check this
// RouterInfo inGateway = getContext().netDb().lookupRouterInfoLocally(inTunnel.getPeer(0));
// if (inGateway == null) {
// _log.error("We can't find the gateway to our inbound tunnel?!");
// getContext().jobQueue().addJob(new FailedJob(getContext(), router));
// return;
// }
int timeout = getPerPeerTimeoutMs(to);
long expiration = getContext().clock().now() + timeout;
I2NPMessage msg = buildMessage(inTunnelId, inTunnel.getPeer(0), expiration, router);
if (msg == null) {
getContext().jobQueue().addJob(new FailedJob(getContext(), router));
return;
}
TunnelInfo outTunnel = getContext().tunnelManager().selectOutboundExploratoryTunnel(to);
if (outTunnel == null) {
_log.warn("No tunnels to send search out through! Impossible?");
getContext().jobQueue().addJob(new FailedJob(getContext(), router));
return;
}
TunnelId outTunnelId = outTunnel.getSendTunnelId(0);
if (_log.shouldLog(Log.DEBUG))
_log.debug(getJobId() + ": Sending search to " + to + " for " + getState().getTarget() + " w/ replies through " + inTunnel.getPeer(0) + " via tunnel " + inTunnelId);
SearchMessageSelector sel = new SearchMessageSelector(getContext(), router, _expiration, _state);
SearchUpdateReplyFoundJob reply = new SearchUpdateReplyFoundJob(getContext(), router, _state, _facade, this, outTunnel, inTunnel);
if (FloodfillNetworkDatabaseFacade.isFloodfill(router))
_floodfillSearchesOutstanding++;
getContext().messageRegistry().registerPending(sel, reply, new FailedJob(getContext(), router));
// TODO pass a priority to the dispatcher
getContext().tunnelDispatcher().dispatchOutbound(msg, outTunnelId, to);
}
use of net.i2p.router.TunnelInfo in project i2p.i2p by i2p.
the class SingleSearchJob method runJob.
@Override
public void runJob() {
_onm = getContext().messageRegistry().registerPending(_replySelector, _onReply, _onTimeout);
DatabaseLookupMessage dlm = new DatabaseLookupMessage(getContext(), true);
TunnelInfo replyTunnel = getContext().tunnelManager().selectInboundExploratoryTunnel(_to);
TunnelInfo outTunnel = getContext().tunnelManager().selectOutboundExploratoryTunnel(_to);
if ((replyTunnel == null) || (outTunnel == null)) {
failed();
return;
}
dlm.setFrom(replyTunnel.getPeer(0));
dlm.setMessageExpiration(getContext().clock().now() + 5 * 1000);
dlm.setReplyTunnel(replyTunnel.getReceiveTunnelId(0));
dlm.setSearchKey(_key);
dlm.setSearchType(DatabaseLookupMessage.Type.RI);
if (_log.shouldLog(Log.INFO))
_log.info(getJobId() + ": Single search for " + _key + " to " + _to);
getContext().tunnelDispatcher().dispatchOutbound(dlm, outTunnel.getSendTunnelId(0), _to);
_lookupsRemaining.set(1);
}
Aggregations